Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
project
drupal
Commits
2c79c025
Commit
2c79c025
authored
May 28, 2012
by
Larry Garfield
Committed by
Alex Bronstein
Oct 01, 2012
Browse files
Copy in old dumping logic. Still being refactored.
parent
eba77ad5
Changes
1
Hide whitespace changes
Inline
Side-by-side
core/lib/Drupal/Core/Routing/UrlMatcherDumper.php
View file @
2c79c025
...
...
@@ -3,17 +3,21 @@
namespace
Drupal\Core\Routing
;
use
Symfony\Component\Routing\Matcher\Dumper\MatcherDumperInterface
;
use
Symfony\Component\Routing\Route
;
use
Symfony\Component\Routing\RouteCollection
;
use
Drupal\Core\Database\Connection
;
/**
* Description of UrlMatcherDumper
*
* @author crell
* Description of UrlMatcherDumper.
*/
class
UrlMatcherDumper
implements
MatcherDumperInterface
{
/**
* The maximum number of path elements for a route pattern;
*/
const
MAX_PARTS
=
9
;
/**
* The database connection to which to dump route information.
*
...
...
@@ -58,7 +62,34 @@ public function addRoutes(RouteCollection $routes) {
*
* @return string A PHP class representing the matcher class
*/
function
dump
(
array
$options
=
array
())
{
public
function
dump
(
array
$options
=
array
())
{
$options
+=
array
(
'route_set'
=>
''
,
);
$compiled
=
$this
->
compileRoutes
(
$this
->
routes
,
$route_set
);
// Convert all of the routes into database records.
$insert
=
$this
->
connection
->
insert
(
'router'
);
foreach
(
$this
->
routes
as
$name
=>
$route
)
{
$insert
->
values
(
$record
);
}
// Delete any old records in this route set first, then insert the new ones.
// That avoids stale data. The transaction makes it atomic to avoid
// unstable router states due to random failures.
$txn
=
$this
->
connection
->
startTransaction
();
$this
->
connection
->
delete
(
'router'
)
->
condition
(
'route_set'
,
$options
[
'route_set'
])
->
execute
();
$insert
->
execute
();
// Transaction ends here.
}
...
...
@@ -67,8 +98,187 @@ function dump(array $options = array()) {
*
* @return RouteCollection A RouteCollection instance
*/
function
getRoutes
()
{
public
function
getRoutes
()
{
return
$this
->
routes
;
}
protected
function
compileRoutes
(
RouteCollection
$routes
,
$route_set
)
{
// First pass: separate callbacks from paths, making paths ready for
// matching. Calculate fitness, and fill some default values.
$menu
=
array
();
$masks
=
array
();
foreach
(
$routes
as
$name
=>
$item
)
{
$path
=
$item
->
getPattern
();
$move
=
FALSE
;
$parts
=
explode
(
'/'
,
$path
,
static
::
MAX_PARTS
);
$number_parts
=
count
(
$parts
);
// We store the highest index of parts here to save some work in the fit
// calculation loop.
$slashes
=
$number_parts
-
1
;
$num_placeholders
=
count
(
array_filter
(
$parts
,
function
(
$value
)
{
return
strpos
(
$value
,
'{'
)
!==
FALSE
;
}));
$fit
=
$this
->
getFit
(
$path
);
if
(
$fit
)
{
$move
=
TRUE
;
}
else
{
// If there is no placeholder, it fits maximally.
$fit
=
(
1
<<
$number_parts
)
-
1
;
}
$masks
[
$fit
]
=
1
;
$item
+=
array
(
'title'
=>
''
,
'weight'
=>
0
,
'type'
=>
MENU_NORMAL_ITEM
,
'module'
=>
''
,
'_number_parts'
=>
$number_parts
,
'_parts'
=>
$parts
,
'_fit'
=>
$fit
,
);
if
(
$move
)
{
$new_path
=
implode
(
'/'
,
$item
[
'_parts'
]);
$menu
[
$new_path
]
=
$item
;
$sort
[
$new_path
]
=
$number_parts
;
}
else
{
$menu
[
$path
]
=
$item
;
$sort
[
$path
]
=
$number_parts
;
}
}
// Sort the route list.
array_multisort
(
$sort
,
SORT_NUMERIC
,
$menu
);
// Apply inheritance rules.
foreach
(
$menu
as
$path
=>
$v
)
{
$item
=
&
$menu
[
$path
];
for
(
$i
=
$item
[
'_number_parts'
]
-
1
;
$i
;
$i
--
)
{
$parent_path
=
implode
(
'/'
,
array_slice
(
$item
[
'_parts'
],
0
,
$i
));
if
(
isset
(
$menu
[
$parent_path
]))
{
$parent
=
&
$menu
[
$parent_path
];
// If an access callback is not found for a default local task we use
// the callback from the parent, since we expect them to be identical.
// In all other cases, the access parameters must be specified.
if
((
$item
[
'type'
]
==
MENU_DEFAULT_LOCAL_TASK
)
&&
!
isset
(
$item
[
'access callback'
])
&&
isset
(
$parent
[
'access callback'
]))
{
$item
[
'access callback'
]
=
$parent
[
'access callback'
];
if
(
!
isset
(
$item
[
'access arguments'
])
&&
isset
(
$parent
[
'access arguments'
]))
{
$item
[
'access arguments'
]
=
$parent
[
'access arguments'
];
}
}
// Same for theme callbacks.
if
(
!
isset
(
$item
[
'theme callback'
])
&&
isset
(
$parent
[
'theme callback'
]))
{
$item
[
'theme callback'
]
=
$parent
[
'theme callback'
];
if
(
!
isset
(
$item
[
'theme arguments'
])
&&
isset
(
$parent
[
'theme arguments'
]))
{
$item
[
'theme arguments'
]
=
$parent
[
'theme arguments'
];
}
}
}
}
if
(
!
isset
(
$item
[
'access callback'
])
&&
isset
(
$item
[
'access arguments'
]))
{
// Default callback.
$item
[
'access callback'
]
=
'user_access'
;
}
if
(
!
isset
(
$item
[
'access callback'
])
||
empty
(
$item
[
'page callback'
]))
{
$item
[
'access callback'
]
=
0
;
}
if
(
is_bool
(
$item
[
'access callback'
]))
{
$item
[
'access callback'
]
=
intval
(
$item
[
'access callback'
]);
}
$item
+=
array
(
'access arguments'
=>
array
(),
'access callback'
=>
''
,
'page arguments'
=>
array
(),
'page callback'
=>
''
,
'delivery callback'
=>
''
,
'title arguments'
=>
array
(),
'title callback'
=>
't'
,
'theme arguments'
=>
array
(),
'theme callback'
=>
''
,
'description'
=>
''
,
'position'
=>
''
,
'context'
=>
0
,
'tab_parent'
=>
''
,
'tab_root'
=>
$path
,
'path'
=>
$path
,
'file'
=>
''
,
'file path'
=>
''
,
'include file'
=>
''
,
);
// Calculate out the file to be included for each callback, if any.
if
(
$item
[
'file'
])
{
$file_path
=
$item
[
'file path'
]
?
$item
[
'file path'
]
:
drupal_get_path
(
'module'
,
$item
[
'module'
]);
$item
[
'include file'
]
=
$file_path
.
'/'
.
$item
[
'file'
];
}
}
// Sort the masks so they are in order of descending fit.
$masks
=
array_keys
(
$masks
);
rsort
(
$masks
);
return
array
(
$menu
,
$masks
);
// The old menu_router record structure, copied here for easy referencing.
array
(
'path'
=>
$item
[
'path'
],
'load_functions'
=>
$item
[
'load_functions'
],
'to_arg_functions'
=>
$item
[
'to_arg_functions'
],
'access_callback'
=>
$item
[
'access callback'
],
'access_arguments'
=>
serialize
(
$item
[
'access arguments'
]),
'page_callback'
=>
$item
[
'page callback'
],
'page_arguments'
=>
serialize
(
$item
[
'page arguments'
]),
'delivery_callback'
=>
$item
[
'delivery callback'
],
'fit'
=>
$item
[
'_fit'
],
'number_parts'
=>
$item
[
'_number_parts'
],
'context'
=>
$item
[
'context'
],
'tab_parent'
=>
$item
[
'tab_parent'
],
'tab_root'
=>
$item
[
'tab_root'
],
'title'
=>
$item
[
'title'
],
'title_callback'
=>
$item
[
'title callback'
],
'title_arguments'
=>
(
$item
[
'title arguments'
]
?
serialize
(
$item
[
'title arguments'
])
:
''
),
'theme_callback'
=>
$item
[
'theme callback'
],
'theme_arguments'
=>
serialize
(
$item
[
'theme arguments'
]),
'type'
=>
$item
[
'type'
],
'description'
=>
$item
[
'description'
],
'position'
=>
$item
[
'position'
],
'weight'
=>
$item
[
'weight'
],
'include_file'
=>
$item
[
'include file'
],
);
}
/**
* Determines the fitness of the provided path.
*
* @param string $path
* The path whose fitness we want.
*
* @return int
* The fitness of the path, as an integer.
*/
public
function
getFit
(
$path
)
{
$fit
=
0
;
$parts
=
explode
(
'/'
,
$path
,
static
::
MAX_PARTS
);
foreach
(
$parts
as
$k
=>
$part
)
{
if
(
strpos
(
$part
,
'{'
)
===
FALSE
)
{
$fit
|=
1
<<
(
$slashes
-
$k
);
}
}
return
$fit
;
}
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment