annotate core/lib/Drupal/Core/Database/database.api.php @ 13:5fb285c0d0e3

Update Drupal core to 8.4.7 via Composer. Security update; I *think* we've been lucky to get away with this so far, as we don't support self-registration which seems to be used by the so-called "drupalgeddon 2" attack that 8.4.5 was vulnerable to.
author Chris Cannam
date Mon, 23 Apr 2018 09:33:26 +0100
parents 4c8ae668cc8c
children c2387f117808
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 /**
Chris@0 4 * @file
Chris@0 5 * Hooks related to the Database system and the Schema API.
Chris@0 6 */
Chris@0 7
Chris@0 8 use Drupal\Core\Database\Query\Condition;
Chris@0 9
Chris@0 10 /**
Chris@0 11 * @defgroup database Database abstraction layer
Chris@0 12 * @{
Chris@0 13 * Allow the use of different database servers using the same code base.
Chris@0 14 *
Chris@0 15 * @section sec_intro Overview
Chris@0 16 * Drupal's database abstraction layer provides a unified database query API
Chris@0 17 * that can query different underlying databases. It is built upon PHP's
Chris@0 18 * PDO (PHP Data Objects) database API, and inherits much of its syntax and
Chris@0 19 * semantics. Besides providing a unified API for database queries, the
Chris@0 20 * database abstraction layer also provides a structured way to construct
Chris@0 21 * complex queries, and it protects the database by using good security
Chris@0 22 * practices.
Chris@0 23 *
Chris@0 24 * For more detailed information on the database abstraction layer, see
Chris@0 25 * https://www.drupal.org/developing/api/database.
Chris@0 26 *
Chris@0 27 * @section sec_entity Querying entities
Chris@0 28 * Any query on Drupal entities or fields should use the Entity Query API. See
Chris@0 29 * the @link entity_api entity API topic @endlink for more information.
Chris@0 30 *
Chris@0 31 * @section sec_simple Simple SELECT database queries
Chris@0 32 * For simple SELECT queries that do not involve entities, the Drupal database
Chris@0 33 * abstraction layer provides the functions db_query() and db_query_range(),
Chris@0 34 * which execute SELECT queries (optionally with range limits) and return result
Chris@0 35 * sets that you can iterate over using foreach loops. (The result sets are
Chris@0 36 * objects implementing the \Drupal\Core\Database\StatementInterface interface.)
Chris@0 37 * You can use the simple query functions for query strings that are not
Chris@0 38 * dynamic (except for placeholders, see below), and that you are certain will
Chris@0 39 * work in any database engine. See @ref sec_dynamic below if you have a more
Chris@0 40 * complex query, or a query whose syntax would be different in some databases.
Chris@0 41 *
Chris@0 42 * As a note, db_query() and similar functions are wrappers on connection object
Chris@0 43 * methods. In most classes, you should use dependency injection and the
Chris@0 44 * database connection object instead of these wrappers; See @ref sec_connection
Chris@0 45 * below for details.
Chris@0 46 *
Chris@0 47 * To use the simple database query functions, you will need to make a couple of
Chris@0 48 * modifications to your bare SQL query:
Chris@0 49 * - Enclose your table name in {}. Drupal allows site builders to use
Chris@0 50 * database table name prefixes, so you cannot be sure what the actual
Chris@0 51 * name of the table will be. So, use the name that is in the hook_schema(),
Chris@0 52 * enclosed in {}, and Drupal will calculate the right name.
Chris@0 53 * - Instead of putting values for conditions into the query, use placeholders.
Chris@0 54 * The placeholders are named and start with :, and they take the place of
Chris@0 55 * putting variables directly into the query, to protect against SQL
Chris@0 56 * injection attacks.
Chris@0 57 * - LIMIT syntax differs between databases, so if you have a ranged query,
Chris@0 58 * use db_query_range() instead of db_query().
Chris@0 59 *
Chris@0 60 * For example, if the query you want to run is:
Chris@0 61 * @code
Chris@0 62 * SELECT e.id, e.title, e.created FROM example e WHERE e.uid = $uid
Chris@0 63 * ORDER BY e.created DESC LIMIT 0, 10;
Chris@0 64 * @endcode
Chris@0 65 * you would do it like this:
Chris@0 66 * @code
Chris@0 67 * $result = db_query_range('SELECT e.id, e.title, e.created
Chris@0 68 * FROM {example} e
Chris@0 69 * WHERE e.uid = :uid
Chris@0 70 * ORDER BY e.created DESC',
Chris@0 71 * 0, 10, array(':uid' => $uid));
Chris@0 72 * foreach ($result as $record) {
Chris@0 73 * // Perform operations on $record->title, etc. here.
Chris@0 74 * }
Chris@0 75 * @endcode
Chris@0 76 *
Chris@0 77 * Note that if your query has a string condition, like:
Chris@0 78 * @code
Chris@0 79 * WHERE e.my_field = 'foo'
Chris@0 80 * @endcode
Chris@0 81 * when you convert it to placeholders, omit the quotes:
Chris@0 82 * @code
Chris@0 83 * WHERE e.my_field = :my_field
Chris@0 84 * ... array(':my_field' => 'foo') ...
Chris@0 85 * @endcode
Chris@0 86 *
Chris@0 87 * @section sec_dynamic Dynamic SELECT queries
Chris@0 88 * For SELECT queries where the simple query API described in @ref sec_simple
Chris@0 89 * will not work well, you need to use the dynamic query API. However, you
Chris@0 90 * should still use the Entity Query API if your query involves entities or
Chris@0 91 * fields (see the @link entity_api Entity API topic @endlink for more on
Chris@0 92 * entity queries).
Chris@0 93 *
Chris@0 94 * As a note, db_select() and similar functions are wrappers on connection
Chris@0 95 * object methods. In most classes, you should use dependency injection and the
Chris@0 96 * database connection object instead of these wrappers; See @ref sec_connection
Chris@0 97 * below for details.
Chris@0 98 *
Chris@0 99 * The dynamic query API lets you build up a query dynamically using method
Chris@0 100 * calls. As an illustration, the query example from @ref sec_simple above
Chris@0 101 * would be:
Chris@0 102 * @code
Chris@0 103 * $result = db_select('example', 'e')
Chris@0 104 * ->fields('e', array('id', 'title', 'created'))
Chris@0 105 * ->condition('e.uid', $uid)
Chris@0 106 * ->orderBy('e.created', 'DESC')
Chris@0 107 * ->range(0, 10)
Chris@0 108 * ->execute();
Chris@0 109 * @endcode
Chris@0 110 *
Chris@0 111 * There are also methods to join to other tables, add fields with aliases,
Chris@0 112 * isNull() to have a @code WHERE e.foo IS NULL @endcode condition, etc. See
Chris@0 113 * https://www.drupal.org/developing/api/database for many more details.
Chris@0 114 *
Chris@0 115 * One note on chaining: It is common in the dynamic database API to chain
Chris@0 116 * method calls (as illustrated here), because most of the query methods modify
Chris@0 117 * the query object and then return the modified query as their return
Chris@0 118 * value. However, there are some important exceptions; these methods (and some
Chris@0 119 * others) do not support chaining:
Chris@0 120 * - join(), innerJoin(), etc.: These methods return the joined table alias.
Chris@0 121 * - addField(): This method returns the field alias.
Chris@0 122 * Check the documentation for the query method you are using to see if it
Chris@0 123 * returns the query or something else, and only chain methods that return the
Chris@0 124 * query.
Chris@0 125 *
Chris@0 126 * @section_insert INSERT, UPDATE, and DELETE queries
Chris@0 127 * INSERT, UPDATE, and DELETE queries need special care in order to behave
Chris@0 128 * consistently across databases; you should never use db_query() to run
Chris@0 129 * an INSERT, UPDATE, or DELETE query. Instead, use functions db_insert(),
Chris@0 130 * db_update(), and db_delete() to obtain a base query on your table, and then
Chris@0 131 * add dynamic conditions (as illustrated in @ref sec_dynamic above).
Chris@0 132 *
Chris@0 133 * As a note, db_insert() and similar functions are wrappers on connection
Chris@0 134 * object methods. In most classes, you should use dependency injection and the
Chris@0 135 * database connection object instead of these wrappers; See @ref sec_connection
Chris@0 136 * below for details.
Chris@0 137 *
Chris@0 138 * For example, if your query is:
Chris@0 139 * @code
Chris@0 140 * INSERT INTO example (id, uid, path, name) VALUES (1, 2, 'path', 'Name');
Chris@0 141 * @endcode
Chris@0 142 * You can execute it via:
Chris@0 143 * @code
Chris@0 144 * $fields = array('id' => 1, 'uid' => 2, 'path' => 'path', 'name' => 'Name');
Chris@0 145 * db_insert('example')
Chris@0 146 * ->fields($fields)
Chris@0 147 * ->execute();
Chris@0 148 * @endcode
Chris@0 149 *
Chris@0 150 * @section sec_transaction Transactions
Chris@0 151 * Drupal supports transactions, including a transparent fallback for
Chris@0 152 * databases that do not support transactions. To start a new transaction,
Chris@0 153 * call @code $txn = db_transaction(); @endcode The transaction will
Chris@0 154 * remain open for as long as the variable $txn remains in scope; when $txn is
Chris@0 155 * destroyed, the transaction will be committed. If your transaction is nested
Chris@0 156 * inside of another then Drupal will track each transaction and only commit
Chris@0 157 * the outer-most transaction when the last transaction object goes out out of
Chris@0 158 * scope (when all relevant queries have completed successfully).
Chris@0 159 *
Chris@0 160 * Example:
Chris@0 161 * @code
Chris@0 162 * function my_transaction_function() {
Chris@0 163 * // The transaction opens here.
Chris@0 164 * $txn = db_transaction();
Chris@0 165 *
Chris@0 166 * try {
Chris@0 167 * $id = db_insert('example')
Chris@0 168 * ->fields(array(
Chris@0 169 * 'field1' => 'mystring',
Chris@0 170 * 'field2' => 5,
Chris@0 171 * ))
Chris@0 172 * ->execute();
Chris@0 173 *
Chris@0 174 * my_other_function($id);
Chris@0 175 *
Chris@0 176 * return $id;
Chris@0 177 * }
Chris@0 178 * catch (Exception $e) {
Chris@0 179 * // Something went wrong somewhere, so roll back now.
Chris@0 180 * $txn->rollBack();
Chris@0 181 * // Log the exception to watchdog.
Chris@0 182 * watchdog_exception('type', $e);
Chris@0 183 * }
Chris@0 184 *
Chris@0 185 * // $txn goes out of scope here. Unless the transaction was rolled back, it
Chris@0 186 * // gets automatically committed here.
Chris@0 187 * }
Chris@0 188 *
Chris@0 189 * function my_other_function($id) {
Chris@0 190 * // The transaction is still open here.
Chris@0 191 *
Chris@0 192 * if ($id % 2 == 0) {
Chris@0 193 * db_update('example')
Chris@0 194 * ->condition('id', $id)
Chris@0 195 * ->fields(array('field2' => 10))
Chris@0 196 * ->execute();
Chris@0 197 * }
Chris@0 198 * }
Chris@0 199 * @endcode
Chris@0 200 *
Chris@0 201 * @section sec_connection Database connection objects
Chris@0 202 * The examples here all use functions like db_select() and db_query(), which
Chris@0 203 * can be called from any Drupal method or function code. In some classes, you
Chris@0 204 * may already have a database connection object in a member variable, or it may
Chris@0 205 * be passed into a class constructor via dependency injection. If that is the
Chris@0 206 * case, you can look at the code for db_select() and the other functions to see
Chris@0 207 * how to get a query object from your connection variable. For example:
Chris@0 208 * @code
Chris@0 209 * $query = $connection->select('example', 'e');
Chris@0 210 * @endcode
Chris@0 211 * would be the equivalent of
Chris@0 212 * @code
Chris@0 213 * $query = db_select('example', 'e');
Chris@0 214 * @endcode
Chris@0 215 * if you had a connection object variable $connection available to use. See
Chris@0 216 * also the @link container Services and Dependency Injection topic. @endlink
Chris@0 217 *
Chris@0 218 * @see https://www.drupal.org/developing/api/database
Chris@0 219 * @see entity_api
Chris@0 220 * @see schemaapi
Chris@0 221 *
Chris@0 222 * @}
Chris@0 223 */
Chris@0 224
Chris@0 225 /**
Chris@0 226 * @defgroup schemaapi Schema API
Chris@0 227 * @{
Chris@0 228 * API to handle database schemas.
Chris@0 229 *
Chris@0 230 * A Drupal schema definition is an array structure representing one or
Chris@0 231 * more tables and their related keys and indexes. A schema is defined by
Chris@0 232 * hook_schema(), which usually lives in a modulename.install file.
Chris@0 233 *
Chris@0 234 * By implementing hook_schema() and specifying the tables your module
Chris@0 235 * declares, you can easily create and drop these tables on all
Chris@0 236 * supported database engines. You don't have to deal with the
Chris@0 237 * different SQL dialects for table creation and alteration of the
Chris@0 238 * supported database engines.
Chris@0 239 *
Chris@0 240 * hook_schema() should return an array with a key for each table that
Chris@0 241 * the module defines.
Chris@0 242 *
Chris@0 243 * The following keys are defined:
Chris@0 244 * - 'description': A string in non-markup plain text describing this table
Chris@0 245 * and its purpose. References to other tables should be enclosed in
Chris@0 246 * curly-brackets. For example, the node_field_revision table
Chris@0 247 * description field might contain "Stores per-revision title and
Chris@0 248 * body data for each {node}."
Chris@0 249 * - 'fields': An associative array ('fieldname' => specification)
Chris@0 250 * that describes the table's database columns. The specification
Chris@0 251 * is also an array. The following specification parameters are defined:
Chris@0 252 * - 'description': A string in non-markup plain text describing this field
Chris@0 253 * and its purpose. References to other tables should be enclosed in
Chris@0 254 * curly-brackets. For example, the node table vid field
Chris@0 255 * description might contain "Always holds the largest (most
Chris@0 256 * recent) {node_field_revision}.vid value for this nid."
Chris@0 257 * - 'type': The generic datatype: 'char', 'varchar', 'text', 'blob', 'int',
Chris@0 258 * 'float', 'numeric', or 'serial'. Most types just map to the according
Chris@0 259 * database engine specific datatypes. Use 'serial' for auto incrementing
Chris@0 260 * fields. This will expand to 'INT auto_increment' on MySQL.
Chris@0 261 * A special 'varchar_ascii' type is also available for limiting machine
Chris@0 262 * name field to US ASCII characters.
Chris@0 263 * - 'mysql_type', 'pgsql_type', 'sqlite_type', etc.: If you need to
Chris@0 264 * use a record type not included in the officially supported list
Chris@0 265 * of types above, you can specify a type for each database
Chris@0 266 * backend. In this case, you can leave out the type parameter,
Chris@0 267 * but be advised that your schema will fail to load on backends that
Chris@0 268 * do not have a type specified. A possible solution can be to
Chris@0 269 * use the "text" type as a fallback.
Chris@0 270 * - 'serialize': A boolean indicating whether the field will be stored as
Chris@0 271 * a serialized string.
Chris@0 272 * - 'size': The data size: 'tiny', 'small', 'medium', 'normal',
Chris@0 273 * 'big'. This is a hint about the largest value the field will
Chris@0 274 * store and determines which of the database engine specific
Chris@0 275 * datatypes will be used (e.g. on MySQL, TINYINT vs. INT vs. BIGINT).
Chris@0 276 * 'normal', the default, selects the base type (e.g. on MySQL,
Chris@0 277 * INT, VARCHAR, BLOB, etc.).
Chris@0 278 * Not all sizes are available for all data types. See
Chris@0 279 * DatabaseSchema::getFieldTypeMap() for possible combinations.
Chris@0 280 * - 'not null': If true, no NULL values will be allowed in this
Chris@0 281 * database column. Defaults to false.
Chris@0 282 * - 'default': The field's default value. The PHP type of the
Chris@0 283 * value matters: '', '0', and 0 are all different. If you
Chris@0 284 * specify '0' as the default value for a type 'int' field it
Chris@0 285 * will not work because '0' is a string containing the
Chris@0 286 * character "zero", not an integer.
Chris@0 287 * - 'length': The maximal length of a type 'char', 'varchar' or 'text'
Chris@0 288 * field. Ignored for other field types.
Chris@0 289 * - 'unsigned': A boolean indicating whether a type 'int', 'float'
Chris@0 290 * and 'numeric' only is signed or unsigned. Defaults to
Chris@0 291 * FALSE. Ignored for other field types.
Chris@0 292 * - 'precision', 'scale': For type 'numeric' fields, indicates
Chris@0 293 * the precision (total number of significant digits) and scale
Chris@0 294 * (decimal digits right of the decimal point). Both values are
Chris@0 295 * mandatory. Ignored for other field types.
Chris@0 296 * - 'binary': A boolean indicating that MySQL should force 'char',
Chris@0 297 * 'varchar' or 'text' fields to use case-sensitive binary collation.
Chris@0 298 * This has no effect on other database types for which case sensitivity
Chris@0 299 * is already the default behavior.
Chris@0 300 * All parameters apart from 'type' are optional except that type
Chris@0 301 * 'numeric' columns must specify 'precision' and 'scale', and type
Chris@0 302 * 'varchar' must specify the 'length' parameter.
Chris@0 303 * - 'primary key': An array of one or more key column specifiers (see below)
Chris@0 304 * that form the primary key.
Chris@0 305 * - 'unique keys': An associative array of unique keys ('keyname' =>
Chris@0 306 * specification). Each specification is an array of one or more
Chris@0 307 * key column specifiers (see below) that form a unique key on the table.
Chris@0 308 * - 'foreign keys': An associative array of relations ('my_relation' =>
Chris@0 309 * specification). Each specification is an array containing the name of
Chris@0 310 * the referenced table ('table'), and an array of column mappings
Chris@0 311 * ('columns'). Column mappings are defined by key pairs ('source_column' =>
Chris@0 312 * 'referenced_column'). This key is for documentation purposes only; foreign
Chris@0 313 * keys are not created in the database, nor are they enforced by Drupal.
Chris@0 314 * - 'indexes': An associative array of indexes ('indexname' =>
Chris@0 315 * specification). Each specification is an array of one or more
Chris@0 316 * key column specifiers (see below) that form an index on the
Chris@0 317 * table.
Chris@0 318 *
Chris@0 319 * A key column specifier is either a string naming a column or an
Chris@0 320 * array of two elements, column name and length, specifying a prefix
Chris@0 321 * of the named column.
Chris@0 322 *
Chris@0 323 * As an example, here is a SUBSET of the schema definition for
Chris@0 324 * Drupal's 'node' table. It show four fields (nid, vid, type, and
Chris@0 325 * title), the primary key on field 'nid', a unique key named 'vid' on
Chris@0 326 * field 'vid', and two indexes, one named 'nid' on field 'nid' and
Chris@0 327 * one named 'node_title_type' on the field 'title' and the first four
Chris@0 328 * bytes of the field 'type':
Chris@0 329 *
Chris@0 330 * @code
Chris@0 331 * $schema['node'] = array(
Chris@0 332 * 'description' => 'The base table for nodes.',
Chris@0 333 * 'fields' => array(
Chris@0 334 * 'nid' => array('type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE),
Chris@0 335 * 'vid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE,'default' => 0),
Chris@0 336 * 'type' => array('type' => 'varchar','length' => 32,'not null' => TRUE, 'default' => ''),
Chris@0 337 * 'language' => array('type' => 'varchar','length' => 12,'not null' => TRUE,'default' => ''),
Chris@0 338 * 'title' => array('type' => 'varchar','length' => 255,'not null' => TRUE, 'default' => ''),
Chris@0 339 * 'uid' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
Chris@0 340 * 'status' => array('type' => 'int', 'not null' => TRUE, 'default' => 1),
Chris@0 341 * 'created' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
Chris@0 342 * 'changed' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
Chris@0 343 * 'comment' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
Chris@0 344 * 'promote' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
Chris@0 345 * 'moderate' => array('type' => 'int', 'not null' => TRUE,'default' => 0),
Chris@0 346 * 'sticky' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
Chris@0 347 * 'translate' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
Chris@0 348 * ),
Chris@0 349 * 'indexes' => array(
Chris@0 350 * 'node_changed' => array('changed'),
Chris@0 351 * 'node_created' => array('created'),
Chris@0 352 * 'node_moderate' => array('moderate'),
Chris@0 353 * 'node_frontpage' => array('promote', 'status', 'sticky', 'created'),
Chris@0 354 * 'node_status_type' => array('status', 'type', 'nid'),
Chris@0 355 * 'node_title_type' => array('title', array('type', 4)),
Chris@0 356 * 'node_type' => array(array('type', 4)),
Chris@0 357 * 'uid' => array('uid'),
Chris@0 358 * 'translate' => array('translate'),
Chris@0 359 * ),
Chris@0 360 * 'unique keys' => array(
Chris@0 361 * 'vid' => array('vid'),
Chris@0 362 * ),
Chris@0 363 * // For documentation purposes only; foreign keys are not created in the
Chris@0 364 * // database.
Chris@0 365 * 'foreign keys' => array(
Chris@0 366 * 'node_revision' => array(
Chris@0 367 * 'table' => 'node_field_revision',
Chris@0 368 * 'columns' => array('vid' => 'vid'),
Chris@0 369 * ),
Chris@0 370 * 'node_author' => array(
Chris@0 371 * 'table' => 'users',
Chris@0 372 * 'columns' => array('uid' => 'uid'),
Chris@0 373 * ),
Chris@0 374 * ),
Chris@0 375 * 'primary key' => array('nid'),
Chris@0 376 * );
Chris@0 377 * @endcode
Chris@0 378 *
Chris@0 379 * @see drupal_install_schema()
Chris@0 380 *
Chris@0 381 * @}
Chris@0 382 */
Chris@0 383
Chris@0 384 /**
Chris@0 385 * @addtogroup hooks
Chris@0 386 * @{
Chris@0 387 */
Chris@0 388
Chris@0 389 /**
Chris@0 390 * Perform alterations to a structured query.
Chris@0 391 *
Chris@0 392 * Structured (aka dynamic) queries that have tags associated may be altered by any module
Chris@0 393 * before the query is executed.
Chris@0 394 *
Chris@0 395 * @param $query
Chris@0 396 * A Query object describing the composite parts of a SQL query.
Chris@0 397 *
Chris@0 398 * @see hook_query_TAG_alter()
Chris@0 399 * @see node_query_node_access_alter()
Chris@0 400 * @see AlterableInterface
Chris@0 401 * @see SelectInterface
Chris@0 402 *
Chris@0 403 * @ingroup database
Chris@0 404 */
Chris@0 405 function hook_query_alter(Drupal\Core\Database\Query\AlterableInterface $query) {
Chris@0 406 if ($query->hasTag('micro_limit')) {
Chris@0 407 $query->range(0, 2);
Chris@0 408 }
Chris@0 409 }
Chris@0 410
Chris@0 411 /**
Chris@0 412 * Perform alterations to a structured query for a given tag.
Chris@0 413 *
Chris@0 414 * @param $query
Chris@0 415 * An Query object describing the composite parts of a SQL query.
Chris@0 416 *
Chris@0 417 * @see hook_query_alter()
Chris@0 418 * @see node_query_node_access_alter()
Chris@0 419 * @see AlterableInterface
Chris@0 420 * @see SelectInterface
Chris@0 421 *
Chris@0 422 * @ingroup database
Chris@0 423 */
Chris@0 424 function hook_query_TAG_alter(Drupal\Core\Database\Query\AlterableInterface $query) {
Chris@0 425 // Skip the extra expensive alterations if site has no node access control modules.
Chris@0 426 if (!node_access_view_all_nodes()) {
Chris@0 427 // Prevent duplicates records.
Chris@0 428 $query->distinct();
Chris@0 429 // The recognized operations are 'view', 'update', 'delete'.
Chris@0 430 if (!$op = $query->getMetaData('op')) {
Chris@0 431 $op = 'view';
Chris@0 432 }
Chris@0 433 // Skip the extra joins and conditions for node admins.
Chris@0 434 if (!\Drupal::currentUser()->hasPermission('bypass node access')) {
Chris@0 435 // The node_access table has the access grants for any given node.
Chris@0 436 $access_alias = $query->join('node_access', 'na', '%alias.nid = n.nid');
Chris@0 437 $or = new Condition('OR');
Chris@0 438 // If any grant exists for the specified user, then user has access to the node for the specified operation.
Chris@0 439 foreach (node_access_grants($op, $query->getMetaData('account')) as $realm => $gids) {
Chris@0 440 foreach ($gids as $gid) {
Chris@0 441 $or->condition((new Condition('AND'))
Chris@0 442 ->condition($access_alias . '.gid', $gid)
Chris@0 443 ->condition($access_alias . '.realm', $realm)
Chris@0 444 );
Chris@0 445 }
Chris@0 446 }
Chris@0 447
Chris@0 448 if (count($or->conditions())) {
Chris@0 449 $query->condition($or);
Chris@0 450 }
Chris@0 451
Chris@0 452 $query->condition($access_alias . 'grant_' . $op, 1, '>=');
Chris@0 453 }
Chris@0 454 }
Chris@0 455 }
Chris@0 456
Chris@0 457 /**
Chris@0 458 * Define the current version of the database schema.
Chris@0 459 *
Chris@0 460 * A Drupal schema definition is an array structure representing one or more
Chris@0 461 * tables and their related keys and indexes. A schema is defined by
Chris@0 462 * hook_schema() which must live in your module's .install file.
Chris@0 463 *
Chris@0 464 * The tables declared by this hook will be automatically created when the
Chris@0 465 * module is installed, and removed when the module is uninstalled. This happens
Chris@0 466 * before hook_install() is invoked, and after hook_uninstall() is invoked,
Chris@0 467 * respectively.
Chris@0 468 *
Chris@0 469 * By declaring the tables used by your module via an implementation of
Chris@0 470 * hook_schema(), these tables will be available on all supported database
Chris@0 471 * engines. You don't have to deal with the different SQL dialects for table
Chris@0 472 * creation and alteration of the supported database engines.
Chris@0 473 *
Chris@0 474 * See the Schema API Handbook at https://www.drupal.org/node/146843 for details
Chris@0 475 * on schema definition structures. Note that foreign key definitions are for
Chris@0 476 * documentation purposes only; foreign keys are not created in the database,
Chris@0 477 * nor are they enforced by Drupal.
Chris@0 478 *
Chris@0 479 * @return array
Chris@0 480 * A schema definition structure array. For each element of the
Chris@0 481 * array, the key is a table name and the value is a table structure
Chris@0 482 * definition.
Chris@0 483 *
Chris@0 484 * @ingroup schemaapi
Chris@0 485 */
Chris@0 486 function hook_schema() {
Chris@0 487 $schema['node'] = [
Chris@0 488 // Example (partial) specification for table "node".
Chris@0 489 'description' => 'The base table for nodes.',
Chris@0 490 'fields' => [
Chris@0 491 'nid' => [
Chris@0 492 'description' => 'The primary identifier for a node.',
Chris@0 493 'type' => 'serial',
Chris@0 494 'unsigned' => TRUE,
Chris@0 495 'not null' => TRUE,
Chris@0 496 ],
Chris@0 497 'vid' => [
Chris@0 498 'description' => 'The current {node_field_revision}.vid version identifier.',
Chris@0 499 'type' => 'int',
Chris@0 500 'unsigned' => TRUE,
Chris@0 501 'not null' => TRUE,
Chris@0 502 'default' => 0,
Chris@0 503 ],
Chris@0 504 'type' => [
Chris@0 505 'description' => 'The type of this node.',
Chris@0 506 'type' => 'varchar',
Chris@0 507 'length' => 32,
Chris@0 508 'not null' => TRUE,
Chris@0 509 'default' => '',
Chris@0 510 ],
Chris@0 511 'title' => [
Chris@0 512 'description' => 'The node title.',
Chris@0 513 'type' => 'varchar',
Chris@0 514 'length' => 255,
Chris@0 515 'not null' => TRUE,
Chris@0 516 'default' => '',
Chris@0 517 ],
Chris@0 518 ],
Chris@0 519 'indexes' => [
Chris@0 520 'node_changed' => ['changed'],
Chris@0 521 'node_created' => ['created'],
Chris@0 522 ],
Chris@0 523 'unique keys' => [
Chris@0 524 'nid_vid' => ['nid', 'vid'],
Chris@0 525 'vid' => ['vid'],
Chris@0 526 ],
Chris@0 527 // For documentation purposes only; foreign keys are not created in the
Chris@0 528 // database.
Chris@0 529 'foreign keys' => [
Chris@0 530 'node_revision' => [
Chris@0 531 'table' => 'node_field_revision',
Chris@0 532 'columns' => ['vid' => 'vid'],
Chris@0 533 ],
Chris@0 534 'node_author' => [
Chris@0 535 'table' => 'users',
Chris@0 536 'columns' => ['uid' => 'uid'],
Chris@0 537 ],
Chris@0 538 ],
Chris@0 539 'primary key' => ['nid'],
Chris@0 540 ];
Chris@0 541 return $schema;
Chris@0 542 }
Chris@0 543
Chris@0 544 /**
Chris@0 545 * @} End of "addtogroup hooks".
Chris@0 546 */