Mercurial > hg > isophonics-drupal-site
comparison core/lib/Drupal/Core/Routing/MatcherDumper.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children | 7a779792577d |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 | |
3 namespace Drupal\Core\Routing; | |
4 | |
5 use Drupal\Core\Database\SchemaObjectExistsException; | |
6 use Drupal\Core\State\StateInterface; | |
7 use Symfony\Component\Routing\RouteCollection; | |
8 | |
9 use Drupal\Core\Database\Connection; | |
10 | |
11 /** | |
12 * Dumps Route information to a database table. | |
13 * | |
14 * @see \Drupal\Core\Routing\RouteProvider | |
15 */ | |
16 class MatcherDumper implements MatcherDumperInterface { | |
17 | |
18 /** | |
19 * The database connection to which to dump route information. | |
20 * | |
21 * @var \Drupal\Core\Database\Connection | |
22 */ | |
23 protected $connection; | |
24 | |
25 /** | |
26 * The routes to be dumped. | |
27 * | |
28 * @var \Symfony\Component\Routing\RouteCollection | |
29 */ | |
30 protected $routes; | |
31 | |
32 /** | |
33 * The state. | |
34 * | |
35 * @var \Drupal\Core\State\StateInterface | |
36 */ | |
37 protected $state; | |
38 | |
39 /** | |
40 * The name of the SQL table to which to dump the routes. | |
41 * | |
42 * @var string | |
43 */ | |
44 protected $tableName; | |
45 | |
46 /** | |
47 * Construct the MatcherDumper. | |
48 * | |
49 * @param \Drupal\Core\Database\Connection $connection | |
50 * The database connection which will be used to store the route | |
51 * information. | |
52 * @param \Drupal\Core\State\StateInterface $state | |
53 * The state. | |
54 * @param string $table | |
55 * (optional) The table to store the route info in. Defaults to 'router'. | |
56 */ | |
57 public function __construct(Connection $connection, StateInterface $state, $table = 'router') { | |
58 $this->connection = $connection; | |
59 $this->state = $state; | |
60 | |
61 $this->tableName = $table; | |
62 } | |
63 | |
64 /** | |
65 * {@inheritdoc} | |
66 */ | |
67 public function addRoutes(RouteCollection $routes) { | |
68 if (empty($this->routes)) { | |
69 $this->routes = $routes; | |
70 } | |
71 else { | |
72 $this->routes->addCollection($routes); | |
73 } | |
74 } | |
75 | |
76 /** | |
77 * Dumps a set of routes to the router table in the database. | |
78 * | |
79 * Available options: | |
80 * - provider: The route grouping that is being dumped. All existing | |
81 * routes with this provider will be deleted on dump. | |
82 * - base_class: The base class name. | |
83 * | |
84 * @param array $options | |
85 * An array of options. | |
86 */ | |
87 public function dump(array $options = []) { | |
88 // Convert all of the routes into database records. | |
89 // Accumulate the menu masks on top of any we found before. | |
90 $masks = array_flip($this->state->get('routing.menu_masks.' . $this->tableName, [])); | |
91 // Delete any old records first, then insert the new ones. That avoids | |
92 // stale data. The transaction makes it atomic to avoid unstable router | |
93 // states due to random failures. | |
94 $transaction = $this->connection->startTransaction(); | |
95 try { | |
96 // We don't use truncate, because it is not guaranteed to be transaction | |
97 // safe. | |
98 try { | |
99 $this->connection->delete($this->tableName) | |
100 ->execute(); | |
101 } | |
102 catch (\Exception $e) { | |
103 $this->ensureTableExists(); | |
104 } | |
105 | |
106 // Split the routes into chunks to avoid big INSERT queries. | |
107 $route_chunks = array_chunk($this->routes->all(), 50, TRUE); | |
108 foreach ($route_chunks as $routes) { | |
109 $insert = $this->connection->insert($this->tableName)->fields([ | |
110 'name', | |
111 'fit', | |
112 'path', | |
113 'pattern_outline', | |
114 'number_parts', | |
115 'route', | |
116 ]); | |
117 $names = []; | |
118 foreach ($routes as $name => $route) { | |
119 /** @var \Symfony\Component\Routing\Route $route */ | |
120 $route->setOption('compiler_class', '\Drupal\Core\Routing\RouteCompiler'); | |
121 /** @var \Drupal\Core\Routing\CompiledRoute $compiled */ | |
122 $compiled = $route->compile(); | |
123 // The fit value is a binary number which has 1 at every fixed path | |
124 // position and 0 where there is a wildcard. We keep track of all such | |
125 // patterns that exist so that we can minimize the number of path | |
126 // patterns we need to check in the RouteProvider. | |
127 $masks[$compiled->getFit()] = 1; | |
128 $names[] = $name; | |
129 $values = [ | |
130 'name' => $name, | |
131 'fit' => $compiled->getFit(), | |
132 'path' => $route->getPath(), | |
133 'pattern_outline' => $compiled->getPatternOutline(), | |
134 'number_parts' => $compiled->getNumParts(), | |
135 'route' => serialize($route), | |
136 ]; | |
137 $insert->values($values); | |
138 } | |
139 | |
140 // Insert all new routes. | |
141 $insert->execute(); | |
142 } | |
143 | |
144 | |
145 } | |
146 catch (\Exception $e) { | |
147 $transaction->rollBack(); | |
148 watchdog_exception('Routing', $e); | |
149 throw $e; | |
150 } | |
151 // Sort the masks so they are in order of descending fit. | |
152 $masks = array_keys($masks); | |
153 rsort($masks); | |
154 $this->state->set('routing.menu_masks.' . $this->tableName, $masks); | |
155 | |
156 $this->routes = NULL; | |
157 } | |
158 | |
159 /** | |
160 * Gets the routes to match. | |
161 * | |
162 * @return \Symfony\Component\Routing\RouteCollection | |
163 * A RouteCollection instance representing all routes currently in the | |
164 * dumper. | |
165 */ | |
166 public function getRoutes() { | |
167 return $this->routes; | |
168 } | |
169 | |
170 /** | |
171 * Checks if the tree table exists and create it if not. | |
172 * | |
173 * @return bool | |
174 * TRUE if the table was created, FALSE otherwise. | |
175 */ | |
176 protected function ensureTableExists() { | |
177 try { | |
178 if (!$this->connection->schema()->tableExists($this->tableName)) { | |
179 $this->connection->schema()->createTable($this->tableName, $this->schemaDefinition()); | |
180 return TRUE; | |
181 } | |
182 } | |
183 catch (SchemaObjectExistsException $e) { | |
184 // If another process has already created the config table, attempting to | |
185 // recreate it will throw an exception. In this case just catch the | |
186 // exception and do nothing. | |
187 return TRUE; | |
188 } | |
189 return FALSE; | |
190 } | |
191 | |
192 /** | |
193 * Defines the schema for the router table. | |
194 * | |
195 * @return array | |
196 * The schema API definition for the SQL storage table. | |
197 * | |
198 * @internal | |
199 */ | |
200 protected function schemaDefinition() { | |
201 $schema = [ | |
202 'description' => 'Maps paths to various callbacks (access, page and title)', | |
203 'fields' => [ | |
204 'name' => [ | |
205 'description' => 'Primary Key: Machine name of this route', | |
206 'type' => 'varchar_ascii', | |
207 'length' => 255, | |
208 'not null' => TRUE, | |
209 'default' => '', | |
210 ], | |
211 'path' => [ | |
212 'description' => 'The path for this URI', | |
213 'type' => 'varchar', | |
214 'length' => 255, | |
215 'not null' => TRUE, | |
216 'default' => '', | |
217 ], | |
218 'pattern_outline' => [ | |
219 'description' => 'The pattern', | |
220 'type' => 'varchar', | |
221 'length' => 255, | |
222 'not null' => TRUE, | |
223 'default' => '', | |
224 ], | |
225 'fit' => [ | |
226 'description' => 'A numeric representation of how specific the path is.', | |
227 'type' => 'int', | |
228 'not null' => TRUE, | |
229 'default' => 0, | |
230 ], | |
231 'route' => [ | |
232 'description' => 'A serialized Route object', | |
233 'type' => 'blob', | |
234 'size' => 'big', | |
235 ], | |
236 'number_parts' => [ | |
237 'description' => 'Number of parts in this router path.', | |
238 'type' => 'int', | |
239 'not null' => TRUE, | |
240 'default' => 0, | |
241 'size' => 'small', | |
242 ], | |
243 ], | |
244 'indexes' => [ | |
245 'pattern_outline_parts' => ['pattern_outline', 'number_parts'], | |
246 ], | |
247 'primary key' => ['name'], | |
248 ]; | |
249 | |
250 return $schema; | |
251 } | |
252 | |
253 } |