2012-04-10 23:18:20 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
final class PhabricatorSlug {
|
|
|
|
|
|
|
|
public static function normalize($slug) {
|
|
|
|
$slug = preg_replace('@/+@', '/', $slug);
|
|
|
|
$slug = trim($slug, '/');
|
Allow slugs to contain most utf8 characters
Summary:
Ref T2632. Fixes T1466.
Currently, we normalize slugs (and thus Phriction URIs and canonical project names) to a small number of latin characters. Instead, blacklist a few characters and permit everything else (including utf8 characters).
When generating Phriction URIs, encode any utf8 characters. This means we render URIs encoded, but browsers handle this fine and display them readably in the URI and address bar, etc.
The blacklisted characters are mostly for practical reasons: \x00-\x19 are control characters, `#%?` are meaningful in URIs, `+` is sometimes configured to be interprted as space by apache, etc., `<>\\` are just silly, `&= ` are largely cosmetic.
This allows some silly stuff, like generating URIs with zero-width spaces and RTL markers in them. Possibly we should go blacklist those characters at some point.
Depends on: D5191
Test Plan: {F34402}
Reviewers: AnhNhan, chad, vrana
Reviewed By: chad
CC: aran
Maniphest Tasks: T1466, T2632
Differential Revision: https://secure.phabricator.com/D5192
2013-03-03 19:56:33 +01:00
|
|
|
$slug = phutil_utf8_strtolower($slug);
|
|
|
|
$slug = preg_replace("@[\\x00-\\x19#%&+=\\\\?<> ]+@", '_', $slug);
|
|
|
|
$slug = preg_replace('@_+@', '_', $slug);
|
Improve Phriction page move dialog
Summary:
Fixes T5492. I figured this would be easier to just fix than write a guide for; it actually took me an hour, but I spent like 75% of that futzing with my editor.
- The Move controller currently accepts either a slug or an ID. I can't find any callsites which pass a slug, and this doesn't make sense. Pretty sure this was copy/pasted from Edit or something. Only accept IDs.
- Slightly modernize the Move controller (newDialog(), handleRequest(), $viewer).
- When the user enters a bad slug, warn them that we're going to fix it for them and let them accept or reject the changes.
- Don't prefill the edit note (this feels inconsistent/unusual).
- On the form, label the input "Path" instead of "URI".
- Show the old path, to help remind the user what the input should look like.
- When a user tries to do a no-op move, show a more tailored message.
- When the user tries to do an overwriting move, explain how they can fix it.
- When normalizing a slug like `/question/???/mark/`, make it normalize to `/question/_/mark`.
Test Plan:
- Tried to move a document to itself.
- Tried to overwrite a document.
- Did a bad-path move, accepted corrected path.
- Did a good-path move.
- Did a path move with a weird component like `/???/`.
- Added and executed unit tests.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T5492
Differential Revision: https://secure.phabricator.com/D10838
2014-11-12 16:04:51 +01:00
|
|
|
|
|
|
|
// Remove leading and trailing underscores from each component, if the
|
|
|
|
// component has not been reduced to a single underscore. For example, "a?"
|
|
|
|
// converts to "a", but "??" converts to "_".
|
|
|
|
$parts = explode('/', $slug);
|
|
|
|
foreach ($parts as $key => $part) {
|
|
|
|
if ($part != '_') {
|
|
|
|
$parts[$key] = trim($part, '_');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$slug = implode('/', $parts);
|
2012-04-10 23:18:20 +02:00
|
|
|
|
2014-03-14 16:54:26 +01:00
|
|
|
// Specifically rewrite these slugs. It's OK to have a slug like "a..b",
|
|
|
|
// but not a slug which is only "..".
|
|
|
|
|
|
|
|
// NOTE: These are explicitly not pht()'d, because they should be stable
|
|
|
|
// across languages.
|
|
|
|
|
|
|
|
$replace = array(
|
|
|
|
'.' => 'dot',
|
|
|
|
'..' => 'dotdot',
|
|
|
|
);
|
|
|
|
|
|
|
|
foreach ($replace as $pattern => $replacement) {
|
|
|
|
$pattern = preg_quote($pattern, '@');
|
|
|
|
$slug = preg_replace(
|
|
|
|
'@(^|/)'.$pattern.'(\z|/)@',
|
|
|
|
'\1'.$replacement.'\2', $slug);
|
|
|
|
}
|
|
|
|
|
2012-04-10 23:18:20 +02:00
|
|
|
return $slug.'/';
|
|
|
|
}
|
|
|
|
|
|
|
|
public static function getDefaultTitle($slug) {
|
|
|
|
$parts = explode('/', trim($slug, '/'));
|
|
|
|
$default_title = end($parts);
|
|
|
|
$default_title = str_replace('_', ' ', $default_title);
|
Allow slugs to contain most utf8 characters
Summary:
Ref T2632. Fixes T1466.
Currently, we normalize slugs (and thus Phriction URIs and canonical project names) to a small number of latin characters. Instead, blacklist a few characters and permit everything else (including utf8 characters).
When generating Phriction URIs, encode any utf8 characters. This means we render URIs encoded, but browsers handle this fine and display them readably in the URI and address bar, etc.
The blacklisted characters are mostly for practical reasons: \x00-\x19 are control characters, `#%?` are meaningful in URIs, `+` is sometimes configured to be interprted as space by apache, etc., `<>\\` are just silly, `&= ` are largely cosmetic.
This allows some silly stuff, like generating URIs with zero-width spaces and RTL markers in them. Possibly we should go blacklist those characters at some point.
Depends on: D5191
Test Plan: {F34402}
Reviewers: AnhNhan, chad, vrana
Reviewed By: chad
CC: aran
Maniphest Tasks: T1466, T2632
Differential Revision: https://secure.phabricator.com/D5192
2013-03-03 19:56:33 +01:00
|
|
|
$default_title = phutil_utf8_ucwords($default_title);
|
|
|
|
$default_title = nonempty($default_title, pht('Untitled Document'));
|
2012-04-10 23:18:20 +02:00
|
|
|
return $default_title;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static function getAncestry($slug) {
|
|
|
|
$slug = self::normalize($slug);
|
|
|
|
|
|
|
|
if ($slug == '/') {
|
|
|
|
return array();
|
|
|
|
}
|
|
|
|
|
|
|
|
$ancestors = array(
|
|
|
|
'/',
|
|
|
|
);
|
|
|
|
|
|
|
|
$slug = explode('/', $slug);
|
|
|
|
array_pop($slug);
|
|
|
|
array_pop($slug);
|
|
|
|
|
|
|
|
$accumulate = '';
|
|
|
|
foreach ($slug as $part) {
|
|
|
|
$accumulate .= $part.'/';
|
|
|
|
$ancestors[] = $accumulate;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $ancestors;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static function getDepth($slug) {
|
|
|
|
$slug = self::normalize($slug);
|
|
|
|
if ($slug == '/') {
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return substr_count($slug, '/');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|