diff --git a/core/modules/node/lib/Drupal/node/Plugin/views/argument/CreatedDay.php b/core/modules/node/lib/Drupal/node/Plugin/views/argument/CreatedDay.php index ba037cdd99335f2f0e04e4779f3baee1a016201d..fd7ebe542dcd0432659d679da6f916d111730a84 100644 --- a/core/modules/node/lib/Drupal/node/Plugin/views/argument/CreatedDay.php +++ b/core/modules/node/lib/Drupal/node/Plugin/views/argument/CreatedDay.php @@ -22,14 +22,6 @@ */ class CreatedDay extends Date { - /** - * Overrides Drupal\views\Plugin\views\argument\Formula::get_formula(). - */ - function get_formula() { - $this->formula = $this->extractSQL('DAY'); - return parent::get_formula(); - } - /** * Provide a link to the next level of the view */ diff --git a/core/modules/node/lib/Drupal/node/Plugin/views/argument/CreatedFullDate.php b/core/modules/node/lib/Drupal/node/Plugin/views/argument/CreatedFullDate.php index 1f128c62fec0d0eea58ee9712b9c385df4af3bc8..0b098cff08d98155ede42a80a324dc48d3a1057b 100644 --- a/core/modules/node/lib/Drupal/node/Plugin/views/argument/CreatedFullDate.php +++ b/core/modules/node/lib/Drupal/node/Plugin/views/argument/CreatedFullDate.php @@ -22,14 +22,6 @@ */ class CreatedFullDate extends Date { - /** - * Overrides Drupal\views\Plugin\views\argument\Formula::get_formula(). - */ - function get_formula() { - $this->formula = $this->getSQLFormat($this->definition['arg_format']); - return parent::get_formula(); - } - /** * Provide a link to the next level of the view */ diff --git a/core/modules/node/lib/Drupal/node/Plugin/views/argument/CreatedMonth.php b/core/modules/node/lib/Drupal/node/Plugin/views/argument/CreatedMonth.php index e85b6fa47a338ca315bd4118875bb60ffc0a8662..a156a7bbb0fbb7b624ef3a0861157963bfcb0645 100644 --- a/core/modules/node/lib/Drupal/node/Plugin/views/argument/CreatedMonth.php +++ b/core/modules/node/lib/Drupal/node/Plugin/views/argument/CreatedMonth.php @@ -22,14 +22,6 @@ */ class CreatedMonth extends Date { - /** - * Overrides Drupal\views\Plugin\views\argument\Formula::get_formula(). - */ - function get_formula() { - $this->formula = $this->extractSQL('MONTH'); - return parent::get_formula(); - } - /** * Provide a link to the next level of the view */ diff --git a/core/modules/node/lib/Drupal/node/Plugin/views/argument/CreatedWeek.php b/core/modules/node/lib/Drupal/node/Plugin/views/argument/CreatedWeek.php index 867d0acb2fc032ff5d1b1898a533eda5aaee2365..e6174b1fdba65124d775c8e1a9379bfdb63604e0 100644 --- a/core/modules/node/lib/Drupal/node/Plugin/views/argument/CreatedWeek.php +++ b/core/modules/node/lib/Drupal/node/Plugin/views/argument/CreatedWeek.php @@ -15,20 +15,12 @@ * * @Plugin( * id = "node_created_week", - * arg_format = "w", + * arg_format = "W", * module = "node" * ) */ class CreatedWeek extends Date { - /** - * Overrides Drupal\views\Plugin\views\argument\Formula::get_formula(). - */ - function get_formula() { - $this->formula = $this->extractSQL('WEEK'); - return parent::get_formula(); - } - /** * Provide a link to the next level of the view */ diff --git a/core/modules/node/lib/Drupal/node/Plugin/views/argument/CreatedYear.php b/core/modules/node/lib/Drupal/node/Plugin/views/argument/CreatedYear.php index f4a832ca4662f1bfa61be248f55cc7810b4bab74..68bab3018acf6dc1ab61b38afb4a2ba3e0936bd4 100644 --- a/core/modules/node/lib/Drupal/node/Plugin/views/argument/CreatedYear.php +++ b/core/modules/node/lib/Drupal/node/Plugin/views/argument/CreatedYear.php @@ -21,12 +21,4 @@ */ class CreatedYear extends Date { - /** - * Overrides Drupal\views\Plugin\views\argument\Formula::get_formula(). - */ - function get_formula() { - $this->formula = $this->extractSQL('YEAR'); - return parent::get_formula(); - } - } diff --git a/core/modules/node/lib/Drupal/node/Plugin/views/argument/CreatedYearMonth.php b/core/modules/node/lib/Drupal/node/Plugin/views/argument/CreatedYearMonth.php index 598512c10c69a19a6560e814c9bce30195fe2b51..26f268d37ca02dfce2c8f0e3ffee0b588c42789c 100644 --- a/core/modules/node/lib/Drupal/node/Plugin/views/argument/CreatedYearMonth.php +++ b/core/modules/node/lib/Drupal/node/Plugin/views/argument/CreatedYearMonth.php @@ -22,14 +22,6 @@ */ class CreatedYearMonth extends Date { - /** - * Overrides Drupal\views\Plugin\views\argument\Formula::get_formula(). - */ - function get_formula() { - $this->formula = $this->getSQLFormat($this->definition['arg_format']); - return parent::get_formula(); - } - /** * Provide a link to the next level of the view */ diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/HandlerBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/HandlerBase.php index a0fad3684a7894daff6a3d4aba4431e2d2cca9b3..94b4a3be93fb5fb5873cc22ebe881d6b8fa16f16 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/HandlerBase.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/HandlerBase.php @@ -620,74 +620,8 @@ public function broken() { } * @return string * An appropriate SQL string for the DB type and field type. */ - public function getSQLFormat($format) { - $db_type = Database::getConnection()->databaseType(); - $field = $this->getSQLDateField(); - switch ($db_type) { - case 'mysql': - $replace = array( - 'Y' => '%Y', - 'y' => '%y', - 'M' => '%b', - 'm' => '%m', - 'n' => '%c', - 'F' => '%M', - 'D' => '%a', - 'd' => '%d', - 'l' => '%W', - 'j' => '%e', - 'W' => '%v', - 'H' => '%H', - 'h' => '%h', - 'i' => '%i', - 's' => '%s', - 'A' => '%p', - ); - $format = strtr($format, $replace); - return "DATE_FORMAT($field, '$format')"; - case 'pgsql': - $replace = array( - 'Y' => 'YYYY', - 'y' => 'YY', - 'M' => 'Mon', - 'm' => 'MM', - 'n' => 'MM', // no format for Numeric representation of a month, without leading zeros - 'F' => 'Month', - 'D' => 'Dy', - 'd' => 'DD', - 'l' => 'Day', - 'j' => 'DD', // no format for Day of the month without leading zeros - 'W' => 'WW', - 'H' => 'HH24', - 'h' => 'HH12', - 'i' => 'MI', - 's' => 'SS', - 'A' => 'AM', - ); - $format = strtr($format, $replace); - return "TO_CHAR($field, '$format')"; - case 'sqlite': - $replace = array( - 'Y' => '%Y', // 4 digit year number - 'y' => '%Y', // no format for 2 digit year number - 'M' => '%m', // no format for 3 letter month name - 'm' => '%m', // month number with leading zeros - 'n' => '%m', // no format for month number without leading zeros - 'F' => '%m', // no format for full month name - 'D' => '%d', // no format for 3 letter day name - 'd' => '%d', // day of month number with leading zeros - 'l' => '%d', // no format for full day name - 'j' => '%d', // no format for day of month number without leading zeros - 'W' => '%W', // ISO week number - 'H' => '%H', // 24 hour hour with leading zeros - 'h' => '%H', // no format for 12 hour hour with leading zeros - 'i' => '%M', // minutes with leading zeros - 's' => '%S', // seconds with leading zeros - 'A' => '', // no format for AM/PM - ); - $format = strtr($format, $replace); - return "strftime('$format', $field, 'unixepoch')"; - } + public function getDateFormat($format) { + return $this->query->getDateFormat($this->getDateField(), $format); } /** @@ -696,61 +630,8 @@ public function getSQLFormat($format) { * @return string * An appropriate SQL string for the db type and field type. */ - public function getSQLDateField() { - $field = "$this->tableAlias.$this->realField"; - $db_type = Database::getConnection()->databaseType(); - $offset = $this->getTimezone(); - if (isset($offset) && !is_numeric($offset)) { - $dtz = new \DateTimeZone($offset); - $dt = new \DateTime('now', $dtz); - $offset_seconds = $dtz->getOffset($dt); - } - - switch ($db_type) { - case 'mysql': - $field = "DATE_ADD('19700101', INTERVAL $field SECOND)"; - if (!empty($offset)) { - $field = "($field + INTERVAL $offset_seconds SECOND)"; - } - return $field; - case 'pgsql': - $field = "TO_TIMESTAMP($field)"; - if (!empty($offset)) { - $field = "($field + INTERVAL '$offset_seconds SECONDS')"; - } - return $field; - case 'sqlite': - if (!empty($offset)) { - $field = "($field + '$offset_seconds')"; - } - return $field; - } - } - - /** - * Figure out what timezone we're in; needed for some date manipulations. - */ - public static function getTimezone() { - $timezone = drupal_get_user_timezone(); - - // set up the database timezone - $db_type = Database::getConnection()->databaseType(); - if (in_array($db_type, array('mysql', 'pgsql'))) { - $offset = '+00:00'; - static $already_set = FALSE; - if (!$already_set) { - if ($db_type == 'pgsql') { - db_query("SET TIME ZONE INTERVAL '$offset' HOUR TO MINUTE"); - } - elseif ($db_type == 'mysql') { - db_query("SET @@session.time_zone = '$offset'"); - } - - $already_set = TRUE; - } - } - - return $timezone; + public function getDateField() { + return $this->query->getDateField("$this->tableAlias.$this->realField"); } /** diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/argument/Date.php b/core/modules/views/lib/Drupal/views/Plugin/views/argument/Date.php index 54d0d73c840710b8d7da2617a870b5e1c7933c22..57638f9bef5dd48c287e27d3841c0b62852ae80f 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/argument/Date.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/argument/Date.php @@ -14,27 +14,25 @@ * * Adds an option to set a default argument based on the current date. * - * @param $arg_format - * The format string to use on the current time when - * creating a default date argument. - * * Definitions terms: * - many to one: If true, the "many to one" helper will be used. * - invalid input: A string to give to the user for obviously invalid input. * This is deprecated in favor of argument validators. + * - arg_format: The format string to use on the current time when dealing with + * date values. * * @see Drupal\views\ManyTonOneHelper * * @ingroup views_argument_handlers * * @Plugin( - * id = "date" + * id = "date", + * arg_format = "Y-m-d" * ) */ class Date extends Formula { var $option_name = 'default_argument_date'; - var $arg_format = 'Y-m-d'; /** * Add an option to set the default value to the current date. @@ -84,62 +82,11 @@ function get_sort_name() { } /** - * Creates cross-database SQL date extraction. - * - * @param string $extract_type - * The type of value to extract from the date, like 'MONTH'. - * - * @return string - * An appropriate SQL string for the DB type and field type. + * Overrides \Drupal\views\Plugin\views\argument\Formula::get_formula(). */ - public function extractSQL($extract_type) { - $db_type = Database::getConnection()->databaseType(); - $field = $this->getSQLDateField(); - - // Note there is no space after FROM to avoid db_rewrite problems - // see http://drupal.org/node/79904. - switch ($extract_type) { - case 'DATE': - return $field; - case 'YEAR': - return "EXTRACT(YEAR FROM($field))"; - case 'MONTH': - return "EXTRACT(MONTH FROM($field))"; - case 'DAY': - return "EXTRACT(DAY FROM($field))"; - case 'HOUR': - return "EXTRACT(HOUR FROM($field))"; - case 'MINUTE': - return "EXTRACT(MINUTE FROM($field))"; - case 'SECOND': - return "EXTRACT(SECOND FROM($field))"; - // ISO week number for date - case 'WEEK': - switch ($db_type) { - case 'mysql': - // WEEK using arg 3 in mysql should return the same value as postgres - // EXTRACT. - return "WEEK($field, 3)"; - case 'pgsql': - return "EXTRACT(WEEK FROM($field))"; - } - case 'DOW': - switch ($db_type) { - case 'mysql': - // mysql returns 1 for Sunday through 7 for Saturday php date - // functions and postgres use 0 for Sunday and 6 for Saturday. - return "INTEGER(DAYOFWEEK($field) - 1)"; - case 'pgsql': - return "EXTRACT(DOW FROM($field))"; - } - case 'DOY': - switch ($db_type) { - case 'mysql': - return "DAYOFYEAR($field)"; - case 'pgsql': - return "EXTRACT(DOY FROM($field))"; - } - } + function get_formula() { + $this->formula = $this->getDateFormat($this->definition['arg_format']); + return parent::get_formula(); } } diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/query/QueryPluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/query/QueryPluginBase.php index d5506896f7c9d5ec916ed2d5bf2645efa1b6e592..e78516d88eff5ca50cb3bb5cd4b4805ebdc3bae5 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/query/QueryPluginBase.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/query/QueryPluginBase.php @@ -169,4 +169,43 @@ function set_group_operator($type = 'AND') { */ function load_entities(&$results) {} + /** + * Returns a Unix timestamp to database native timestamp expression. + * + * @param string $field + * The query field that will be used in the expression. + * + * @return string + * An expression representing a timestamp with time zone. + */ + public function getDateField($field) { + return $field; + } + + /** + * Set the database to the current user timezone, + * + * @return string + * The current timezone as returned by drupal_get_user_timezone(). + */ + public function setupTimezone() { + return drupal_get_user_timezone(); + } + + /** + * Creates cross-database date formatting. + * + * @param string $field + * An appropriate query expression pointing to the date field. + * @param string $format + * A format string for the result, like 'Y-m-d H:i:s'. + * + * @return string + * A string representing the field formatted as a date in the format + * specified by $format. + */ + public function getDateFormat($field, $format) { + return $field; + } + } diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/query/Sql.php b/core/modules/views/lib/Drupal/views/Plugin/views/query/Sql.php index 2e8a5c791c4e860f7ca2cc3ec41a6f812c7c5046..8f50431afa655a91fd7450f81b6b2c8b88fd2d8f 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/query/Sql.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/query/Sql.php @@ -1739,4 +1739,149 @@ function aggregation_method_distinct($group_type, $field) { return strtoupper($group_type) . '(DISTINCT ' . $field . ')'; } + /** + * Overrides \Drupal\views\Plugin\views\query\QueryPluginBase::getDateField(). + */ + public function getDateField($field) { + $db_type = Database::getConnection()->databaseType(); + $offset = $this->setupTimezone(); + if (isset($offset) && !is_numeric($offset)) { + $dtz = new \DateTimeZone($offset); + $dt = new \DateTime('now', $dtz); + $offset_seconds = $dtz->getOffset($dt); + } + + switch ($db_type) { + case 'mysql': + $field = "DATE_ADD('19700101', INTERVAL $field SECOND)"; + if (!empty($offset)) { + $field = "($field + INTERVAL $offset_seconds SECOND)"; + } + break; + case 'pgsql': + $field = "TO_TIMESTAMP($field)"; + if (!empty($offset)) { + $field = "($field + INTERVAL '$offset_seconds SECONDS')"; + } + break; + case 'sqlite': + if (!empty($offset)) { + $field = "($field + '$offset_seconds')"; + } + break; + } + + return $field; + } + + /** + * Overrides \Drupal\views\Plugin\views\query\QueryPluginBase::setupTimezone(). + */ + public function setupTimezone() { + $timezone = drupal_get_user_timezone(); + + // set up the database timezone + $db_type = Database::getConnection()->databaseType(); + if (in_array($db_type, array('mysql', 'pgsql'))) { + $offset = '+00:00'; + static $already_set = FALSE; + if (!$already_set) { + if ($db_type == 'pgsql') { + Database::getConnection()->query("SET TIME ZONE INTERVAL '$offset' HOUR TO MINUTE"); + } + elseif ($db_type == 'mysql') { + Database::getConnection()->query("SET @@session.time_zone = '$offset'"); + } + + $already_set = TRUE; + } + } + + return $timezone; + } + + /** + * Overrides \Drupal\views\Plugin\views\query\QueryPluginBase::getDateFormat(). + */ + public function getDateFormat($field, $format) { + $db_type = Database::getConnection()->databaseType(); + switch ($db_type) { + case 'mysql': + $replace = array( + 'Y' => '%Y', + 'y' => '%y', + 'M' => '%b', + 'm' => '%m', + 'n' => '%c', + 'F' => '%M', + 'D' => '%a', + 'd' => '%d', + 'l' => '%W', + 'j' => '%e', + 'W' => '%v', + 'H' => '%H', + 'h' => '%h', + 'i' => '%i', + 's' => '%s', + 'A' => '%p', + ); + $format = strtr($format, $replace); + return "DATE_FORMAT($field, '$format')"; + case 'pgsql': + $replace = array( + 'Y' => 'YYYY', + 'y' => 'YY', + 'M' => 'Mon', + 'm' => 'MM', + // No format for Numeric representation of a month, without leading + // zeros. + 'n' => 'MM', + 'F' => 'Month', + 'D' => 'Dy', + 'd' => 'DD', + 'l' => 'Day', + // No format for Day of the month without leading zeros. + 'j' => 'DD', + 'W' => 'WW', + 'H' => 'HH24', + 'h' => 'HH12', + 'i' => 'MI', + 's' => 'SS', + 'A' => 'AM', + ); + $format = strtr($format, $replace); + return "TO_CHAR($field, '$format')"; + case 'sqlite': + $replace = array( + 'Y' => '%Y', + // No format for 2 digit year number. + 'y' => '%Y', + // No format for 3 letter month name. + 'M' => '%m', + 'm' => '%m', + // No format for month number without leading zeros. + 'n' => '%m', + // No format for full month name. + 'F' => '%m', + // No format for 3 letter day name. + 'D' => '%d', + 'd' => '%d', + // No format for full day name. + 'l' => '%d', + // no format for day of month number without leading zeros. + 'j' => '%d', + 'W' => '%W', + 'H' => '%H', + // No format for 12 hour hour with leading zeros. + 'h' => '%H', + 'i' => '%M', + 's' => '%S', + // No format for AM/PM. + 'A' => '', + ); + $format = strtr($format, $replace); + return "strftime('$format', $field, 'unixepoch')"; + } + } + } diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/sort/Date.php b/core/modules/views/lib/Drupal/views/Plugin/views/sort/Date.php index 072aea67ae8780f8a3542f6d89c3abb8a31c16d0..6ccd5fe71aa7765cf4cbffb671fc1ebf0a2cf23a 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/sort/Date.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/sort/Date.php @@ -59,19 +59,19 @@ public function query() { $this->query->add_orderby($this->tableAlias, $this->realField, $this->options['order']); return; case 'minute': - $formula = $this->getSQLFormat('YmdHi'); + $formula = $this->getDateFormat('YmdHi'); break; case 'hour': - $formula = $this->getSQLFormat('YmdH'); + $formula = $this->getDateFormat('YmdH'); break; case 'day': - $formula = $this->getSQLFormat('Ymd'); + $formula = $this->getDateFormat('Ymd'); break; case 'month': - $formula = $this->getSQLFormat('Ym'); + $formula = $this->getDateFormat('Ym'); break; case 'year': - $formula = $this->getSQLFormat('Y'); + $formula = $this->getDateFormat('Y'); break; }