mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-23 05:50:55 +01:00
PhabricatorSlug
Summary: This is to be used in Phame so the logic is shared where possible. The change has three main things going on - broke out functionality from PhrictionDocument that isn't Phriction specific. - swept up code base to use new PhabricatorSlug class. - altered the regex ever so slightly per discussion and http://stackoverflow.com/questions/2028022/javascript-how-to-convert-unicode-string-to-ascii I think maybe we should punt on unicode here for quite a bit -- http://www.456bereastreet.com/archive/201006/be_careful_with_non-ascii_characters_in_urls/ -- but we'll be well-positioned to add it with the code here. Test Plan: used phriction to create, edit, view documents. used a tool (codemod) for the codebase sweeping Reviewers: epriestley Reviewed By: epriestley CC: aran Differential Revision: https://secure.phabricator.com/D2195
This commit is contained in:
parent
01907bcccc
commit
1175784d5d
26 changed files with 211 additions and 134 deletions
|
@ -862,6 +862,8 @@ phutil_register_library_map(array(
|
|||
'PhabricatorSlowvoteOption' => 'applications/slowvote/storage/option',
|
||||
'PhabricatorSlowvotePoll' => 'applications/slowvote/storage/poll',
|
||||
'PhabricatorSlowvotePollController' => 'applications/slowvote/controller/poll',
|
||||
'PhabricatorSlug' => 'infrastructure/util/slug',
|
||||
'PhabricatorSlugTestCase' => 'infrastructure/util/slug/__tests__',
|
||||
'PhabricatorSortTableExample' => 'applications/uiexample/examples/sorttable',
|
||||
'PhabricatorStandardPageView' => 'view/page/standard',
|
||||
'PhabricatorStatusController' => 'applications/status/base',
|
||||
|
@ -1679,6 +1681,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorSlowvoteOption' => 'PhabricatorSlowvoteDAO',
|
||||
'PhabricatorSlowvotePoll' => 'PhabricatorSlowvoteDAO',
|
||||
'PhabricatorSlowvotePollController' => 'PhabricatorSlowvoteController',
|
||||
'PhabricatorSlugTestCase' => 'PhabricatorTestCase',
|
||||
'PhabricatorSortTableExample' => 'PhabricatorUIExample',
|
||||
'PhabricatorStandardPageView' => 'AphrontPageView',
|
||||
'PhabricatorStatusController' => 'PhabricatorController',
|
||||
|
|
|
@ -46,7 +46,7 @@ final class ConduitAPI_phriction_history_Method
|
|||
$slug = $request->getValue('slug');
|
||||
$doc = id(new PhrictionDocument())->loadOneWhere(
|
||||
'slug = %s',
|
||||
PhrictionDocument::normalizeSlug($slug));
|
||||
PhabricatorSlug::normalize($slug));
|
||||
if (!$doc) {
|
||||
throw new ConduitException('ERR-BAD-DOCUMENT');
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ phutil_require_module('phabricator', 'applications/conduit/method/phriction/base
|
|||
phutil_require_module('phabricator', 'applications/conduit/protocol/exception');
|
||||
phutil_require_module('phabricator', 'applications/phriction/storage/content');
|
||||
phutil_require_module('phabricator', 'applications/phriction/storage/document');
|
||||
phutil_require_module('phabricator', 'infrastructure/util/slug');
|
||||
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ final class ConduitAPI_phriction_info_Method
|
|||
|
||||
$doc = id(new PhrictionDocument())->loadOneWhere(
|
||||
'slug = %s',
|
||||
PhrictionDocument::normalizeSlug($slug));
|
||||
PhabricatorSlug::normalize($slug));
|
||||
|
||||
if (!$doc) {
|
||||
throw new ConduitException('ERR-BAD-DOCUMENT');
|
||||
|
|
|
@ -10,6 +10,7 @@ phutil_require_module('phabricator', 'applications/conduit/method/phriction/base
|
|||
phutil_require_module('phabricator', 'applications/conduit/protocol/exception');
|
||||
phutil_require_module('phabricator', 'applications/phriction/storage/content');
|
||||
phutil_require_module('phabricator', 'applications/phriction/storage/document');
|
||||
phutil_require_module('phabricator', 'infrastructure/util/slug');
|
||||
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ final class PhrictionDocumentController
|
|||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
|
||||
$slug = PhrictionDocument::normalizeSlug($this->slug);
|
||||
$slug = PhabricatorSlug::normalize($this->slug);
|
||||
if ($slug != $this->slug) {
|
||||
$uri = PhrictionDocument::getSlugURI($slug);
|
||||
// Canonicalize pages to their one true URI.
|
||||
|
@ -208,7 +208,7 @@ final class PhrictionDocumentController
|
|||
private function renderBreadcrumbs($slug) {
|
||||
|
||||
$ancestor_handles = array();
|
||||
$ancestral_slugs = PhrictionDocument::getSlugAncestry($slug);
|
||||
$ancestral_slugs = PhabricatorSlug::getAncestry($slug);
|
||||
$ancestral_slugs[] = $slug;
|
||||
if ($ancestral_slugs) {
|
||||
$empty_slugs = array_fill_keys($ancestral_slugs, null);
|
||||
|
@ -230,7 +230,7 @@ final class PhrictionDocumentController
|
|||
$ancestor_handles[] = $handles[$ancestors[$slug]->getPHID()];
|
||||
} else {
|
||||
$handle = new PhabricatorObjectHandle();
|
||||
$handle->setName(PhrictionDocument::getDefaultSlugTitle($slug));
|
||||
$handle->setName(PhabricatorSlug::getDefaultTitle($slug));
|
||||
$handle->setURI(PhrictionDocument::getSlugURI($slug));
|
||||
$ancestor_handles[] = $handle;
|
||||
}
|
||||
|
@ -264,8 +264,8 @@ final class PhrictionDocumentController
|
|||
$conn = $document_dao->establishConnection('r');
|
||||
|
||||
$limit = 50;
|
||||
$d_child = PhrictionDocument::getSlugDepth($slug) + 1;
|
||||
$d_grandchild = PhrictionDocument::getSlugDepth($slug) + 2;
|
||||
$d_child = PhabricatorSlug::getDepth($slug) + 1;
|
||||
$d_grandchild = PhabricatorSlug::getDepth($slug) + 2;
|
||||
|
||||
// Select children and grandchildren.
|
||||
$children = queryfx_all(
|
||||
|
@ -320,7 +320,7 @@ final class PhrictionDocumentController
|
|||
} else {
|
||||
unset($children[$key]);
|
||||
if ($show_grandchildren) {
|
||||
$ancestors = PhrictionDocument::getSlugAncestry($child['slug']);
|
||||
$ancestors = PhabricatorSlug::getAncestry($child['slug']);
|
||||
$grandchildren[end($ancestors)][] = $child;
|
||||
}
|
||||
}
|
||||
|
@ -333,7 +333,7 @@ final class PhrictionDocumentController
|
|||
$children[] = array(
|
||||
'slug' => $slug,
|
||||
'depth' => $d_child,
|
||||
'title' => PhrictionDocument::getDefaultSlugTitle($slug),
|
||||
'title' => PhabricatorSlug::getDefaultTitle($slug),
|
||||
'empty' => true,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ phutil_require_module('phabricator', 'applications/phriction/storage/content');
|
|||
phutil_require_module('phabricator', 'applications/phriction/storage/document');
|
||||
phutil_require_module('phabricator', 'applications/project/storage/project');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/util/slug');
|
||||
phutil_require_module('phabricator', 'storage/queryfx');
|
||||
phutil_require_module('phabricator', 'view/form/error');
|
||||
phutil_require_module('phabricator', 'view/utils');
|
||||
|
|
|
@ -54,7 +54,7 @@ final class PhrictionEditController
|
|||
|
||||
} else {
|
||||
$slug = $request->getStr('slug');
|
||||
$slug = PhrictionDocument::normalizeSlug($slug);
|
||||
$slug = PhabricatorSlug::normalize($slug);
|
||||
if (!$slug) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ final class PhrictionEditController
|
|||
$content = new PhrictionContent();
|
||||
$content->setSlug($slug);
|
||||
|
||||
$default_title = PhrictionDocument::getDefaultSlugTitle($slug);
|
||||
$default_title = PhabricatorSlug::getDefaultTitle($slug);
|
||||
$content->setTitle($default_title);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ phutil_require_module('phabricator', 'applications/phriction/storage/document');
|
|||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/env');
|
||||
phutil_require_module('phabricator', 'infrastructure/javelin/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/util/slug');
|
||||
phutil_require_module('phabricator', 'view/form/base');
|
||||
phutil_require_module('phabricator', 'view/form/control/static');
|
||||
phutil_require_module('phabricator', 'view/form/control/submit');
|
||||
|
|
|
@ -35,7 +35,7 @@ final class PhrictionHistoryController
|
|||
|
||||
$document = id(new PhrictionDocument())->loadOneWhere(
|
||||
'slug = %s',
|
||||
PhrictionDocument::normalizeSlug($this->slug));
|
||||
PhabricatorSlug::normalize($this->slug));
|
||||
|
||||
if (!$document) {
|
||||
return new Aphront404Response();
|
||||
|
|
|
@ -12,6 +12,7 @@ phutil_require_module('phabricator', 'applications/phriction/constants/changetyp
|
|||
phutil_require_module('phabricator', 'applications/phriction/controller/base');
|
||||
phutil_require_module('phabricator', 'applications/phriction/storage/content');
|
||||
phutil_require_module('phabricator', 'applications/phriction/storage/document');
|
||||
phutil_require_module('phabricator', 'infrastructure/util/slug');
|
||||
phutil_require_module('phabricator', 'view/control/pager');
|
||||
phutil_require_module('phabricator', 'view/control/table');
|
||||
phutil_require_module('phabricator', 'view/layout/crumbs');
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -37,7 +37,7 @@ final class PhrictionDocumentEditor {
|
|||
}
|
||||
|
||||
public static function newForSlug($slug) {
|
||||
$slug = PhrictionDocument::normalizeSlug($slug);
|
||||
$slug = PhabricatorSlug::normalize($slug);
|
||||
$document = id(new PhrictionDocument())->loadOneWhere(
|
||||
'slug = %s',
|
||||
$slug);
|
||||
|
@ -51,7 +51,7 @@ final class PhrictionDocumentEditor {
|
|||
}
|
||||
|
||||
if (!$content) {
|
||||
$default_title = PhrictionDocument::getDefaultSlugTitle($slug);
|
||||
$default_title = PhabricatorSlug::getDefaultTitle($slug);
|
||||
$content = new PhrictionContent();
|
||||
$content->setSlug($slug);
|
||||
$content->setTitle($default_title);
|
||||
|
|
|
@ -15,6 +15,7 @@ phutil_require_module('phabricator', 'applications/phriction/storage/content');
|
|||
phutil_require_module('phabricator', 'applications/phriction/storage/document');
|
||||
phutil_require_module('phabricator', 'applications/project/storage/project');
|
||||
phutil_require_module('phabricator', 'applications/search/index/indexer/phriction');
|
||||
phutil_require_module('phabricator', 'infrastructure/util/slug');
|
||||
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
|
|
@ -61,65 +61,9 @@ final class PhrictionDocument extends PhrictionDAO {
|
|||
}
|
||||
}
|
||||
|
||||
public static function normalizeSlug($slug) {
|
||||
|
||||
// TODO: We need to deal with unicode at some point, this is just a very
|
||||
// basic proof-of-concept implementation.
|
||||
|
||||
$slug = strtolower($slug);
|
||||
$slug = preg_replace('@/+@', '/', $slug);
|
||||
$slug = trim($slug, '/');
|
||||
$slug = preg_replace('@[^a-z0-9/]+@', '_', $slug);
|
||||
$slug = trim($slug, '_');
|
||||
|
||||
return $slug.'/';
|
||||
}
|
||||
|
||||
public static function getDefaultSlugTitle($slug) {
|
||||
$parts = explode('/', trim($slug, '/'));
|
||||
$default_title = end($parts);
|
||||
$default_title = str_replace('_', ' ', $default_title);
|
||||
$default_title = ucwords($default_title);
|
||||
$default_title = nonempty($default_title, 'Untitled Document');
|
||||
return $default_title;
|
||||
}
|
||||
|
||||
public static function getSlugAncestry($slug) {
|
||||
$slug = self::normalizeSlug($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 getSlugDepth($slug) {
|
||||
$slug = self::normalizeSlug($slug);
|
||||
if ($slug == '/') {
|
||||
return 0;
|
||||
} else {
|
||||
return substr_count($slug, '/');
|
||||
}
|
||||
}
|
||||
|
||||
public function setSlug($slug) {
|
||||
$this->slug = self::normalizeSlug($slug);
|
||||
$this->depth = self::getSlugDepth($slug);
|
||||
$this->slug = PhabricatorSlug::normalize($slug);
|
||||
$this->depth = PhabricatorSlug::getDepth($slug);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -136,7 +80,7 @@ final class PhrictionDocument extends PhrictionDAO {
|
|||
}
|
||||
|
||||
public static function isProjectSlug($slug) {
|
||||
$slug = self::normalizeSlug($slug);
|
||||
$slug = PhabricatorSlug::normalize($slug);
|
||||
$prefix = 'projects/';
|
||||
if ($slug == $prefix) {
|
||||
// The 'projects/' document is not itself a project slug.
|
||||
|
@ -150,7 +94,7 @@ final class PhrictionDocument extends PhrictionDAO {
|
|||
throw new Exception("Slug '{$slug}' is not a project slug!");
|
||||
}
|
||||
|
||||
$slug = self::normalizeSlug($slug);
|
||||
$slug = PhabricatorSlug::normalize($slug);
|
||||
$parts = explode('/', $slug);
|
||||
return $parts[1].'/';
|
||||
}
|
||||
|
|
|
@ -9,8 +9,7 @@
|
|||
phutil_require_module('phabricator', 'applications/phid/constants');
|
||||
phutil_require_module('phabricator', 'applications/phid/storage/phid');
|
||||
phutil_require_module('phabricator', 'applications/phriction/storage/base');
|
||||
|
||||
phutil_require_module('phutil', 'utils');
|
||||
phutil_require_module('phabricator', 'infrastructure/util/slug');
|
||||
|
||||
|
||||
phutil_require_source('PhrictionDocument.php');
|
||||
|
|
|
@ -21,58 +21,6 @@
|
|||
*/
|
||||
final class PhrictionDocumentTestCase 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/',
|
||||
);
|
||||
|
||||
foreach ($slugs as $slug => $normal) {
|
||||
$this->assertEqual(
|
||||
$normal,
|
||||
PhrictionDocument::normalizeSlug($slug),
|
||||
"Normalization of '{$slug}'");
|
||||
}
|
||||
}
|
||||
|
||||
public function testSlugAncestry() {
|
||||
$slugs = array(
|
||||
'/' => array(),
|
||||
'pokemon/' => array('/'),
|
||||
'pokemon/squirtle/' => array('/', 'pokemon/'),
|
||||
);
|
||||
|
||||
foreach ($slugs as $slug => $ancestry) {
|
||||
$this->assertEqual(
|
||||
$ancestry,
|
||||
PhrictionDocument::getSlugAncestry($slug),
|
||||
"Ancestry of '{$slug}'");
|
||||
}
|
||||
}
|
||||
|
||||
public function testSlugDepth() {
|
||||
$slugs = array(
|
||||
'/' => 0,
|
||||
'a/' => 1,
|
||||
'a/b/' => 2,
|
||||
'a////b/' => 2,
|
||||
);
|
||||
|
||||
foreach ($slugs as $slug => $depth) {
|
||||
$this->assertEqual(
|
||||
$depth,
|
||||
PhrictionDocument::getSlugDepth($slug),
|
||||
"Depth of '{$slug}'");
|
||||
}
|
||||
}
|
||||
|
||||
public function testProjectSlugs() {
|
||||
$slugs = array(
|
||||
'/' => false,
|
||||
|
|
|
@ -60,7 +60,7 @@ final class PhabricatorProjectProfileController
|
|||
|
||||
$external_arrow = "\xE2\x86\x97";
|
||||
$tasks_uri = '/maniphest/view/all/?projects='.$project->getPHID();
|
||||
$slug = PhrictionDocument::normalizeSlug($project->getName());
|
||||
$slug = PhabricatorSlug::normalize($project->getName());
|
||||
$phriction_uri = '/w/projects/'.$slug;
|
||||
|
||||
$edit_uri = '/project/edit/'.$project->getID().'/';
|
||||
|
|
|
@ -13,12 +13,12 @@ phutil_require_module('phabricator', 'applications/files/storage/file');
|
|||
phutil_require_module('phabricator', 'applications/maniphest/query');
|
||||
phutil_require_module('phabricator', 'applications/maniphest/view/tasksummary');
|
||||
phutil_require_module('phabricator', 'applications/phid/handle/data');
|
||||
phutil_require_module('phabricator', 'applications/phriction/storage/document');
|
||||
phutil_require_module('phabricator', 'applications/project/controller/base');
|
||||
phutil_require_module('phabricator', 'applications/project/storage/profile');
|
||||
phutil_require_module('phabricator', 'applications/project/storage/project');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/javelin/markup');
|
||||
phutil_require_module('phabricator', 'infrastructure/util/slug');
|
||||
phutil_require_module('phabricator', 'view/control/table');
|
||||
phutil_require_module('phabricator', 'view/layout/profileheader');
|
||||
phutil_require_module('phabricator', 'view/layout/sidenavfilter');
|
||||
|
|
|
@ -82,7 +82,7 @@ final class PhabricatorProject extends PhabricatorProjectDAO {
|
|||
// 'hack_slash' instead of 'hack/slash').
|
||||
|
||||
$slug = str_replace('/', ' ', $slug);
|
||||
$slug = PhrictionDocument::normalizeSlug($slug);
|
||||
$slug = PhabricatorSlug::normalize($slug);
|
||||
$this->phrictionSlug = $slug;
|
||||
return $this;
|
||||
}
|
||||
|
|
|
@ -8,12 +8,12 @@
|
|||
|
||||
phutil_require_module('phabricator', 'applications/phid/constants');
|
||||
phutil_require_module('phabricator', 'applications/phid/storage/phid');
|
||||
phutil_require_module('phabricator', 'applications/phriction/storage/document');
|
||||
phutil_require_module('phabricator', 'applications/project/constants/status');
|
||||
phutil_require_module('phabricator', 'applications/project/storage/affiliation');
|
||||
phutil_require_module('phabricator', 'applications/project/storage/base');
|
||||
phutil_require_module('phabricator', 'applications/project/storage/profile');
|
||||
phutil_require_module('phabricator', 'applications/project/storage/subproject');
|
||||
phutil_require_module('phabricator', 'infrastructure/util/slug');
|
||||
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ final class PhabricatorRemarkupRulePhriction
|
|||
$name = explode('/', trim($name, '/'));
|
||||
$name = end($name);
|
||||
|
||||
$slug = PhrictionDocument::normalizeSlug($slug);
|
||||
$slug = PhabricatorSlug::normalize($slug);
|
||||
$uri = PhrictionDocument::getSlugURI($slug);
|
||||
|
||||
return $this->getEngine()->storeText(
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/phriction/storage/document');
|
||||
phutil_require_module('phabricator', 'infrastructure/util/slug');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
phutil_require_module('phutil', 'markup/engine/remarkup/markuprule/base');
|
||||
|
|
77
src/infrastructure/util/slug/PhabricatorSlug.php
Normal file
77
src/infrastructure/util/slug/PhabricatorSlug.php
Normal file
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
final class PhabricatorSlug {
|
||||
|
||||
public static function normalize($slug) {
|
||||
|
||||
// TODO: We need to deal with unicode at some point, this is just a very
|
||||
// basic proof-of-concept implementation.
|
||||
|
||||
$slug = strtolower($slug);
|
||||
$slug = preg_replace('@/+@', '/', $slug);
|
||||
$slug = trim($slug, '/');
|
||||
$slug = preg_replace('@[^a-z0-9/]+@', '_', $slug);
|
||||
$slug = trim($slug, '_');
|
||||
|
||||
return $slug.'/';
|
||||
}
|
||||
|
||||
public static function getDefaultTitle($slug) {
|
||||
$parts = explode('/', trim($slug, '/'));
|
||||
$default_title = end($parts);
|
||||
$default_title = str_replace('_', ' ', $default_title);
|
||||
$default_title = ucwords($default_title);
|
||||
$default_title = nonempty($default_title, '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, '/');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
12
src/infrastructure/util/slug/__init__.php
Normal file
12
src/infrastructure/util/slug/__init__.php
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorSlug.php');
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
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\x95O\x95D\x95O" => 't_o_d_o/',
|
||||
);
|
||||
|
||||
foreach ($slugs as $slug => $normal) {
|
||||
$this->assertEqual(
|
||||
$normal,
|
||||
PhabricatorSlug::normalize($slug),
|
||||
"Normalization of '{$slug}'");
|
||||
}
|
||||
}
|
||||
|
||||
public function testSlugAncestry() {
|
||||
$slugs = array(
|
||||
'/' => array(),
|
||||
'pokemon/' => array('/'),
|
||||
'pokemon/squirtle/' => array('/', 'pokemon/'),
|
||||
);
|
||||
|
||||
foreach ($slugs as $slug => $ancestry) {
|
||||
$this->assertEqual(
|
||||
$ancestry,
|
||||
PhabricatorSlug::getAncestry($slug),
|
||||
"Ancestry of '{$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),
|
||||
"Depth of '{$slug}'");
|
||||
}
|
||||
}
|
||||
}
|
13
src/infrastructure/util/slug/__tests__/__init__.php
Normal file
13
src/infrastructure/util/slug/__tests__/__init__.php
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'infrastructure/testing/testcase');
|
||||
phutil_require_module('phabricator', 'infrastructure/util/slug');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorSlugTestCase.php');
|
Loading…
Reference in a new issue