+ fwrite( $output, $this->getCategoriesUpdate( $dbr, $deleteUrls, $pages, "Edits" ) );
+ }
+ }
+
+ /**
+ * Handles categorization changes
+ * @param IDatabase $dbr
+ * @param resource $output
+ */
+ public function handleCategorization( IDatabase $dbr, $output ) {
+ $processedTitle = [];
+ // Categorization change can add new parents and change counts
+ // for the parent category.
+ foreach ( $this->getChangedCatsIterator( $dbr, RC_CATEGORIZE ) as $batch ) {
+ /*
+ * Note that on categorization event, cur_id points to
+ * the child page, not the parent category!
+ * So we need to have a two-stage process, since we have ID from one
+ * category and title from another, and we need both for proper updates.
+ * TODO: For now, we do full update even though some data hasn't changed,
+ * e.g. parents for parent cat and counts for child cat.
+ */
+ foreach ( $batch as $row ) {
+ $childPages[$row->rc_cur_id] = true;
+ $parentCats[$row->rc_title] = true;
+ }
+
+ $joinConditions = [
+ 'page_props' => [
+ 'LEFT JOIN',
+ [ 'pp_propname' => 'hiddencat', 'pp_page = page_id' ],
+ ],
+ 'category' => [
+ 'LEFT JOIN',
+ [ 'cat_title = page_title' ],
+ ],
+ ];
+
+ $pages = [];
+ $deleteUrls = [];
+
+ if ( !empty( $childPages ) ) {
+ // Load child rows by ID
+ $childRows = $dbr->select(
+ [ 'page', 'page_props', 'category' ],
+ [
+ 'page_id',
+ 'rc_title' => 'page_title',
+ 'pp_propname',
+ 'cat_pages',
+ 'cat_subcats',
+ 'cat_files',
+ ],
+ [ 'page_namespace' => NS_CATEGORY, 'page_id' => array_keys( $childPages ) ],
+ __METHOD__,
+ [],
+ $joinConditions
+ );
+ foreach ( $childRows as $row ) {
+ if ( isset( $this->processed[$row->page_id] ) ) {
+ // We already captured this one before
+ continue;
+ }
+ $this->writeCategoryData( $row );
+ $deleteUrls[] = '<' . $this->categoriesRdf->labelToUrl( $row->rc_title ) . '>';
+ $this->processed[$row->page_id] = true;
+ }
+ }
+
+ if ( !empty( $parentCats ) ) {
+ // Load parent rows by title
+ $joinConditions = [
+ 'page' => [
+ 'LEFT JOIN',
+ [ 'page_title = cat_title', 'page_namespace' => NS_CATEGORY ],
+ ],
+ 'page_props' => [
+ 'LEFT JOIN',
+ [ 'pp_propname' => 'hiddencat', 'pp_page = page_id' ],
+ ],
+ ];
+
+ $parentRows = $dbr->select(
+ [ 'category', 'page', 'page_props' ],
+ [
+ 'page_id',
+ 'rc_title' => 'cat_title',
+ 'pp_propname',
+ 'cat_pages',
+ 'cat_subcats',
+ 'cat_files',
+ ],
+ [ 'cat_title' => array_keys( $parentCats ) ],
+ __METHOD__,
+ [],
+ $joinConditions
+ );
+ foreach ( $parentRows as $row ) {
+ if ( $row->page_id && isset( $this->processed[$row->page_id] ) ) {
+ // We already captured this one before
+ continue;
+ }
+ if ( isset( $processedTitle[$row->rc_title] ) ) {
+ // We already captured this one before
+ continue;
+ }
+ $this->writeCategoryData( $row );
+ $deleteUrls[] = '<' . $this->categoriesRdf->labelToUrl( $row->rc_title ) . '>';
+ if ( $row->page_id ) {
+ $this->processed[$row->page_id] = true;
+ }
+ $processedTitle[$row->rc_title] = true;
+ }
+ }
+