Skip to content
This is documentation for version 1.X.X, which may no longer be maintained. Go to the latest version (2.2).

Moving from 1x to 2 0


title: Moving from 1.x to 2.0 description: What 2.0.0 changed for 1.x installations: table prefixes, one collation, merged forum tables, removed classes and the upgrade steps.

2.0.0 (16 September 2026) is a major release because it renames tables and removes classes: a third-party module that names either stops working until it is updated.

Back up first

The schema migration is not reversible. It renames 31 tables, folds four into two and converts every table's collation; undoing the merges would mean inventing votes nobody cast. Rolling back means restoring the backup.

The upgrade runs the migration for you. It took about 1.5 seconds against a 2,100-row database; a site with a large forum should expect the collation pass to take proportionally longer.

One prefix, everywhere

Nine core tables predated the cp_ convention (users, nodes, assets, menus, menu_items, node_field_index, url_aliases, node_category, node_tag) and modules used whatever prefix their author picked. The rule is now: core tables are cp_<noun>, module tables are cp_<module>_<noun>. So users is cp_users and forum_posts is cp_forum_posts. doctrine_migration_versions and messenger_messages keep their names because Doctrine and Symfony Messenger hardcode them.

One collation

The database carried three collations; joining a varchar across them raises Illegal mix of collations. Everything is now utf8mb4_unicode_ci, already used by 56 of the 66 tables and accepted by MySQL 8 and MariaDB 11.

Likes and dislikes are one table

forum_post_likes and forum_post_dislikes become cp_forum_post_votes, with the verdict stored as +1 or -1. UNIQUE(post_id, user_id) makes it impossible for a member to hold both a like and a dislike on one post, which two concurrent requests could previously produce. Existing votes are carried over; a member who held both keeps the last one cast.

Thread read state and watches are one row

forum_topic_views and forum_topic_watches become cp_forum_topic_user_state, with last_seen_at and watching_since as two nullable columns. Unwatching clears a column instead of deleting a row, so it no longer loses where you had read up to.

Removed classes

  • Modules\Forum\Entity\ForumPostLike and ForumPostDislike: use ForumPostVote with ForumPostVote::LIKE / ::DISLIKE.
  • Modules\Forum\Entity\ForumTopicView and ForumTopicWatch: use ForumTopicUserState.
  • ForumPostLikeRepository, ForumPostDislikeRepository, ForumTopicViewRepository, ForumTopicWatchRepository: use ForumPostVoteRepository and ForumTopicUserStateRepository.

The domain events ForumPostLikedEvent and ForumPostDislikedEvent are unchanged.

Upgrade steps

  1. Take a database backup.
  2. Apply the update from AACP → Updates. Migrations run first, then update hooks, then the cache rebuild.
  3. If you apply by FTP on shared hosting, empty cp-core/var/cache/prod/ afterwards and clear the Doctrine cache pools. From the update that lands this release onwards, the updater does it itself.
  4. Check any module you did not get from us for the removed classes.

Fixes that came with it

Doctrine's query cache is cleared after an update; module schema files are back in the repository (Whitepaper's tables could not be created from a clean clone); the forum presence table no longer breaks a fresh module install; a post-auth SSRF in the performance probe is closed by pinning the scheme to HTTP and HTTPS; and a path sanitiser that could manufacture the traversal it removed was fixed.

Known limit

doctrine:schema:validate still reports 81 lines of drift on an upgraded database, none introduced here: MariaDB representing JSON columns as longtext, hand-named indexes, and three tables driven by raw SQL with no entity.

Last updated: 16.10.2026