Pull merge.
[yaffs-website] / web / core / modules / views / src / Plugin / views / query / SqliteDateSql.php
1 <?php
2
3 namespace Drupal\views\Plugin\views\query;
4
5 use Drupal\Core\Database\Connection;
6
7 /**
8  * SQLite-specific date handling.
9  *
10  * @internal
11  *   This class should only be used by the Views SQL query plugin.
12  *
13  * @see \Drupal\views\Plugin\views\query\Sql
14  */
15 class SqliteDateSql implements DateSqlInterface {
16
17   /**
18    * The database connection.
19    *
20    * @var \Drupal\Core\Database\Connection
21    */
22   protected $database;
23
24   /**
25    * An array of PHP-to-SQLite date replacement patterns.
26    *
27    * @var array
28    */
29   protected static $replace = [
30     'Y' => '%Y',
31     // No format for 2 digit year number.
32     'y' => '%Y',
33     // No format for 3 letter month name.
34     'M' => '%m',
35     'm' => '%m',
36     // No format for month number without leading zeros.
37     'n' => '%m',
38     // No format for full month name.
39     'F' => '%m',
40     // No format for 3 letter day name.
41     'D' => '%d',
42     'd' => '%d',
43     // No format for full day name.
44     'l' => '%d',
45     // no format for day of month number without leading zeros.
46     'j' => '%d',
47     'W' => '%W',
48     'H' => '%H',
49     // No format for 12 hour hour with leading zeros.
50     'h' => '%H',
51     'i' => '%M',
52     's' => '%S',
53     // No format for AM/PM.
54     'A' => '',
55   ];
56
57   /**
58    * Constructs the SQLite-specific date sql class.
59    *
60    * @param \Drupal\Core\Database\Connection $database
61    *   The database connection.
62    */
63   public function __construct(Connection $database) {
64     $this->database = $database;
65   }
66
67   /**
68    * {@inheritdoc}
69    */
70   public function getDateField($field, $string_date) {
71     if ($string_date) {
72       $field = "strftime('%s', $field)";
73     }
74     return $field;
75   }
76
77   /**
78    * {@inheritdoc}
79    */
80   public function getDateFormat($field, $format) {
81     $format = strtr($format, static::$replace);
82
83     // SQLite does not have a ISO week substitution string, so it needs special
84     // handling.
85     // @see http://wikipedia.org/wiki/ISO_week_date#Calculation
86     // @see http://stackoverflow.com/a/15511864/1499564
87     if ($format === '%W') {
88       $expression = "((strftime('%j', date(strftime('%Y-%m-%d', $field, 'unixepoch'), '-3 days', 'weekday 4')) - 1) / 7 + 1)";
89     }
90     else {
91       $expression = "strftime('$format', $field, 'unixepoch')";
92     }
93     // The expression yields a string, but the comparison value is an integer in
94     // case the comparison value is a float, integer, or numeric. All of the
95     // above SQLite format tokens only produce integers. However, the given
96     // $format may contain 'Y-m-d', which results in a string.
97     // @see \Drupal\Core\Database\Driver\sqlite\Connection::expandArguments()
98     // @see http://www.sqlite.org/lang_datefunc.html
99     // @see http://www.sqlite.org/lang_expr.html#castexpr
100     if (preg_match('/^(?:%\w)+$/', $format)) {
101       $expression = "CAST($expression AS NUMERIC)";
102     }
103     return $expression;
104   }
105
106   /**
107    * {@inheritdoc}
108    */
109   public function setTimezoneOffset($offset) {
110     // Nothing to do here.
111   }
112
113   /**
114    * {@inheritdoc}
115    */
116   public function setFieldTimezoneOffset(&$field, $offset, $string_date = FALSE) {
117     if (!empty($offset)) {
118       $field = "($field + $offset)";
119     }
120   }
121
122 }