Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/infrastructure/util/PhabricatorSlug.php b/src/infrastructure/util/PhabricatorSlug.php
index a6cf0bc70c..fd169914fe 100644
--- a/src/infrastructure/util/PhabricatorSlug.php
+++ b/src/infrastructure/util/PhabricatorSlug.php
@@ -1,125 +1,118 @@
<?php
final class PhabricatorSlug extends Phobject {
public static function normalizeProjectSlug($slug) {
$slug = str_replace('/', ' ', $slug);
$slug = self::normalize($slug, $hashtag = true);
return rtrim($slug, '/');
}
public static function normalize($slug, $hashtag = false) {
$slug = preg_replace('@/+@', '/', $slug);
$slug = trim($slug, '/');
$slug = phutil_utf8_strtolower($slug);
$ban =
// Ban control characters since users can't type them and they create
// various other problems with parsing and rendering.
"\\x00-\\x19".
// Ban characters with special meanings in URIs (and spaces), since we
// want slugs to produce nice URIs.
"#%&+=?".
" ".
// Ban backslashes and various brackets for parsing and URI quality.
"\\\\".
"<>{}\\[\\]".
// Ban single and double quotes since they can mess up URIs.
"'".
'"';
// In hashtag mode (used for Project hashtags), ban additional characters
// which cause parsing problems.
if ($hashtag) {
$ban .= '`~!@$^*,:;(|)';
}
$slug = preg_replace('(['.$ban.']+)', '_', $slug);
$slug = preg_replace('@_+@', '_', $slug);
$parts = explode('/', $slug);
- // Convert "_-_" into "-". This is a little nicer for inputs with
- // hyphens used as internal separators, and turns an input like "A - B"
- // into "a-b" instead of "a_-_b";
- foreach ($parts as $key => $part) {
- $parts[$key] = str_replace('_-_', '-', $part);
- }
-
// 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 "_".
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, '/');
}
}
}
diff --git a/src/infrastructure/util/__tests__/PhabricatorSlugTestCase.php b/src/infrastructure/util/__tests__/PhabricatorSlugTestCase.php
index e493ab7363..6a801bb54c 100644
--- a/src/infrastructure/util/__tests__/PhabricatorSlugTestCase.php
+++ b/src/infrastructure/util/__tests__/PhabricatorSlugTestCase.php
@@ -1,98 +1,98 @@
<?php
final class PhabricatorSlugTestCase extends PhabricatorTestCase {
public function testSlugNormalization() {
$slugs = array(
'' => '/',
'/' => '/',
'//' => '/',
'&&&' => '_/',
'/derp/' => 'derp/',
'derp' => 'derp/',
'derp//derp' => 'derp/derp/',
'DERP//DERP' => 'derp/derp/',
'a B c' => 'a_b_c/',
'-1~2.3abcd' => '-1~2.3abcd/',
"T\x00O\x00D\x00O" => 't_o_d_o/',
'x#%&+=\\?<> y' => 'x_y/',
"\xE2\x98\x83" => "\xE2\x98\x83/",
'..' => 'dotdot/',
'../' => 'dotdot/',
'/../' => 'dotdot/',
'a/b' => 'a/b/',
'a//b' => 'a/b/',
'a/../b/' => 'a/dotdot/b/',
'/../a' => 'dotdot/a/',
'../a' => 'dotdot/a/',
'a/..' => 'a/dotdot/',
'a/../' => 'a/dotdot/',
'a?' => 'a/',
'??' => '_/',
'a/?' => 'a/_/',
'??/a/??' => '_/a/_/',
'a/??/c' => 'a/_/c/',
'a/?b/c' => 'a/b/c/',
'a/b?/c' => 'a/b/c/',
- 'a - b' => 'a-b/',
+ 'a - b' => 'a_-_b/',
'a[b]' => 'a_b/',
'ab!' => 'ab!/',
);
foreach ($slugs as $slug => $normal) {
$this->assertEqual(
$normal,
PhabricatorSlug::normalize($slug),
pht("Normalization of '%s'", $slug));
}
}
public function testProjectSlugs() {
$slugs = array(
'a:b' => 'a_b',
'a!b' => 'a_b',
- 'a - b' => 'a-b',
+ 'a - b' => 'a_-_b',
'' => '',
'Demonology: HSA (Hexes, Signs, Alchemy)' =>
'demonology_hsa_hexes_signs_alchemy',
);
foreach ($slugs as $slug => $normal) {
$this->assertEqual(
$normal,
PhabricatorSlug::normalizeProjectSlug($slug),
pht('Hashtag normalization of "%s"', $slug));
}
}
public function testSlugAncestry() {
$slugs = array(
'/' => array(),
'pokemon/' => array('/'),
'pokemon/squirtle/' => array('/', 'pokemon/'),
);
foreach ($slugs as $slug => $ancestry) {
$this->assertEqual(
$ancestry,
PhabricatorSlug::getAncestry($slug),
pht("Ancestry of '%s'", $slug));
}
}
public function testSlugDepth() {
$slugs = array(
'/' => 0,
'a/' => 1,
'a/b/' => 2,
'a////b/' => 2,
);
foreach ($slugs as $slug => $depth) {
$this->assertEqual(
$depth,
PhabricatorSlug::getDepth($slug),
pht("Depth of '%s'", $slug));
}
}
}

File Metadata

Mime Type
text/x-diff
Expires
Sat, Sep 20, 4:37 AM (1 d, 9 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
240789
Default Alt Text
(6 KB)

Event Timeline