commit 34b1737bccd192772a5a5a3839d287d6d7f4dc82 Author: fago Date: Sun Jun 1 13:36:43 2014 -0500 Removed Tables hack by implementing the sql storage interface for menu links. diff --git a/core/includes/schema.inc b/core/includes/schema.inc index a386e62..ade770c 100644 --- a/core/includes/schema.inc +++ b/core/includes/schema.inc @@ -358,18 +358,23 @@ function drupal_schema_fields_sql($table, $prefix = NULL) { * If this is an update, this argument specifies the primary keys' field * names. If there is only 1 field in the key, you may pass in a string; if * there are multiple fields in the key, pass in an array. + * @param array|null $schema + * (optional) The table schema to use. If not given, it is retrieved via + * drupal_get_schema(). Defaults to NULL. * * @return bool|int * If the record insert or update failed, returns FALSE. If it succeeded, * returns SAVED_NEW or SAVED_UPDATED, depending on the operation performed. */ -function drupal_write_record($table, &$record, $primary_keys = array()) { +function drupal_write_record($table, &$record, $primary_keys = array(), $schema = NULL) { // Standardize $primary_keys to an array. if (is_string($primary_keys)) { $primary_keys = array($primary_keys); } - $schema = drupal_get_schema($table); + if (!isset($schema)) { + $schema = drupal_get_schema($table); + } if (empty($schema)) { return FALSE; } diff --git a/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php b/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php index 54664d1..a4e3d88 100644 --- a/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php +++ b/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php @@ -259,15 +259,7 @@ protected function addJoin($type, $table, $join_condition, $langcode) { */ protected function getTableMapping($table, $entity_type_id) { $storage = $this->entityManager->getStorage($entity_type_id); - // @todo Stop calling drupal_get_schema() once menu links are converted - // to the Entity Field API. See https://drupal.org/node/1842858. - $schema = drupal_get_schema($table); - if (!$schema && $storage instanceof SqlEntityStorageInterface) { - $mapping = $storage->getTableMapping()->getAllColumns($table); - } - else { - $mapping = array_keys($schema['fields']); - } + $mapping = $storage->getTableMapping()->getAllColumns($table); return array_flip($mapping); } diff --git a/core/modules/menu_link/menu_link.install b/core/modules/menu_link/menu_link.install deleted file mode 100644 index c789d34..0000000 --- a/core/modules/menu_link/menu_link.install +++ /dev/null @@ -1,221 +0,0 @@ - 'Contains the individual links within a menu.', - 'fields' => array( - 'menu_name' => array( - 'description' => "The menu name. All links with the same menu name (such as 'tools') are part of the same menu.", - 'type' => 'varchar', - 'length' => 32, - 'not null' => TRUE, - 'default' => '', - ), - 'mlid' => array( - 'description' => 'The menu link ID (mlid) is the integer primary key.', - 'type' => 'serial', - 'unsigned' => TRUE, - 'not null' => TRUE, - ), - 'uuid' => array( - 'description' => 'Unique Key: Universally unique identifier for this entity.', - 'type' => 'varchar', - 'length' => 128, - 'not null' => FALSE, - ), - 'machine_name' => array( - 'description' => 'Unique machine name: Optional human-readable ID for this link.', - 'type' => 'varchar', - 'length' => 255, - 'not null' => FALSE, - ), - 'plid' => array( - 'description' => 'The parent link ID (plid) is the mlid of the link above in the hierarchy, or zero if the link is at the top level in its menu.', - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => TRUE, - 'default' => 0, - ), - 'link_path' => array( - 'description' => 'The Drupal path or external path this link points to.', - 'type' => 'varchar', - 'length' => 255, - 'not null' => TRUE, - 'default' => '', - ), - 'langcode' => array( - 'description' => 'The {language}.langcode of this link.', - 'type' => 'varchar', - 'length' => 12, - 'not null' => TRUE, - 'default' => '', - ), - 'link_title' => array( - 'description' => 'The text displayed for the link.', - 'type' => 'varchar', - 'length' => 255, - 'not null' => TRUE, - 'default' => '', - ), - 'options' => array( - 'description' => 'A serialized array of options to be passed to the url() or l() function, such as a query string or HTML attributes.', - 'type' => 'blob', - 'not null' => FALSE, - 'serialize' => TRUE, - ), - 'module' => array( - 'description' => 'The name of the module that generated this link.', - 'type' => 'varchar', - 'length' => DRUPAL_EXTENSION_NAME_MAX_LENGTH, - 'not null' => TRUE, - 'default' => 'system', - ), - 'hidden' => array( - 'description' => 'A flag for whether the link should be rendered in menus. (1 = a disabled menu item that may be shown on admin screens, -1 = a menu callback, 0 = a normal, visible link)', - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - 'size' => 'small', - ), - 'external' => array( - 'description' => 'A flag to indicate if the link points to a full URL starting with a protocol, like http:// (1 = external, 0 = internal).', - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - 'size' => 'small', - ), - 'has_children' => array( - 'description' => 'Flag indicating whether any links have this link as a parent (1 = children exist, 0 = no children).', - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - 'size' => 'small', - ), - 'expanded' => array( - 'description' => 'Flag for whether this link should be rendered as expanded in menus - expanded links always have their child links displayed, instead of only when the link is in the active trail (1 = expanded, 0 = not expanded)', - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - 'size' => 'small', - ), - 'weight' => array( - 'description' => 'Link weight among links in the same menu at the same depth.', - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - ), - 'depth' => array( - 'description' => 'The depth relative to the top level. A link with plid == 0 will have depth == 1.', - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - 'size' => 'small', - ), - 'customized' => array( - 'description' => 'A flag to indicate that the user has manually created or edited the link (1 = customized, 0 = not customized).', - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - 'size' => 'small', - ), - 'p1' => array( - 'description' => 'The first mlid in the materialized path. If N = depth, then pN must equal the mlid. If depth > 1 then p(N-1) must equal the plid. All pX where X > depth must equal zero. The columns p1 .. p9 are also called the parents.', - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => TRUE, - 'default' => 0, - ), - 'p2' => array( - 'description' => 'The second mlid in the materialized path. See p1.', - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => TRUE, - 'default' => 0, - ), - 'p3' => array( - 'description' => 'The third mlid in the materialized path. See p1.', - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => TRUE, - 'default' => 0, - ), - 'p4' => array( - 'description' => 'The fourth mlid in the materialized path. See p1.', - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => TRUE, - 'default' => 0, - ), - 'p5' => array( - 'description' => 'The fifth mlid in the materialized path. See p1.', - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => TRUE, - 'default' => 0, - ), - 'p6' => array( - 'description' => 'The sixth mlid in the materialized path. See p1.', - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => TRUE, - 'default' => 0, - ), - 'p7' => array( - 'description' => 'The seventh mlid in the materialized path. See p1.', - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => TRUE, - 'default' => 0, - ), - 'p8' => array( - 'description' => 'The eighth mlid in the materialized path. See p1.', - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => TRUE, - 'default' => 0, - ), - 'p9' => array( - 'description' => 'The ninth mlid in the materialized path. See p1.', - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => TRUE, - 'default' => 0, - ), - 'updated' => array( - 'description' => 'Flag that indicates that this link was generated during the update from Drupal 5.', - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - 'size' => 'small', - ), - 'route_name' => array( - 'description' => 'The machine name of a defined Symfony Route this menu item represents.', - 'type' => 'varchar', - 'length' => 255, - ), - 'route_parameters' => array( - 'description' => 'Serialized array of route parameters of this menu link.', - 'type' => 'blob', - 'size' => 'big', - 'not null' => FALSE, - 'serialize' => TRUE, - ), - ), - 'indexes' => array( - 'path_menu' => array(array('link_path', 128), 'menu_name'), - 'menu_plid_expand_child' => array('menu_name', 'plid', 'expanded', 'has_children'), - 'menu_parents' => array('menu_name', 'p1', 'p2', 'p3', 'p4', 'p5', 'p6', 'p7', 'p8', 'p9'), - ), - 'primary key' => array('mlid'), - ); - - return $schema; -} diff --git a/core/modules/menu_link/src/MenuLinkStorage.php b/core/modules/menu_link/src/MenuLinkStorage.php index 60871d0..765080c 100644 --- a/core/modules/menu_link/src/MenuLinkStorage.php +++ b/core/modules/menu_link/src/MenuLinkStorage.php @@ -10,6 +10,8 @@ use Drupal\Core\Entity\EntityDatabaseStorage; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityStorageException; +use Drupal\Core\Entity\Sql\DefaultTableMapping; +use Drupal\Core\Entity\Sql\SqlEntityStorageInterface; /** * Controller class for menu links. @@ -17,7 +19,7 @@ * This extends the Drupal\entity\EntityDatabaseStorage class, adding * required special handling for menu_link entities. */ -class MenuLinkStorage extends EntityDatabaseStorage implements MenuLinkStorageInterface { +class MenuLinkStorage extends EntityDatabaseStorage implements MenuLinkStorageInterface, SqlEntityStorageInterface { /** * Indicates whether the delete operation should re-parent children items. @@ -27,6 +29,20 @@ class MenuLinkStorage extends EntityDatabaseStorage implements MenuLinkStorageIn protected $preventReparenting = FALSE; /** + * The table mapping of menu links. + * + * @var \Drupal\Core\Entity\Sql\TableMappingInterface + */ + protected $tableMapping; + + /** + * The entity's db schema. + * + * @var array + */ + protected $schema; + + /** * {@inheritdoc} */ public function create(array $values = array()) { @@ -76,7 +92,8 @@ public function save(EntityInterface $entity) { // $entity may have additional keys left over from building a router entry. // The intersect removes the extra keys, allowing a meaningful comparison. if ($entity->isNew() || (array_intersect_key(get_object_vars($entity), get_object_vars($entity->original)) != get_object_vars($entity->original))) { - $return = drupal_write_record($this->entityType->getBaseTable(), $entity, $this->idKey); + $table = $this->entityType->getBaseTable(); + $return = drupal_write_record($table, $entity, $this->idKey, $this->getSchema()[$table]); if ($return) { if (!$entity->isNew()) { @@ -316,4 +333,232 @@ public function createFromDefaultLink(array $item) { return $this->create($item); } + /** + * {@inheritdoc} + */ + public function getSchema() { + if (!isset($this->schema)) { + $this->schema[$this->entityType->getBaseTable()] = array( + 'description' => 'Contains the individual links within a menu.', + 'fields' => array( + 'menu_name' => array( + 'description' => "The menu name. All links with the same menu name (such as 'tools') are part of the same menu.", + 'type' => 'varchar', + 'length' => 32, + 'not null' => TRUE, + 'default' => '', + ), + 'mlid' => array( + 'description' => 'The menu link ID (mlid) is the integer primary key.', + 'type' => 'serial', + 'unsigned' => TRUE, + 'not null' => TRUE, + ), + 'uuid' => array( + 'description' => 'Unique Key: Universally unique identifier for this entity.', + 'type' => 'varchar', + 'length' => 128, + 'not null' => FALSE, + ), + 'machine_name' => array( + 'description' => 'Unique machine name: Optional human-readable ID for this link.', + 'type' => 'varchar', + 'length' => 255, + 'not null' => FALSE, + ), + 'plid' => array( + 'description' => 'The parent link ID (plid) is the mlid of the link above in the hierarchy, or zero if the link is at the top level in its menu.', + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'link_path' => array( + 'description' => 'The Drupal path or external path this link points to.', + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '', + ), + 'langcode' => array( + 'description' => 'The {language}.langcode of this link.', + 'type' => 'varchar', + 'length' => 12, + 'not null' => TRUE, + 'default' => '', + ), + 'link_title' => array( + 'description' => 'The text displayed for the link.', + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '', + ), + 'options' => array( + 'description' => 'A serialized array of options to be passed to the url() or l() function, such as a query string or HTML attributes.', + 'type' => 'blob', + 'not null' => FALSE, + 'serialize' => TRUE, + ), + 'module' => array( + 'description' => 'The name of the module that generated this link.', + 'type' => 'varchar', + 'length' => DRUPAL_EXTENSION_NAME_MAX_LENGTH, + 'not null' => TRUE, + 'default' => 'system', + ), + 'hidden' => array( + 'description' => 'A flag for whether the link should be rendered in menus. (1 = a disabled menu item that may be shown on admin screens, -1 = a menu callback, 0 = a normal, visible link)', + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + 'size' => 'small', + ), + 'external' => array( + 'description' => 'A flag to indicate if the link points to a full URL starting with a protocol, like http:// (1 = external, 0 = internal).', + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + 'size' => 'small', + ), + 'has_children' => array( + 'description' => 'Flag indicating whether any links have this link as a parent (1 = children exist, 0 = no children).', + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + 'size' => 'small', + ), + 'expanded' => array( + 'description' => 'Flag for whether this link should be rendered as expanded in menus - expanded links always have their child links displayed, instead of only when the link is in the active trail (1 = expanded, 0 = not expanded)', + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + 'size' => 'small', + ), + 'weight' => array( + 'description' => 'Link weight among links in the same menu at the same depth.', + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + ), + 'depth' => array( + 'description' => 'The depth relative to the top level. A link with plid == 0 will have depth == 1.', + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + 'size' => 'small', + ), + 'customized' => array( + 'description' => 'A flag to indicate that the user has manually created or edited the link (1 = customized, 0 = not customized).', + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + 'size' => 'small', + ), + 'p1' => array( + 'description' => 'The first mlid in the materialized path. If N = depth, then pN must equal the mlid. If depth > 1 then p(N-1) must equal the plid. All pX where X > depth must equal zero. The columns p1 .. p9 are also called the parents.', + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'p2' => array( + 'description' => 'The second mlid in the materialized path. See p1.', + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'p3' => array( + 'description' => 'The third mlid in the materialized path. See p1.', + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'p4' => array( + 'description' => 'The fourth mlid in the materialized path. See p1.', + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'p5' => array( + 'description' => 'The fifth mlid in the materialized path. See p1.', + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'p6' => array( + 'description' => 'The sixth mlid in the materialized path. See p1.', + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'p7' => array( + 'description' => 'The seventh mlid in the materialized path. See p1.', + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'p8' => array( + 'description' => 'The eighth mlid in the materialized path. See p1.', + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'p9' => array( + 'description' => 'The ninth mlid in the materialized path. See p1.', + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'updated' => array( + 'description' => 'Flag that indicates that this link was generated during the update from Drupal 5.', + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + 'size' => 'small', + ), + 'route_name' => array( + 'description' => 'The machine name of a defined Symfony Route this menu item represents.', + 'type' => 'varchar', + 'length' => 255, + ), + 'route_parameters' => array( + 'description' => 'Serialized array of route parameters of this menu link.', + 'type' => 'blob', + 'size' => 'big', + 'not null' => FALSE, + 'serialize' => TRUE, + ), + ), + 'indexes' => array( + 'path_menu' => array(array('link_path', 128), 'menu_name'), + 'menu_plid_expand_child' => array('menu_name', 'plid', 'expanded', 'has_children'), + 'menu_parents' => array('menu_name', 'p1', 'p2', 'p3', 'p4', 'p5', 'p6', 'p7', 'p8', 'p9'), + ), + 'primary key' => array('mlid'), + ); + } + return $this->schema; + } + + /** + * {@inheritdoc} + */ + public function getTableMapping() { + if (!isset($this->tableMapping)) { + $this->tableMapping = new DefaultTableMapping(array()); + $table = $this->entityType->getBaseTable(); + $this->tableMapping->setExtraColumns($table, array_keys($this->getSchema()[$table]['fields'])); + } + return $this->tableMapping; + } + }