mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-26 07:20:57 +01:00
120a7d9164
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
86 lines
2.1 KiB
PHP
86 lines
2.1 KiB
PHP
<?php
|
|
|
|
final class PhabricatorSlug {
|
|
|
|
public static function normalize($slug) {
|
|
$slug = preg_replace('@/+@', '/', $slug);
|
|
$slug = trim($slug, '/');
|
|
$slug = phutil_utf8_strtolower($slug);
|
|
$slug = preg_replace("@[\\x00-\\x19#%&+=\\\\?<> ]+@", '_', $slug);
|
|
$slug = preg_replace('@_+@', '_', $slug);
|
|
|
|
// 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);
|
|
|
|
// 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);
|
|
}
|
|
|
|
return $slug.'/';
|
|
}
|
|
|
|
public static function getDefaultTitle($slug) {
|
|
$parts = explode('/', trim($slug, '/'));
|
|
$default_title = end($parts);
|
|
$default_title = str_replace('_', ' ', $default_title);
|
|
$default_title = phutil_utf8_ucwords($default_title);
|
|
$default_title = nonempty($default_title, pht('Untitled Document'));
|
|
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, '/');
|
|
}
|
|
}
|
|
|
|
}
|