association-1.0.0-alpha2/modules/association_menu/association_menu.install
modules/association_menu/association_menu.install
<?php /** * @file * Installation file for the association_menu module. */ use Drupal\association_menu\AssociationMenuStorageInterface; use Drupal\association_menu\Utility\MenuTreeHelper; /** * Implements hook_schema(). */ function association_menu_schema() { $schema = []; $schema[AssociationMenuStorageInterface::TABLE_NAME] = [ 'description' => '', 'fields' => [ 'id' => [ 'type' => 'serial', 'not null' => TRUE, 'description' => 'The unique identifier for menu items.', ], 'association' => [ 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'description' => 'The entity association owning this content.', ], 'enabled' => [ 'type' => 'int', 'size' => 'tiny', 'not null' => TRUE, 'default' => 1, ], 'expanded' => [ 'type' => 'int', 'size' => 'tiny', 'not null' => TRUE, 'default' => 1, ], 'parent' => [ 'type' => 'int', 'unsigned' => TRUE, 'description' => 'ID of the parent menu item.', 'default' => 0, ], 'depth' => [ 'type' => 'int', 'size' => 'medium', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, ], 'weight' => [ 'type' => 'int', 'not null' => TRUE, 'default' => 0, 'description' => 'A value to use for sorting menu items', ], 'title' => [ 'type' => 'blob', 'not null' => FALSE, 'serialize' => TRUE, ], 'entity' => [ 'type' => 'varchar', 'length' => 64, 'description' => 'The association link or page identifier.', ], 'route' => [ 'type' => 'blob', 'size' => 'big', 'serialize' => TRUE, 'description' => 'The route name and parameters for the route.', ], 'uri' => [ 'type' => 'varchar', 'length' => 255, 'description' => 'URI of to build the menu item link from.', ], 'options' => [ 'type' => 'blob', 'size' => 'big', 'serialize' => TRUE, 'description' => 'Link options for the menu item.', ], ], 'primary key' => ['id'], 'indexes' => [ 'associated' => ['association', 'entity'], 'association' => ['association', 'enabled', 'depth', 'parent', 'weight'], ], 'foreign keys' => [ 'association_link' => [ 'table' => 'association_link', 'columns' => ['link' => 'id'], ], ], ]; return $schema; } /** * Convert all PHP serialize menu data into JSON format and add depth field. * * For code safety and performance, using JSON serialization has become * recommended over the PHP object serialization. Convert existing menu item * data into JSON storage. */ function association_menu_update_9101(&$sandbox) { $db = \Drupal::database(); $json = \Drupal::service('serialization.json'); $menu_table = AssociationMenuStorageInterface::TABLE_NAME; if (!isset($sandbox['progress'])) { $schema = $db->schema(); // Drop this index so we can recreate it with the depth field. $schema->dropIndex($menu_table, 'association'); $schema->addField($menu_table, 'depth', [ 'type' => 'int', 'size' => 'medium', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, ]); // Add the "by association" index back in on the table. $schema->addIndex( $menu_table, 'association', ['association', 'enabled', 'depth', 'parent', 'weight'], [ 'fields' => [ 'association' => [ 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'description' => 'The entity association owning this content.', ], 'enabled' => [ 'type' => 'int', 'size' => 'tiny', 'not null' => TRUE, 'default' => 1, ], 'parent' => [ 'type' => 'int', 'unsigned' => TRUE, 'description' => 'ID of the parent menu item.', 'default' => 0, ], 'depth' => [ 'type' => 'int', 'size' => 'medium', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, ], 'weight' => [ 'type' => 'int', 'not null' => TRUE, 'default' => 0, 'description' => 'A value to use for sorting menu items', ], ], ] ); // Populate the Drupal sandbox batch tracking values. $countQuery = $db->select($menu_table)->countQuery(); $sandbox['total'] = $countQuery->execute()->fetchField(); $sandbox['current'] = 0; $sandbox['progress'] = 0; } $items = $db ->select($menu_table, 'nav') ->fields('nav', ['id', 'route', 'options']) ->condition('id', $sandbox['current'], '>') ->range(0, 100) ->orderBy('id', 'ASC') ->execute() ->fetchAll(); if ($items) { foreach ($items as $data) { $options = !empty($data->options) ? unserialize($data->options, ['allowed_classes' => FALSE]) : []; $updates = [ 'options' => $json->encode($options), 'depth' => 0, ]; if (!empty($data->route)) { $route = unserialize($data->route, ['allowed_classes' => FALSE]); if ($route) { $updates['route'] = $json->encode($route); } } $db->update($menu_table) ->fields($updates) ->condition('id', $data->id) ->execute(); $sandbox['current'] = $data->id; ++$sandbox['progress']; } if ($sandbox['progress'] < $sandbox['total']) { $sandbox['#finished'] = $sandbox['progress'] / $sandbox['total']; } } } /** * Calculate and populate values for the newly added menu item depth. */ function association_menu_update_9102(&$sandbox) { $db = \Drupal::database(); $assoc_table = \Drupal::entityDefinitionUpdateManager() ->getEntityType('association') ->getBaseTable(); if (!isset($sandbox['progress'])) { $count_query = $db->select($assoc_table)->countQuery(); $sandbox['total'] = $count_query->execute()->fetchField(); $sandbox['current'] = 0; $sandbox['progress'] = 0; } $assoc_ids = $db ->select($assoc_table, 'assoc') ->fields('assoc', ['id']) ->condition('id', $sandbox['current'], '>') ->orderBy('id', 'ASC') ->range(0, 25) ->execute() ->fetchCol(); if ($assoc_ids) { $processed = 0; $assoc_id = reset($assoc_ids); while ($assoc_id && $processed <= 50) { $items = $db ->select('association_menu_items', 'items') ->fields('items', ['id', 'parent']) ->condition('association', $assoc_id) ->orderBy('parent', 'ASC') ->execute() ->fetchAllAssoc('id', PDO::FETCH_ASSOC); foreach ($items as $id => &$item) { // If not already found, compute a depth value. // No values were loaded from the DB for depth, since the default // value would set these all to 0, which could be wrong. if (!isset($item['depth'])) { MenuTreeHelper::setItemDepth($items, $item); } $db ->update('association_menu_items') ->fields(['depth' => $item['depth']]) ->condition('id', $id) ->execute(); ++$processed; } unset($item); ++$sandbox['progress']; $sandbox['current'] = $assoc_id; $assoc_id = next($assoc_ids); } if ($sandbox['progress'] < $sandbox['total']) { $sandbox['#finished'] = $sandbox['progress'] / $sandbox['total']; } } }