From 212b0d29c54f079dee5643c54b1e930690b4a059 Mon Sep 17 00:00:00 2001 From: Joshua Spence Date: Mon, 22 Sep 2014 18:50:20 +1000 Subject: [PATCH 01/24] Add an acceptance test for Celerity maps Summary: Fixes T5374. Add an acceptance test to the `PhabricatorInfrastructureTestCase` class which fails if a Celerity map is not up-to-date. In order to achieve this, a lot of code used to generate Celerity maps was transferred from `CelerityManagementMapWorkflow` to `CelerityResourceMap` and `CelerityResourceMapGenerator`. Test Plan: Ran `arc unit` and noticed that all tests passed. Modified a JavaScript file and ran `arc unit` again (without running `./bin/celerity map`)... this time the test failed, as expected. Reviewers: epriestley, #blessed_reviewers Reviewed By: epriestley, #blessed_reviewers Subscribers: epriestley, Korvin Maniphest Tasks: T5374 Differential Revision: https://secure.phabricator.com/D9817 --- src/__phutil_library_map__.php | 3 + src/__tests__/PhabricatorCelerityTestCase.php | 33 ++ .../celerity/CelerityResourceMap.php | 16 + .../celerity/CelerityResourceMapGenerator.php | 361 ++++++++++++++++++ .../CelerityManagementMapWorkflow.php | 325 +--------------- 5 files changed, 418 insertions(+), 320 deletions(-) create mode 100644 src/__tests__/PhabricatorCelerityTestCase.php create mode 100644 src/infrastructure/celerity/CelerityResourceMapGenerator.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 726f77c881..fc4f8c1b35 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -111,6 +111,7 @@ phutil_register_library_map(array( 'CelerityResourceController' => 'infrastructure/celerity/CelerityResourceController.php', 'CelerityResourceGraph' => 'infrastructure/celerity/CelerityResourceGraph.php', 'CelerityResourceMap' => 'infrastructure/celerity/CelerityResourceMap.php', + 'CelerityResourceMapGenerator' => 'infrastructure/celerity/CelerityResourceMapGenerator.php', 'CelerityResourceTransformer' => 'infrastructure/celerity/CelerityResourceTransformer.php', 'CelerityResourceTransformerTestCase' => 'infrastructure/celerity/__tests__/CelerityResourceTransformerTestCase.php', 'CelerityResources' => 'infrastructure/celerity/resources/CelerityResources.php', @@ -1304,6 +1305,7 @@ phutil_register_library_map(array( 'PhabricatorCalendarSchemaSpec' => 'applications/calendar/storage/PhabricatorCalendarSchemaSpec.php', 'PhabricatorCalendarViewController' => 'applications/calendar/controller/PhabricatorCalendarViewController.php', 'PhabricatorCampfireProtocolAdapter' => 'infrastructure/daemon/bot/adapter/PhabricatorCampfireProtocolAdapter.php', + 'PhabricatorCelerityTestCase' => '__tests__/PhabricatorCelerityTestCase.php', 'PhabricatorChangeParserTestCase' => 'applications/repository/worker/__tests__/PhabricatorChangeParserTestCase.php', 'PhabricatorChangesetResponse' => 'infrastructure/diff/PhabricatorChangesetResponse.php', 'PhabricatorChatLogApplication' => 'applications/chatlog/application/PhabricatorChatLogApplication.php', @@ -4216,6 +4218,7 @@ phutil_register_library_map(array( 'PhabricatorCalendarSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorCalendarViewController' => 'PhabricatorCalendarController', 'PhabricatorCampfireProtocolAdapter' => 'PhabricatorBotBaseStreamingProtocolAdapter', + 'PhabricatorCelerityTestCase' => 'PhabricatorTestCase', 'PhabricatorChangeParserTestCase' => 'PhabricatorWorkingCopyTestCase', 'PhabricatorChangesetResponse' => 'AphrontProxyResponse', 'PhabricatorChatLogApplication' => 'PhabricatorApplication', diff --git a/src/__tests__/PhabricatorCelerityTestCase.php b/src/__tests__/PhabricatorCelerityTestCase.php new file mode 100644 index 0000000000..d36ef051c8 --- /dev/null +++ b/src/__tests__/PhabricatorCelerityTestCase.php @@ -0,0 +1,33 @@ +generate(); + + $this->assertEqual( + $new_map->getNameMap(), + $old_map->getNameMap()); + $this->assertEqual( + $new_map->getSymbolMap(), + $old_map->getSymbolMap()); + $this->assertEqual( + $new_map->getRequiresMap(), + $old_map->getRequiresMap()); + $this->assertEqual( + $new_map->getPackageMap(), + $old_map->getPackageMap()); + } + } + +} diff --git a/src/infrastructure/celerity/CelerityResourceMap.php b/src/infrastructure/celerity/CelerityResourceMap.php index 030fd3233d..5b0c374dab 100644 --- a/src/infrastructure/celerity/CelerityResourceMap.php +++ b/src/infrastructure/celerity/CelerityResourceMap.php @@ -53,6 +53,22 @@ final class CelerityResourceMap { return self::$instances[$name]; } + public function getNameMap() { + return $this->nameMap; + } + + public function getSymbolMap() { + return $this->symbolMap; + } + + public function getRequiresMap() { + return $this->requiresMap; + } + + public function getPackageMap() { + return $this->packageMap; + } + public function getPackagedNamesForSymbols(array $symbols) { $resolved = $this->resolveResources($symbols); return $this->packageResources($resolved); diff --git a/src/infrastructure/celerity/CelerityResourceMapGenerator.php b/src/infrastructure/celerity/CelerityResourceMapGenerator.php new file mode 100644 index 0000000000..b7a1dfb563 --- /dev/null +++ b/src/infrastructure/celerity/CelerityResourceMapGenerator.php @@ -0,0 +1,361 @@ +resources = $resources; + } + + public function getNameMap() { + return $this->nameMap; + } + + public function getSymbolMap() { + return $this->symbolMap; + } + + public function getRequiresMap() { + return $this->requiresMap; + } + + public function getPackageMap() { + return $this->packageMap; + } + + public function setDebug($debug) { + $this->debug = $debug; + return $this; + } + + protected function log($message) { + if ($this->debug) { + $console = PhutilConsole::getConsole(); + $console->writeErr("%s\n", $message); + } + } + + public function generate() { + $binary_map = $this->rebuildBinaryResources($this->resources); + + $this->log(pht('Found %d binary resources.', count($binary_map))); + + $xformer = id(new CelerityResourceTransformer()) + ->setMinify(false) + ->setRawURIMap(ipull($binary_map, 'uri')); + + $text_map = $this->rebuildTextResources($this->resources, $xformer); + + $this->log(pht('Found %d text resources.', count($text_map))); + + $resource_graph = array(); + $requires_map = array(); + $symbol_map = array(); + foreach ($text_map as $name => $info) { + if (isset($info['provides'])) { + $symbol_map[$info['provides']] = $info['hash']; + + // We only need to check for cycles and add this to the requires map + // if it actually requires anything. + if (!empty($info['requires'])) { + $resource_graph[$info['provides']] = $info['requires']; + $requires_map[$info['hash']] = $info['requires']; + } + } + } + + $this->detectGraphCycles($resource_graph); + $name_map = ipull($binary_map, 'hash') + ipull($text_map, 'hash'); + $hash_map = array_flip($name_map); + + $package_map = $this->rebuildPackages( + $this->resources, + $symbol_map, + $hash_map); + + $this->log(pht('Found %d packages.', count($package_map))); + + $component_map = array(); + foreach ($package_map as $package_name => $package_info) { + foreach ($package_info['symbols'] as $symbol) { + $component_map[$symbol] = $package_name; + } + } + + $name_map = $this->mergeNameMaps( + array( + array(pht('Binary'), ipull($binary_map, 'hash')), + array(pht('Text'), ipull($text_map, 'hash')), + array(pht('Package'), ipull($package_map, 'hash')), + )); + $package_map = ipull($package_map, 'symbols'); + + ksort($name_map); + ksort($symbol_map); + ksort($requires_map); + ksort($package_map); + + $this->nameMap = $name_map; + $this->symbolMap = $symbol_map; + $this->requiresMap = $requires_map; + $this->packageMap = $package_map; + + return $this; + } + + public function write() { + $map_content = $this->formatMapContent(array( + 'names' => $this->getNameMap(), + 'symbols' => $this->getSymbolMap(), + 'requires' => $this->getRequiresMap(), + 'packages' => $this->getPackageMap(), + )); + + $map_path = $this->resources->getPathToMap(); + $this->log(pht('Writing map "%s".', Filesystem::readablePath($map_path))); + Filesystem::writeFile($map_path, $map_content); + + return $this; + } + + private function formatMapContent(array $data) { + $content = phutil_var_export($data); + $generated = '@'.'generated'; + + return <<> Resource information map. + */ + private function rebuildBinaryResources( + CelerityPhysicalResources $resources) { + + $binary_map = $resources->findBinaryResources(); + $result_map = array(); + + foreach ($binary_map as $name => $data_hash) { + $hash = $resources->getCelerityHash($data_hash.$name); + + $result_map[$name] = array( + 'hash' => $hash, + 'uri' => $resources->getResourceURI($hash, $name), + ); + } + + return $result_map; + } + + /** + * Find text resources (like JS and CSS) and return information about them. + * + * @param CelerityPhysicalResources Resource map to find text resources for. + * @param CelerityResourceTransformer Configured resource transformer. + * @return map> Resource information map. + */ + private function rebuildTextResources( + CelerityPhysicalResources $resources, + CelerityResourceTransformer $xformer) { + + $text_map = $resources->findTextResources(); + $result_map = array(); + + foreach ($text_map as $name => $data_hash) { + $raw_data = $resources->getResourceData($name); + $xformed_data = $xformer->transformResource($name, $raw_data); + + $data_hash = $resources->getCelerityHash($xformed_data); + $hash = $resources->getCelerityHash($data_hash.$name); + + list($provides, $requires) = $this->getProvidesAndRequires( + $name, + $raw_data); + + $result_map[$name] = array( + 'hash' => $hash, + ); + + if ($provides !== null) { + $result_map[$name] += array( + 'provides' => $provides, + 'requires' => $requires, + ); + } + } + + return $result_map; + } + + /** + * Parse the `@provides` and `@requires` symbols out of a text resource, like + * JS or CSS. + * + * @param string Resource name. + * @param string Resource data. + * @return pair|null> The `@provides` symbol and + * the list of `@requires` symbols. If the resource is not part of the + * dependency graph, both are null. + */ + private function getProvidesAndRequires($name, $data) { + $parser = new PhutilDocblockParser(); + + $matches = array(); + $ok = preg_match('@/[*][*].*?[*]/@s', $data, $matches); + if (!$ok) { + throw new Exception( + pht( + 'Resource "%s" does not have a header doc comment. Encode '. + 'dependency data in a header docblock.', + $name)); + } + + list($description, $metadata) = $parser->parse($matches[0]); + + $provides = preg_split('/\s+/', trim(idx($metadata, 'provides'))); + $requires = preg_split('/\s+/', trim(idx($metadata, 'requires'))); + $provides = array_filter($provides); + $requires = array_filter($requires); + + if (!$provides) { + // Tests and documentation-only JS is permitted to @provide no targets. + return array(null, null); + } + + if (count($provides) > 1) { + throw new Exception( + pht('Resource "%s" must @provide at most one Celerity target.', $name)); + } + + return array(head($provides), $requires); + } + + /** + * Check for dependency cycles in the resource graph. Raises an exception if + * a cycle is detected. + * + * @param map> Map of `@provides` symbols to their + * `@requires` symbols. + * @return void + */ + private function detectGraphCycles(array $nodes) { + $graph = id(new CelerityResourceGraph()) + ->addNodes($nodes) + ->setResourceGraph($nodes) + ->loadGraph(); + + foreach ($nodes as $provides => $requires) { + $cycle = $graph->detectCycles($provides); + if ($cycle) { + throw new Exception( + pht('Cycle detected in resource graph: %s', implode(' > ', $cycle))); + } + } + } + + /** + * Build package specifications for a given resource source. + * + * @param CelerityPhysicalResources Resource source to rebuild. + * @param map Map of `@provides` to hashes. + * @param map Map of hashes to resource names. + * @return map> Package information maps. + */ + private function rebuildPackages( + CelerityPhysicalResources $resources, + array $symbol_map, + array $reverse_map) { + + $package_map = array(); + + $package_spec = $resources->getResourcePackages(); + foreach ($package_spec as $package_name => $package_symbols) { + $type = null; + $hashes = array(); + foreach ($package_symbols as $symbol) { + $symbol_hash = idx($symbol_map, $symbol); + if ($symbol_hash === null) { + throw new Exception( + pht( + 'Package specification for "%s" includes "%s", but that symbol '. + 'is not @provided by any resource.', + $package_name, + $symbol)); + } + + $resource_name = $reverse_map[$symbol_hash]; + $resource_type = $resources->getResourceType($resource_name); + if ($type === null) { + $type = $resource_type; + } else if ($type !== $resource_type) { + throw new Exception( + pht( + 'Package specification for "%s" includes resources of multiple '. + 'types (%s, %s). Each package may only contain one type of '. + 'resource.', + $package_name, + $type, + $resource_type)); + } + + $hashes[] = $symbol.':'.$symbol_hash; + } + + $hash = $resources->getCelerityHash(implode("\n", $hashes)); + $package_map[$package_name] = array( + 'hash' => $hash, + 'symbols' => $package_symbols, + ); + } + + return $package_map; + } + + private function mergeNameMaps(array $maps) { + $result = array(); + $origin = array(); + + foreach ($maps as $map) { + list($map_name, $data) = $map; + foreach ($data as $name => $hash) { + if (empty($result[$name])) { + $result[$name] = $hash; + $origin[$name] = $map_name; + } else { + $old = $origin[$name]; + $new = $map_name; + throw new Exception( + pht( + 'Resource source defines two resources with the same name, '. + '"%s". One is defined in the "%s" map; the other in the "%s" '. + 'map. Each resource must have a unique name.', + $name, + $old, + $new)); + } + } + } + return $result; + } + +} diff --git a/src/infrastructure/celerity/management/CelerityManagementMapWorkflow.php b/src/infrastructure/celerity/management/CelerityManagementMapWorkflow.php index 81179c086e..be844137e2 100644 --- a/src/infrastructure/celerity/management/CelerityManagementMapWorkflow.php +++ b/src/infrastructure/celerity/management/CelerityManagementMapWorkflow.php @@ -42,330 +42,15 @@ final class CelerityManagementMapWorkflow $resources->getName(), get_class($resources))); - $binary_map = $this->rebuildBinaryResources($resources); - - $this->log( - pht( - 'Found %d binary resources.', - new PhutilNumber(count($binary_map)))); - - $xformer = id(new CelerityResourceTransformer()) - ->setMinify(false) - ->setRawURIMap(ipull($binary_map, 'uri')); - - $text_map = $this->rebuildTextResources($resources, $xformer); - - $this->log( - pht( - 'Found %d text resources.', - new PhutilNumber(count($text_map)))); - - $resource_graph = array(); - $requires_map = array(); - $symbol_map = array(); - foreach ($text_map as $name => $info) { - if (isset($info['provides'])) { - $symbol_map[$info['provides']] = $info['hash']; - - // We only need to check for cycles and add this to the requires map - // if it actually requires anything. - if (!empty($info['requires'])) { - $resource_graph[$info['provides']] = $info['requires']; - $requires_map[$info['hash']] = $info['requires']; - } - } - } - - $this->detectGraphCycles($resource_graph); - $name_map = ipull($binary_map, 'hash') + ipull($text_map, 'hash'); - $hash_map = array_flip($name_map); - - $package_map = $this->rebuildPackages( - $resources, - $symbol_map, - $hash_map); - - $this->log( - pht( - 'Found %d packages.', - new PhutilNumber(count($package_map)))); - - $component_map = array(); - foreach ($package_map as $package_name => $package_info) { - foreach ($package_info['symbols'] as $symbol) { - $component_map[$symbol] = $package_name; - } - } - - $name_map = $this->mergeNameMaps( - array( - array(pht('Binary'), ipull($binary_map, 'hash')), - array(pht('Text'), ipull($text_map, 'hash')), - array(pht('Package'), ipull($package_map, 'hash')), - )); - $package_map = ipull($package_map, 'symbols'); - - ksort($name_map); - ksort($symbol_map); - ksort($requires_map); - ksort($package_map); - - $map_content = $this->formatMapContent(array( - 'names' => $name_map, - 'symbols' => $symbol_map, - 'requires' => $requires_map, - 'packages' => $package_map, - )); - - $map_path = $resources->getPathToMap(); - $this->log(pht('Writing map "%s".', Filesystem::readablePath($map_path))); - Filesystem::writeFile($map_path, $map_content); + id(new CelerityResourceMapGenerator($resources)) + ->setDebug(true) + ->generate() + ->write(); } - - /** - * Find binary resources (like PNG and SWF) and return information about - * them. - * - * @param CelerityPhysicalResources Resource map to find binary resources for. - * @return map> Resource information map. - */ - private function rebuildBinaryResources( - CelerityPhysicalResources $resources) { - - $binary_map = $resources->findBinaryResources(); - - $result_map = array(); - foreach ($binary_map as $name => $data_hash) { - $hash = $resources->getCelerityHash($data_hash.$name); - - $result_map[$name] = array( - 'hash' => $hash, - 'uri' => $resources->getResourceURI($hash, $name), - ); - } - - return $result_map; - } - - - /** - * Find text resources (like JS and CSS) and return information about them. - * - * @param CelerityPhysicalResources Resource map to find text resources for. - * @param CelerityResourceTransformer Configured resource transformer. - * @return map> Resource information map. - */ - private function rebuildTextResources( - CelerityPhysicalResources $resources, - CelerityResourceTransformer $xformer) { - - $text_map = $resources->findTextResources(); - - $result_map = array(); - foreach ($text_map as $name => $data_hash) { - $raw_data = $resources->getResourceData($name); - $xformed_data = $xformer->transformResource($name, $raw_data); - - $data_hash = $resources->getCelerityHash($xformed_data); - $hash = $resources->getCelerityHash($data_hash.$name); - - list($provides, $requires) = $this->getProvidesAndRequires( - $name, - $raw_data); - - $result_map[$name] = array( - 'hash' => $hash, - ); - - if ($provides !== null) { - $result_map[$name] += array( - 'provides' => $provides, - 'requires' => $requires, - ); - } - } - - return $result_map; - } - - - /** - * Parse the `@provides` and `@requires` symbols out of a text resource, like - * JS or CSS. - * - * @param string Resource name. - * @param string Resource data. - * @return pair|null> The `@provides` symbol and the - * list of `@requires` symbols. If the resource is not part of the - * dependency graph, both are null. - */ - private function getProvidesAndRequires($name, $data) { - $parser = new PhutilDocblockParser(); - - $matches = array(); - $ok = preg_match('@/[*][*].*?[*]/@s', $data, $matches); - if (!$ok) { - throw new Exception( - pht( - 'Resource "%s" does not have a header doc comment. Encode '. - 'dependency data in a header docblock.', - $name)); - } - - list($description, $metadata) = $parser->parse($matches[0]); - - $provides = preg_split('/\s+/', trim(idx($metadata, 'provides'))); - $requires = preg_split('/\s+/', trim(idx($metadata, 'requires'))); - $provides = array_filter($provides); - $requires = array_filter($requires); - - if (!$provides) { - // Tests and documentation-only JS is permitted to @provide no targets. - return array(null, null); - } - - if (count($provides) > 1) { - throw new Exception( - pht( - 'Resource "%s" must @provide at most one Celerity target.', - $name)); - } - - return array(head($provides), $requires); - } - - - /** - * Check for dependency cycles in the resource graph. Raises an exception if - * a cycle is detected. - * - * @param map> Map of `@provides` symbols to their - * `@requires` symbols. - * @return void - */ - private function detectGraphCycles(array $nodes) { - $graph = id(new CelerityResourceGraph()) - ->addNodes($nodes) - ->setResourceGraph($nodes) - ->loadGraph(); - - foreach ($nodes as $provides => $requires) { - $cycle = $graph->detectCycles($provides); - if ($cycle) { - throw new Exception( - pht( - 'Cycle detected in resource graph: %s', - implode(' > ', $cycle))); - } - } - } - - /** - * Build package specifications for a given resource source. - * - * @param CelerityPhysicalResources Resource source to rebuild. - * @param list Map of `@provides` to hashes. - * @param list Map of hashes to resource names. - * @return map> Package information maps. - */ - private function rebuildPackages( - CelerityPhysicalResources $resources, - array $symbol_map, - array $reverse_map) { - - $package_map = array(); - - $package_spec = $resources->getResourcePackages(); - foreach ($package_spec as $package_name => $package_symbols) { - $type = null; - $hashes = array(); - foreach ($package_symbols as $symbol) { - $symbol_hash = idx($symbol_map, $symbol); - if ($symbol_hash === null) { - throw new Exception( - pht( - 'Package specification for "%s" includes "%s", but that symbol '. - 'is not @provided by any resource.', - $package_name, - $symbol)); - } - - $resource_name = $reverse_map[$symbol_hash]; - $resource_type = $resources->getResourceType($resource_name); - if ($type === null) { - $type = $resource_type; - } else if ($type !== $resource_type) { - throw new Exception( - pht( - 'Package specification for "%s" includes resources of multiple '. - 'types (%s, %s). Each package may only contain one type of '. - 'resource.', - $package_name, - $type, - $resource_type)); - } - - $hashes[] = $symbol.':'.$symbol_hash; - } - - $hash = $resources->getCelerityHash(implode("\n", $hashes)); - $package_map[$package_name] = array( - 'hash' => $hash, - 'symbols' => $package_symbols, - ); - } - - return $package_map; - } - - private function mergeNameMaps(array $maps) { - $result = array(); - $origin = array(); - foreach ($maps as $map) { - list($map_name, $data) = $map; - foreach ($data as $name => $hash) { - if (empty($result[$name])) { - $result[$name] = $hash; - $origin[$name] = $map_name; - } else { - $old = $origin[$name]; - $new = $map_name; - throw new Exception( - pht( - 'Resource source defines two resources with the same name, '. - '"%s". One is defined in the "%s" map; the other in the "%s" '. - 'map. Each resource must have a unique name.', - $name, - $old, - $new)); - } - } - } - return $result; - } - - private function log($message) { + protected function log($message) { $console = PhutilConsole::getConsole(); $console->writeErr("%s\n", $message); } - private function formatMapContent(array $data) { - $content = phutil_var_export($data); - - $generated = '@'.'generated'; - return << Date: Wed, 24 Sep 2014 09:10:28 -0700 Subject: [PATCH 02/24] Shift footer when on page with sidenav Summary: Fixes T6168, adds spacing when navigation is present. Test Plan: Tested Chrome, IE 9, 10. Numerous pages. Reviewers: epriestley, btrahan Reviewed By: btrahan Subscribers: epriestley, Korvin Maniphest Tasks: T6168 Differential Revision: https://secure.phabricator.com/D10543 --- resources/celerity/map.php | 6 +++--- src/view/page/PhabricatorStandardPageView.php | 3 +-- webroot/rsrc/css/application/base/standard-page-view.css | 8 ++++++-- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index db9d161802..9e171e90a6 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -7,7 +7,7 @@ */ return array( 'names' => array( - 'core.pkg.css' => '3317a3ad', + 'core.pkg.css' => 'fe2446e9', 'core.pkg.js' => 'cbdbd552', 'darkconsole.pkg.js' => 'df001cab', 'differential.pkg.css' => '36884139', @@ -39,7 +39,7 @@ return array( 'rsrc/css/application/base/main-menu-view.css' => 'aceca0e9', 'rsrc/css/application/base/notification-menu.css' => '6aa0a74b', 'rsrc/css/application/base/phabricator-application-launch-view.css' => '5d71008f', - 'rsrc/css/application/base/standard-page-view.css' => 'dd860661', + 'rsrc/css/application/base/standard-page-view.css' => '1b000ec8', 'rsrc/css/application/chatlog/chatlog.css' => '852140ff', 'rsrc/css/application/config/config-options.css' => '7fedf08b', 'rsrc/css/application/config/config-template.css' => '25d446d6', @@ -739,7 +739,7 @@ return array( 'phabricator-side-menu-view-css' => 'a2ccd7bd', 'phabricator-slowvote-css' => '266df6a1', 'phabricator-source-code-view-css' => '7d346aa4', - 'phabricator-standard-page-view' => 'dd860661', + 'phabricator-standard-page-view' => '1b000ec8', 'phabricator-textareautils' => '5c93c52c', 'phabricator-title' => '5c1c758c', 'phabricator-tooltip' => '3915d490', diff --git a/src/view/page/PhabricatorStandardPageView.php b/src/view/page/PhabricatorStandardPageView.php index bcf274817b..9af3affb75 100644 --- a/src/view/page/PhabricatorStandardPageView.php +++ b/src/view/page/PhabricatorStandardPageView.php @@ -352,7 +352,6 @@ final class PhabricatorStandardPageView extends PhabricatorBarePageView { phutil_tag_div('phabricator-standard-page-body', array( ($console ? hsprintf('') : null), parent::getBody(), - phutil_tag('div', array('style' => 'clear: both;')), $this->renderFooter(), )), )); @@ -508,7 +507,7 @@ final class PhabricatorStandardPageView extends PhabricatorBarePageView { return phutil_tag( 'div', array( - 'class' => 'phabricator-standard-page-footer', + 'class' => 'phabricator-standard-page-footer grouped', ), $foot); } diff --git a/webroot/rsrc/css/application/base/standard-page-view.css b/webroot/rsrc/css/application/base/standard-page-view.css index 301137c338..2a13e05bac 100644 --- a/webroot/rsrc/css/application/base/standard-page-view.css +++ b/webroot/rsrc/css/application/base/standard-page-view.css @@ -15,12 +15,16 @@ .phabricator-standard-page-footer { text-align: right; - margin: 0 16px; - padding: 8px 0; + margin: 4px 16px; + padding: 12px 0; border-top: 1px solid {$lightgreyborder}; color: {$lightgreytext}; } +.has-local-nav + .phabricator-standard-page-footer { + margin-left: 221px; +} + .keyboard-shortcut-help td, .keyboard-shortcut-help th { padding: 8px; From 11f6b01428d43a7b48db3cb5f9abf13e9f3fcc2f Mon Sep 17 00:00:00 2001 From: Bob Trahan Date: Wed, 24 Sep 2014 10:28:58 -0700 Subject: [PATCH 03/24] Support - fix some docs on ssh hosting Summary: Fixes T6169 by using the new nav element on the existing troubleshooting hint the user missed. Fixes T6173 by implementing the user's suggestion. Test Plan: Looked at docs and they looked good. Reviewers: epriestley, chad Reviewed By: chad Subscribers: fas, epriestley, Korvin Maniphest Tasks: T6169, T6173 Differential Revision: https://secure.phabricator.com/D10548 --- src/docs/user/userguide/diffusion_hosting.diviner | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/docs/user/userguide/diffusion_hosting.diviner b/src/docs/user/userguide/diffusion_hosting.diviner index a2d845577a..1639639831 100644 --- a/src/docs/user/userguide/diffusion_hosting.diviner +++ b/src/docs/user/userguide/diffusion_hosting.diviner @@ -283,14 +283,23 @@ Some general tips for troubleshooting problems with SSH: - Check that you've configured `diffusion.ssh-user`. - Check that you've configured `phd.user`. - Make sure SSH serving is enabled for the repository you're trying to clone. - You can find this in "Edit Repository" -> "Hosting". + You can change this setting from a main repository screen in Diffusion by + {nav Edit Repository > + Edit Hosting > + Host Repository on Phabricator > + Save and Continue > + SSH Read Only or Read/Write > + Save Changes}. - Make sure you've added an SSH public key to your account. You can do this - in "Settings" -> "SSH Keys". + in {nav Settings > + SSH Public Keys}. - Make sure the main repository screen in Diffusion shows a clone/checkout command for SSH. If it doesn't, something above isn't set up correctly. You should see an `svn checkout svn+ssh://...`, `git clone ssh://...` or `hg clone ssh://...` command. Run that command verbatim to clone the repository. + - Check your `phabricator-ssh-hook.sh` file for proper settings. + - Check your `sshd_config.phabricator` file for proper settings. To troubleshoot SSH setup: connect to the server with `ssh`, without running a command. You may need to use the `-T` flag. You should see a message like From 93e1978e054800781c55b96a09645de2b34277da Mon Sep 17 00:00:00 2001 From: Bob Trahan Date: Wed, 24 Sep 2014 12:09:59 -0700 Subject: [PATCH 04/24] Support - Differential - fix rendering feed story where you removed a repository Summary: Fixes T6176. Language here is a bit awkard but I wanted to use the verb "removed" *and* still have the object first, so I ended up adding the before details parenthetically. Test Plan: story no longer fatal'd in my feed Reviewers: epriestley, chad Reviewed By: chad Subscribers: epriestley, Korvin Maniphest Tasks: T6176 Differential Revision: https://secure.phabricator.com/D10549 --- .../customfield/DifferentialRepositoryField.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/applications/differential/customfield/DifferentialRepositoryField.php b/src/applications/differential/customfield/DifferentialRepositoryField.php index cab25dbbe5..06ada847c9 100644 --- a/src/applications/differential/customfield/DifferentialRepositoryField.php +++ b/src/applications/differential/customfield/DifferentialRepositoryField.php @@ -107,19 +107,25 @@ final class DifferentialRepositoryField $old = $xaction->getOldValue(); $new = $xaction->getNewValue(); - if ($old) { + if ($old && $new) { return pht( '%s updated the repository for %s from %s to %s.', $xaction->renderHandleLink($author_phid), $xaction->renderHandleLink($object_phid), $xaction->renderHandleLink($old), $xaction->renderHandleLink($new)); - } else { + } else if ($new) { return pht( '%s set the repository for %s to %s.', $xaction->renderHandleLink($author_phid), $xaction->renderHandleLink($object_phid), $xaction->renderHandleLink($new)); + } else { + return pht( + '%s removed the repository for %s. (Repository was %s.)', + $xaction->renderHandleLink($author_phid), + $xaction->renderHandleLink($object_phid), + $xaction->renderHandleLink($old)); } } From cd4e3c6399a5467d0ad6f6562066174dee5c5f7d Mon Sep 17 00:00:00 2001 From: epriestley Date: Wed, 24 Sep 2014 13:49:25 -0700 Subject: [PATCH 05/24] Make Releeph a normal prototype application Summary: Fixes T6177. Now that we've reframed "Beta" into "Prototype", there's no reason this needs to be in a separate super-hidden class of application anymore. Test Plan: Saw Releeph available as a normal Prototype application. Reviewers: btrahan, chad Reviewed By: chad Subscribers: epriestley Maniphest Tasks: T6177 Differential Revision: https://secure.phabricator.com/D10550 --- .../application/PhabricatorReleephApplication.php | 7 ++----- .../PhabricatorReleephApplicationConfigOptions.php | 13 ------------- src/infrastructure/testing/PhabricatorTestCase.php | 3 --- 3 files changed, 2 insertions(+), 21 deletions(-) diff --git a/src/applications/releeph/application/PhabricatorReleephApplication.php b/src/applications/releeph/application/PhabricatorReleephApplication.php index 91e8246f85..e04337f912 100644 --- a/src/applications/releeph/application/PhabricatorReleephApplication.php +++ b/src/applications/releeph/application/PhabricatorReleephApplication.php @@ -18,11 +18,8 @@ final class PhabricatorReleephApplication extends PhabricatorApplication { return 'releeph'; } - public function isInstalled() { - if (PhabricatorEnv::getEnvConfig('releeph.installed')) { - return parent::isInstalled(); - } - return false; + public function isPrototype() { + return true; } public function getRoutes() { diff --git a/src/applications/releeph/config/PhabricatorReleephApplicationConfigOptions.php b/src/applications/releeph/config/PhabricatorReleephApplicationConfigOptions.php index 6f54a7ceb2..dc62b59166 100644 --- a/src/applications/releeph/config/PhabricatorReleephApplicationConfigOptions.php +++ b/src/applications/releeph/config/PhabricatorReleephApplicationConfigOptions.php @@ -42,19 +42,6 @@ final class PhabricatorReleephApplicationConfigOptions $custom_field_type = 'custom:PhabricatorCustomFieldConfigOptionType'; return array( - $this->newOption('releeph.installed', 'bool', false) - ->setSummary(pht('Enable the Releeph application.')) - ->setDescription( - pht( - 'Releeph, a tool for managing release branches, will eventually '. - 'fit in to the Phabricator suite as a general purpose tool. '. - 'However Releeph is currently unstable in multiple ways that may '. - 'not migrate properly for you: the code is still in alpha stage '. - 'of design, the storage format is likely to change in unexpected '. - 'ways, and the workflows presented are very specific to a core '. - 'set of alpha testers at Facebook. For the time being you are '. - 'strongly discouraged from relying on Releeph being at all '. - 'stable.')), $this->newOption('releeph.fields', $custom_field_type, $default) ->setCustomData('ReleephFieldSpecification'), $this->newOption( diff --git a/src/infrastructure/testing/PhabricatorTestCase.php b/src/infrastructure/testing/PhabricatorTestCase.php index 14e2a30142..effec47d86 100644 --- a/src/infrastructure/testing/PhabricatorTestCase.php +++ b/src/infrastructure/testing/PhabricatorTestCase.php @@ -116,9 +116,6 @@ abstract class PhabricatorTestCase extends ArcanistPhutilTestCase { 'notification.enabled', false); - // TODO: Remove this when we remove "releeph.installed". - $this->env->overrideEnvConfig('releeph.installed', true); - $this->env->overrideEnvConfig( 'phabricator.base-uri', 'http://phabricator.example.com'); From d6639b68d5a32a579251fb1d87a1c3a44f40ad4a Mon Sep 17 00:00:00 2001 From: epriestley Date: Wed, 24 Sep 2014 13:50:00 -0700 Subject: [PATCH 06/24] Generate expected schemata for MetaMTA, Nuance, MetaData, OAuthServer Summary: Ref T1191. Handful of minor things here (T6150, T6149, T6148, T6147, T6146) but nothing very noteworthy. Test Plan: Viewed web UI, saw fewer errors. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T1191 Differential Revision: https://secure.phabricator.com/D10527 --- src/__phutil_library_map__.php | 8 ++++++ .../schema/PhabricatorConfigSchemaSpec.php | 5 ++++ .../storage/PhabricatorMetaMTAMailingList.php | 20 ++++++++++++++ .../storage/PhabricatorMetaMTAMail.php | 16 +++++++++++ .../PhabricatorMetaMTAReceivedMail.php | 21 +++++++++++++++ .../storage/PhabricatorMetaMTASchemaSpec.php | 14 ++++++++++ .../nuance/storage/NuanceItem.php | 19 +++++++++++++ .../nuance/storage/NuanceQueue.php | 4 +++ .../nuance/storage/NuanceQueueItem.php | 17 ++++++++++++ .../nuance/storage/NuanceSchemaSpec.php | 27 +++++++++++++++++++ .../nuance/storage/NuanceSource.php | 10 +++++++ .../PhabricatorOAuthClientAuthorization.php | 14 ++++++++++ .../storage/PhabricatorOAuthSchemaSpec.php | 10 +++++++ .../PhabricatorOAuthServerAccessToken.php | 15 +++++++++++ ...habricatorOAuthServerAuthorizationCode.php | 17 ++++++++++++ .../storage/PhabricatorOAuthServerClient.php | 15 +++++++++++ .../sms/storage/PhabricatorSMS.php | 19 +++++++++++++ .../schema/PhabricatorStorageSchemaSpec.php | 22 +++++++++++++++ 18 files changed, 273 insertions(+) create mode 100644 src/applications/metamta/storage/PhabricatorMetaMTASchemaSpec.php create mode 100644 src/applications/nuance/storage/NuanceSchemaSpec.php create mode 100644 src/applications/oauthserver/storage/PhabricatorOAuthSchemaSpec.php create mode 100644 src/infrastructure/storage/schema/PhabricatorStorageSchemaSpec.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index fc4f8c1b35..0b57d6b0aa 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -992,6 +992,7 @@ phutil_register_library_map(array( 'NuanceRequestorTransactionComment' => 'applications/nuance/storage/NuanceRequestorTransactionComment.php', 'NuanceRequestorTransactionQuery' => 'applications/nuance/query/NuanceRequestorTransactionQuery.php', 'NuanceRequestorViewController' => 'applications/nuance/controller/NuanceRequestorViewController.php', + 'NuanceSchemaSpec' => 'applications/nuance/storage/NuanceSchemaSpec.php', 'NuanceSource' => 'applications/nuance/storage/NuanceSource.php', 'NuanceSourceDefaultEditCapability' => 'applications/nuance/capability/NuanceSourceDefaultEditCapability.php', 'NuanceSourceDefaultViewCapability' => 'applications/nuance/capability/NuanceSourceDefaultViewCapability.php', @@ -1808,6 +1809,7 @@ phutil_register_library_map(array( 'PhabricatorMetaMTAReceivedMail' => 'applications/metamta/storage/PhabricatorMetaMTAReceivedMail.php', 'PhabricatorMetaMTAReceivedMailProcessingException' => 'applications/metamta/exception/PhabricatorMetaMTAReceivedMailProcessingException.php', 'PhabricatorMetaMTAReceivedMailTestCase' => 'applications/metamta/storage/__tests__/PhabricatorMetaMTAReceivedMailTestCase.php', + 'PhabricatorMetaMTASchemaSpec' => 'applications/metamta/storage/PhabricatorMetaMTASchemaSpec.php', 'PhabricatorMetaMTASendGridReceiveController' => 'applications/metamta/controller/PhabricatorMetaMTASendGridReceiveController.php', 'PhabricatorMetaMTAWorker' => 'applications/metamta/PhabricatorMetaMTAWorker.php', 'PhabricatorMultiColumnExample' => 'applications/uiexample/examples/PhabricatorMultiColumnExample.php', @@ -1844,6 +1846,7 @@ phutil_register_library_map(array( 'PhabricatorOAuthClientListController' => 'applications/oauthserver/controller/client/PhabricatorOAuthClientListController.php', 'PhabricatorOAuthClientViewController' => 'applications/oauthserver/controller/client/PhabricatorOAuthClientViewController.php', 'PhabricatorOAuthResponse' => 'applications/oauthserver/PhabricatorOAuthResponse.php', + 'PhabricatorOAuthSchemaSpec' => 'applications/oauthserver/storage/PhabricatorOAuthSchemaSpec.php', 'PhabricatorOAuthServer' => 'applications/oauthserver/PhabricatorOAuthServer.php', 'PhabricatorOAuthServerAccessToken' => 'applications/oauthserver/storage/PhabricatorOAuthServerAccessToken.php', 'PhabricatorOAuthServerApplication' => 'applications/oauthserver/application/PhabricatorOAuthServerApplication.php', @@ -2305,6 +2308,7 @@ phutil_register_library_map(array( 'PhabricatorStorageManagementUpgradeWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementUpgradeWorkflow.php', 'PhabricatorStorageManagementWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementWorkflow.php', 'PhabricatorStoragePatch' => 'infrastructure/storage/management/PhabricatorStoragePatch.php', + 'PhabricatorStorageSchemaSpec' => 'infrastructure/storage/schema/PhabricatorStorageSchemaSpec.php', 'PhabricatorSubscribableInterface' => 'applications/subscriptions/interface/PhabricatorSubscribableInterface.php', 'PhabricatorSubscribersQuery' => 'applications/subscriptions/query/PhabricatorSubscribersQuery.php', 'PhabricatorSubscriptionsApplication' => 'applications/subscriptions/application/PhabricatorSubscriptionsApplication.php', @@ -3892,6 +3896,7 @@ phutil_register_library_map(array( 'NuanceRequestorTransactionComment' => 'PhabricatorApplicationTransactionComment', 'NuanceRequestorTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'NuanceRequestorViewController' => 'NuanceController', + 'NuanceSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'NuanceSource' => array( 'NuanceDAO', 'PhabricatorPolicyInterface', @@ -4738,6 +4743,7 @@ phutil_register_library_map(array( 'PhabricatorMetaMTAReceivedMail' => 'PhabricatorMetaMTADAO', 'PhabricatorMetaMTAReceivedMailProcessingException' => 'Exception', 'PhabricatorMetaMTAReceivedMailTestCase' => 'PhabricatorTestCase', + 'PhabricatorMetaMTASchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorMetaMTASendGridReceiveController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTAWorker' => 'PhabricatorWorker', 'PhabricatorMultiColumnExample' => 'PhabricatorUIExample', @@ -4778,6 +4784,7 @@ phutil_register_library_map(array( 'PhabricatorOAuthClientListController' => 'PhabricatorOAuthClientController', 'PhabricatorOAuthClientViewController' => 'PhabricatorOAuthClientController', 'PhabricatorOAuthResponse' => 'AphrontResponse', + 'PhabricatorOAuthSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorOAuthServerAccessToken' => 'PhabricatorOAuthServerDAO', 'PhabricatorOAuthServerApplication' => 'PhabricatorApplication', 'PhabricatorOAuthServerAuthController' => 'PhabricatorAuthController', @@ -5283,6 +5290,7 @@ phutil_register_library_map(array( 'PhabricatorStorageManagementStatusWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementUpgradeWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementWorkflow' => 'PhabricatorManagementWorkflow', + 'PhabricatorStorageSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorSubscribersQuery' => 'PhabricatorQuery', 'PhabricatorSubscriptionsApplication' => 'PhabricatorApplication', 'PhabricatorSubscriptionsEditController' => 'PhabricatorController', diff --git a/src/applications/config/schema/PhabricatorConfigSchemaSpec.php b/src/applications/config/schema/PhabricatorConfigSchemaSpec.php index eda715639d..bd4eb3075e 100644 --- a/src/applications/config/schema/PhabricatorConfigSchemaSpec.php +++ b/src/applications/config/schema/PhabricatorConfigSchemaSpec.php @@ -271,6 +271,11 @@ abstract class PhabricatorConfigSchemaSpec extends Phobject { $charset = $this->getUTF8Charset(); $collation = $this->getUTF8Collation(); break; + case 'text40': + $column_type = 'varchar(40)'; + $charset = $this->getUTF8Charset(); + $collation = $this->getUTF8Collation(); + break; case 'text32': $column_type = 'varchar(32)'; $charset = $this->getUTF8Charset(); diff --git a/src/applications/mailinglists/storage/PhabricatorMetaMTAMailingList.php b/src/applications/mailinglists/storage/PhabricatorMetaMTAMailingList.php index 794560e723..b2607e4848 100644 --- a/src/applications/mailinglists/storage/PhabricatorMetaMTAMailingList.php +++ b/src/applications/mailinglists/storage/PhabricatorMetaMTAMailingList.php @@ -17,6 +17,26 @@ final class PhabricatorMetaMTAMailingList extends PhabricatorMetaMTADAO public function getConfiguration() { return array( self::CONFIG_AUX_PHID => true, + self::CONFIG_COLUMN_SCHEMA => array( + 'name' => 'text255', + 'email' => 'text255', + 'uri' => 'text255?', + ), + self::CONFIG_KEY_SCHEMA => array( + 'key_phid' => null, + 'phid' => array( + 'columns' => array('phid'), + 'unique' => true, + ), + 'email' => array( + 'columns' => array('email'), + 'unique' => true, + ), + 'name' => array( + 'columns' => array('name'), + 'unique' => true, + ), + ), ) + parent::getConfiguration(); } diff --git a/src/applications/metamta/storage/PhabricatorMetaMTAMail.php b/src/applications/metamta/storage/PhabricatorMetaMTAMail.php index 9ac771ea23..d7882231ec 100644 --- a/src/applications/metamta/storage/PhabricatorMetaMTAMail.php +++ b/src/applications/metamta/storage/PhabricatorMetaMTAMail.php @@ -32,6 +32,22 @@ final class PhabricatorMetaMTAMail extends PhabricatorMetaMTADAO { self::CONFIG_SERIALIZATION => array( 'parameters' => self::SERIALIZATION_JSON, ), + self::CONFIG_COLUMN_SCHEMA => array( + 'status' => 'text255', + 'message' => 'text', + 'relatedPHID' => 'phid?', + ), + self::CONFIG_KEY_SCHEMA => array( + 'status' => array( + 'columns' => array('status'), + ), + 'relatedPHID' => array( + 'columns' => array('relatedPHID'), + ), + 'key_created' => array( + 'columns' => array('dateCreated'), + ), + ), ) + parent::getConfiguration(); } diff --git a/src/applications/metamta/storage/PhabricatorMetaMTAReceivedMail.php b/src/applications/metamta/storage/PhabricatorMetaMTAReceivedMail.php index 742b4e1ee4..b3828fce24 100644 --- a/src/applications/metamta/storage/PhabricatorMetaMTAReceivedMail.php +++ b/src/applications/metamta/storage/PhabricatorMetaMTAReceivedMail.php @@ -19,6 +19,27 @@ final class PhabricatorMetaMTAReceivedMail extends PhabricatorMetaMTADAO { 'bodies' => self::SERIALIZATION_JSON, 'attachments' => self::SERIALIZATION_JSON, ), + self::CONFIG_COLUMN_SCHEMA => array( + 'relatedPHID' => 'phid?', + 'authorPHID' => 'phid?', + 'message' => 'text?', + 'messageIDHash' => 'bytes12', + 'status' => 'text32', + ), + self::CONFIG_KEY_SCHEMA => array( + 'relatedPHID' => array( + 'columns' => array('relatedPHID'), + ), + 'authorPHID' => array( + 'columns' => array('authorPHID'), + ), + 'key_messageIDHash' => array( + 'columns' => array('messageIDHash'), + ), + 'key_created' => array( + 'columns' => array('dateCreated'), + ), + ), ) + parent::getConfiguration(); } diff --git a/src/applications/metamta/storage/PhabricatorMetaMTASchemaSpec.php b/src/applications/metamta/storage/PhabricatorMetaMTASchemaSpec.php new file mode 100644 index 0000000000..4754a74c48 --- /dev/null +++ b/src/applications/metamta/storage/PhabricatorMetaMTASchemaSpec.php @@ -0,0 +1,14 @@ +buildLiskSchemata('PhabricatorMetaMTADAO'); + $this->buildLiskSchemata('PhabricatorSMSDAO'); + + $this->buildEdgeSchemata( + new PhabricatorMetaMTAMail()); + } + +} diff --git a/src/applications/nuance/storage/NuanceItem.php b/src/applications/nuance/storage/NuanceItem.php index 5f6193d1b0..fe02f7679a 100644 --- a/src/applications/nuance/storage/NuanceItem.php +++ b/src/applications/nuance/storage/NuanceItem.php @@ -22,12 +22,31 @@ final class NuanceItem ->setDateNuanced(time()) ->setStatus(NuanceItem::STATUS_OPEN); } + public function getConfiguration() { return array( self::CONFIG_AUX_PHID => true, self::CONFIG_SERIALIZATION => array( 'data' => self::SERIALIZATION_JSON, ), + self::CONFIG_COLUMN_SCHEMA => array( + 'ownerPHID' => 'phid?', + 'sourceLabel' => 'text255?', + 'status' => 'uint32', + 'mailKey' => 'bytes20', + 'dateNuanced' => 'epoch', + ), + self::CONFIG_KEY_SCHEMA => array( + 'key_source' => array( + 'columns' => array('sourcePHID', 'status', 'dateNuanced'), + ), + 'key_owner' => array( + 'columns' => array('ownerPHID', 'status', 'dateNuanced'), + ), + 'key_contacter' => array( + 'columns' => array('requestorPHID', 'status', 'dateNuanced'), + ), + ), ) + parent::getConfiguration(); } diff --git a/src/applications/nuance/storage/NuanceQueue.php b/src/applications/nuance/storage/NuanceQueue.php index 5871df8504..4a172a9401 100644 --- a/src/applications/nuance/storage/NuanceQueue.php +++ b/src/applications/nuance/storage/NuanceQueue.php @@ -12,6 +12,10 @@ final class NuanceQueue public function getConfiguration() { return array( self::CONFIG_AUX_PHID => true, + self::CONFIG_COLUMN_SCHEMA => array( + 'name' => 'text255?', + 'mailKey' => 'bytes20', + ), ) + parent::getConfiguration(); } diff --git a/src/applications/nuance/storage/NuanceQueueItem.php b/src/applications/nuance/storage/NuanceQueueItem.php index 92bbb51056..3fbaecd099 100644 --- a/src/applications/nuance/storage/NuanceQueueItem.php +++ b/src/applications/nuance/storage/NuanceQueueItem.php @@ -8,5 +8,22 @@ final class NuanceQueueItem protected $itemStatus; protected $itemDateNuanced; + public function getConfiguration() { + return array( + self::CONFIG_COLUMN_SCHEMA => array( + 'itemStatus' => 'uint32', + 'itemDateNuanced' => 'epoch', + ), + self::CONFIG_KEY_SCHEMA => array( + 'key_one_per_queue' => array( + 'columns' => array('itemPHID', 'queuePHID'), + 'unique' => true, + ), + 'key_queue' => array( + 'columns' => array('queuePHID', 'itemStatus', 'itemDateNuanced'), + ), + ), + ) + parent::getConfiguration(); + } } diff --git a/src/applications/nuance/storage/NuanceSchemaSpec.php b/src/applications/nuance/storage/NuanceSchemaSpec.php new file mode 100644 index 0000000000..993dfe63f6 --- /dev/null +++ b/src/applications/nuance/storage/NuanceSchemaSpec.php @@ -0,0 +1,27 @@ +buildLiskSchemata('NuanceDAO'); + $this->buildEdgeSchemata(new NuanceItem()); + + $this->buildTransactionSchema( + new NuanceItemTransaction(), + new NuanceItemTransactionComment()); + + $this->buildTransactionSchema( + new NuanceQueueTransaction(), + new NuanceQueueTransactionComment()); + + $this->buildTransactionSchema( + new NuanceRequestorTransaction(), + new NuanceRequestorTransactionComment()); + + $this->buildTransactionSchema( + new NuanceSourceTransaction(), + new NuanceSourceTransactionComment()); + } + +} diff --git a/src/applications/nuance/storage/NuanceSource.php b/src/applications/nuance/storage/NuanceSource.php index e6fc9da86b..025a60dd89 100644 --- a/src/applications/nuance/storage/NuanceSource.php +++ b/src/applications/nuance/storage/NuanceSource.php @@ -16,6 +16,16 @@ final class NuanceSource extends NuanceDAO self::CONFIG_SERIALIZATION => array( 'data' => self::SERIALIZATION_JSON, ), + self::CONFIG_COLUMN_SCHEMA => array( + 'name' => 'text255?', + 'type' => 'text32', + 'mailKey' => 'bytes20', + ), + self::CONFIG_KEY_SCHEMA => array( + 'key_type' => array( + 'columns' => array('type', 'dateModified'), + ), + ), ) + parent::getConfiguration(); } diff --git a/src/applications/oauthserver/storage/PhabricatorOAuthClientAuthorization.php b/src/applications/oauthserver/storage/PhabricatorOAuthClientAuthorization.php index c29c06eda2..505df7b2d7 100644 --- a/src/applications/oauthserver/storage/PhabricatorOAuthClientAuthorization.php +++ b/src/applications/oauthserver/storage/PhabricatorOAuthClientAuthorization.php @@ -23,6 +23,20 @@ final class PhabricatorOAuthClientAuthorization self::CONFIG_SERIALIZATION => array( 'scope' => self::SERIALIZATION_JSON, ), + self::CONFIG_COLUMN_SCHEMA => array( + 'scope' => 'text', + ), + self::CONFIG_KEY_SCHEMA => array( + 'key_phid' => null, + 'phid' => array( + 'columns' => array('phid'), + 'unique' => true, + ), + 'userPHID' => array( + 'columns' => array('userPHID', 'clientPHID'), + 'unique' => true, + ), + ), ) + parent::getConfiguration(); } diff --git a/src/applications/oauthserver/storage/PhabricatorOAuthSchemaSpec.php b/src/applications/oauthserver/storage/PhabricatorOAuthSchemaSpec.php new file mode 100644 index 0000000000..e7c8c002f1 --- /dev/null +++ b/src/applications/oauthserver/storage/PhabricatorOAuthSchemaSpec.php @@ -0,0 +1,10 @@ +buildLiskSchemata('PhabricatorOAuthServerDAO'); + } + +} diff --git a/src/applications/oauthserver/storage/PhabricatorOAuthServerAccessToken.php b/src/applications/oauthserver/storage/PhabricatorOAuthServerAccessToken.php index fd2e2d1080..1deadaa92b 100644 --- a/src/applications/oauthserver/storage/PhabricatorOAuthServerAccessToken.php +++ b/src/applications/oauthserver/storage/PhabricatorOAuthServerAccessToken.php @@ -7,4 +7,19 @@ final class PhabricatorOAuthServerAccessToken protected $token; protected $userPHID; protected $clientPHID; + + public function getConfiguration() { + return array( + self::CONFIG_COLUMN_SCHEMA => array( + 'token' => 'text32', + ), + self::CONFIG_KEY_SCHEMA => array( + 'token' => array( + 'columns' => array('token'), + 'unique' => true, + ), + ), + ) + parent::getConfiguration(); + } + } diff --git a/src/applications/oauthserver/storage/PhabricatorOAuthServerAuthorizationCode.php b/src/applications/oauthserver/storage/PhabricatorOAuthServerAuthorizationCode.php index bbc39d2bc4..32212d987d 100644 --- a/src/applications/oauthserver/storage/PhabricatorOAuthServerAuthorizationCode.php +++ b/src/applications/oauthserver/storage/PhabricatorOAuthServerAuthorizationCode.php @@ -9,4 +9,21 @@ final class PhabricatorOAuthServerAuthorizationCode protected $clientSecret; protected $userPHID; protected $redirectURI; + + public function getConfiguration() { + return array( + self::CONFIG_COLUMN_SCHEMA => array( + 'code' => 'text32', + 'clientSecret' => 'text32', + 'redirectURI' => 'text255', + ), + self::CONFIG_KEY_SCHEMA => array( + 'code' => array( + 'columns' => array('code'), + 'unique' => true, + ), + ), + ) + parent::getConfiguration(); + } + } diff --git a/src/applications/oauthserver/storage/PhabricatorOAuthServerClient.php b/src/applications/oauthserver/storage/PhabricatorOAuthServerClient.php index 1483ca5ce7..1316e5f017 100644 --- a/src/applications/oauthserver/storage/PhabricatorOAuthServerClient.php +++ b/src/applications/oauthserver/storage/PhabricatorOAuthServerClient.php @@ -30,6 +30,21 @@ final class PhabricatorOAuthServerClient public function getConfiguration() { return array( self::CONFIG_AUX_PHID => true, + self::CONFIG_COLUMN_SCHEMA => array( + 'name' => 'text255', + 'secret' => 'text32', + 'redirectURI' => 'text255', + ), + self::CONFIG_KEY_SCHEMA => array( + 'key_phid' => null, + 'phid' => array( + 'columns' => array('phid'), + 'unique' => true, + ), + 'creatorPHID' => array( + 'columns' => array('creatorPHID'), + ), + ), ) + parent::getConfiguration(); } diff --git a/src/infrastructure/sms/storage/PhabricatorSMS.php b/src/infrastructure/sms/storage/PhabricatorSMS.php index e880fad01d..eb03d890de 100644 --- a/src/infrastructure/sms/storage/PhabricatorSMS.php +++ b/src/infrastructure/sms/storage/PhabricatorSMS.php @@ -43,6 +43,25 @@ final class PhabricatorSMS ->setProviderSMSID(Filesystem::readRandomCharacters(40)); } + public function getConfiguration() { + return array( + self::CONFIG_COLUMN_SCHEMA => array( + 'providerShortName' => 'text16', + 'providerSMSID' => 'text40', + 'toNumber' => 'text20', + 'fromNumber' => 'text20?', + 'body' => 'text', + 'sendStatus' => 'text16?', + ), + self::CONFIG_KEY_SCHEMA => array( + 'key_provider' => array( + 'columns' => array('providerSMSID', 'providerShortName'), + 'unique' => true, + ), + ), + ) + parent::getConfiguration(); + } + public function getTableName() { // Slightly non-standard, but otherwise this class needs "MetaMTA" in its // name. :/ diff --git a/src/infrastructure/storage/schema/PhabricatorStorageSchemaSpec.php b/src/infrastructure/storage/schema/PhabricatorStorageSchemaSpec.php new file mode 100644 index 0000000000..39a1f1c2d9 --- /dev/null +++ b/src/infrastructure/storage/schema/PhabricatorStorageSchemaSpec.php @@ -0,0 +1,22 @@ +buildRawSchema( + 'meta_data', + 'patch_status', + array( + 'patch' => 'text255', + 'applied' => 'uint32', + ), + array( + 'PRIMARY' => array( + 'columns' => array('patch'), + 'unique' => true, + ), + )); + } + +} From 502d18ede4003195d4585d3bbc11043e42d6f913 Mon Sep 17 00:00:00 2001 From: epriestley Date: Wed, 24 Sep 2014 13:50:57 -0700 Subject: [PATCH 07/24] Generate expected scheamta for Passphrase, Paste, Phlux, Phame Summary: Ref T1191. Nothing notable in these. Test Plan: Viewed web UI. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T1191 Differential Revision: https://secure.phabricator.com/D10528 --- src/__phutil_library_map__.php | 8 +++++++ .../storage/PassphraseCredential.php | 23 +++++++++++++++++++ .../storage/PassphraseSchemaSpec.php | 15 ++++++++++++ .../paste/storage/PhabricatorPaste.php | 20 ++++++++++++++++ .../storage/PhabricatorPasteSchemaSpec.php | 16 +++++++++++++ .../PhabricatorPasteTransactionComment.php | 9 ++++++++ src/applications/phame/storage/PhameBlog.php | 17 ++++++++++++++ src/applications/phame/storage/PhamePost.php | 21 +++++++++++++++++ .../phame/storage/PhameSchemaSpec.php | 11 +++++++++ .../phlux/storage/PhluxSchemaSpec.php | 11 +++++++++ .../phlux/storage/PhluxVariable.php | 9 ++++++++ 11 files changed, 160 insertions(+) create mode 100644 src/applications/passphrase/storage/PassphraseSchemaSpec.php create mode 100644 src/applications/paste/storage/PhabricatorPasteSchemaSpec.php create mode 100644 src/applications/phame/storage/PhameSchemaSpec.php create mode 100644 src/applications/phlux/storage/PhluxSchemaSpec.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 0b57d6b0aa..a8f81bc6f6 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1105,6 +1105,7 @@ phutil_register_library_map(array( 'PassphraseQueryConduitAPIMethod' => 'applications/passphrase/conduit/PassphraseQueryConduitAPIMethod.php', 'PassphraseRemarkupRule' => 'applications/passphrase/remarkup/PassphraseRemarkupRule.php', 'PassphraseSSHKey' => 'applications/passphrase/keys/PassphraseSSHKey.php', + 'PassphraseSchemaSpec' => 'applications/passphrase/storage/PassphraseSchemaSpec.php', 'PassphraseSecret' => 'applications/passphrase/storage/PassphraseSecret.php', 'PasteConduitAPIMethod' => 'applications/paste/conduit/PasteConduitAPIMethod.php', 'PasteCreateConduitAPIMethod' => 'applications/paste/conduit/PasteCreateConduitAPIMethod.php', @@ -1920,6 +1921,7 @@ phutil_register_library_map(array( 'PhabricatorPastePastePHIDType' => 'applications/paste/phid/PhabricatorPastePastePHIDType.php', 'PhabricatorPasteQuery' => 'applications/paste/query/PhabricatorPasteQuery.php', 'PhabricatorPasteRemarkupRule' => 'applications/paste/remarkup/PhabricatorPasteRemarkupRule.php', + 'PhabricatorPasteSchemaSpec' => 'applications/paste/storage/PhabricatorPasteSchemaSpec.php', 'PhabricatorPasteSearchEngine' => 'applications/paste/query/PhabricatorPasteSearchEngine.php', 'PhabricatorPasteTestDataGenerator' => 'applications/paste/lipsum/PhabricatorPasteTestDataGenerator.php', 'PhabricatorPasteTransaction' => 'applications/paste/storage/PhabricatorPasteTransaction.php', @@ -2493,11 +2495,13 @@ phutil_register_library_map(array( 'PhameQueryConduitAPIMethod' => 'applications/phame/conduit/PhameQueryConduitAPIMethod.php', 'PhameQueryPostsConduitAPIMethod' => 'applications/phame/conduit/PhameQueryPostsConduitAPIMethod.php', 'PhameResourceController' => 'applications/phame/controller/PhameResourceController.php', + 'PhameSchemaSpec' => 'applications/phame/storage/PhameSchemaSpec.php', 'PhameSkinSpecification' => 'applications/phame/skins/PhameSkinSpecification.php', 'PhluxController' => 'applications/phlux/controller/PhluxController.php', 'PhluxDAO' => 'applications/phlux/storage/PhluxDAO.php', 'PhluxEditController' => 'applications/phlux/controller/PhluxEditController.php', 'PhluxListController' => 'applications/phlux/controller/PhluxListController.php', + 'PhluxSchemaSpec' => 'applications/phlux/storage/PhluxSchemaSpec.php', 'PhluxTransaction' => 'applications/phlux/storage/PhluxTransaction.php', 'PhluxTransactionQuery' => 'applications/phlux/query/PhluxTransactionQuery.php', 'PhluxVariable' => 'applications/phlux/storage/PhluxVariable.php', @@ -4015,6 +4019,7 @@ phutil_register_library_map(array( 'PassphraseQueryConduitAPIMethod' => 'PassphraseConduitAPIMethod', 'PassphraseRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'PassphraseSSHKey' => 'PassphraseAbstractKey', + 'PassphraseSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PassphraseSecret' => 'PassphraseDAO', 'PasteConduitAPIMethod' => 'ConduitAPIMethod', 'PasteCreateConduitAPIMethod' => 'PasteConduitAPIMethod', @@ -4861,6 +4866,7 @@ phutil_register_library_map(array( 'PhabricatorPastePastePHIDType' => 'PhabricatorPHIDType', 'PhabricatorPasteQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorPasteRemarkupRule' => 'PhabricatorObjectRemarkupRule', + 'PhabricatorPasteSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorPasteSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorPasteTestDataGenerator' => 'PhabricatorTestDataGenerator', 'PhabricatorPasteTransaction' => 'PhabricatorApplicationTransaction', @@ -5490,10 +5496,12 @@ phutil_register_library_map(array( 'PhameQueryConduitAPIMethod' => 'PhameConduitAPIMethod', 'PhameQueryPostsConduitAPIMethod' => 'PhameConduitAPIMethod', 'PhameResourceController' => 'CelerityResourceController', + 'PhameSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhluxController' => 'PhabricatorController', 'PhluxDAO' => 'PhabricatorLiskDAO', 'PhluxEditController' => 'PhluxController', 'PhluxListController' => 'PhluxController', + 'PhluxSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhluxTransaction' => 'PhabricatorApplicationTransaction', 'PhluxTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhluxVariable' => array( diff --git a/src/applications/passphrase/storage/PassphraseCredential.php b/src/applications/passphrase/storage/PassphraseCredential.php index 241da9ca41..641988714d 100644 --- a/src/applications/passphrase/storage/PassphraseCredential.php +++ b/src/applications/passphrase/storage/PassphraseCredential.php @@ -35,6 +35,29 @@ final class PassphraseCredential extends PassphraseDAO public function getConfiguration() { return array( self::CONFIG_AUX_PHID => true, + self::CONFIG_COLUMN_SCHEMA => array( + 'name' => 'text255', + 'credentialType' => 'text64', + 'providesType' => 'text64', + 'description' => 'text', + 'username' => 'text255', + 'secretID' => 'id?', + 'isDestroyed' => 'bool', + 'isLocked' => 'bool', + 'allowConduit' => 'bool', + ), + self::CONFIG_KEY_SCHEMA => array( + 'key_secret' => array( + 'columns' => array('secretID'), + 'unique' => true, + ), + 'key_type' => array( + 'columns' => array('credentialType'), + ), + 'key_provides' => array( + 'columns' => array('providesType'), + ), + ), ) + parent::getConfiguration(); } diff --git a/src/applications/passphrase/storage/PassphraseSchemaSpec.php b/src/applications/passphrase/storage/PassphraseSchemaSpec.php new file mode 100644 index 0000000000..a3dbfd8328 --- /dev/null +++ b/src/applications/passphrase/storage/PassphraseSchemaSpec.php @@ -0,0 +1,15 @@ +buildLiskSchemata('PassphraseDAO'); + + $this->buildTransactionSchema( + new PassphraseCredentialTransaction()); + + $this->buildEdgeSchemata(new PassphraseCredential()); + } + +} diff --git a/src/applications/paste/storage/PhabricatorPaste.php b/src/applications/paste/storage/PhabricatorPaste.php index 4e5ac1332e..0b725c7a90 100644 --- a/src/applications/paste/storage/PhabricatorPaste.php +++ b/src/applications/paste/storage/PhabricatorPaste.php @@ -41,6 +41,26 @@ final class PhabricatorPaste extends PhabricatorPasteDAO public function getConfiguration() { return array( self::CONFIG_AUX_PHID => true, + self::CONFIG_COLUMN_SCHEMA => array( + 'title' => 'text255', + 'language' => 'text64', + 'mailKey' => 'bytes20', + 'parentPHID' => 'phid?', + ), + self::CONFIG_KEY_SCHEMA => array( + 'parentPHID' => array( + 'columns' => array('parentPHID'), + ), + 'authorPHID' => array( + 'columns' => array('authorPHID'), + ), + 'key_dateCreated' => array( + 'columns' => array('dateCreated'), + ), + 'key_language' => array( + 'columns' => array('language'), + ), + ), ) + parent::getConfiguration(); } diff --git a/src/applications/paste/storage/PhabricatorPasteSchemaSpec.php b/src/applications/paste/storage/PhabricatorPasteSchemaSpec.php new file mode 100644 index 0000000000..94df0246a3 --- /dev/null +++ b/src/applications/paste/storage/PhabricatorPasteSchemaSpec.php @@ -0,0 +1,16 @@ +buildLiskSchemata('PhabricatorPasteDAO'); + + $this->buildTransactionSchema( + new PhabricatorPasteTransaction(), + new PhabricatorPasteTransactionComment()); + + $this->buildEdgeSchemata(new PhabricatorPaste()); + } + +} diff --git a/src/applications/paste/storage/PhabricatorPasteTransactionComment.php b/src/applications/paste/storage/PhabricatorPasteTransactionComment.php index 145a375793..b50a9afc25 100644 --- a/src/applications/paste/storage/PhabricatorPasteTransactionComment.php +++ b/src/applications/paste/storage/PhabricatorPasteTransactionComment.php @@ -15,4 +15,13 @@ final class PhabricatorPasteTransactionComment return ($this->getTransactionPHID() != null); } + public function getConfiguration() { + $config = parent::getConfiguration(); + $config[self::CONFIG_COLUMN_SCHEMA] = array( + 'lineNumber' => 'uint32?', + 'lineLength' => 'uint32?', + ) + $config[self::CONFIG_COLUMN_SCHEMA]; + return $config; + } + } diff --git a/src/applications/phame/storage/PhameBlog.php b/src/applications/phame/storage/PhameBlog.php index b4c2d5a88a..beccfdc329 100644 --- a/src/applications/phame/storage/PhameBlog.php +++ b/src/applications/phame/storage/PhameBlog.php @@ -27,6 +27,23 @@ final class PhameBlog extends PhameDAO self::CONFIG_SERIALIZATION => array( 'configData' => self::SERIALIZATION_JSON, ), + self::CONFIG_COLUMN_SCHEMA => array( + 'name' => 'text64', + 'description' => 'text', + 'domain' => 'text255?', + 'joinPolicy' => 'policy', + ), + self::CONFIG_KEY_SCHEMA => array( + 'key_phid' => null, + 'phid' => array( + 'columns' => array('phid'), + 'unique' => true, + ), + 'domain' => array( + 'columns' => array('domain'), + 'unique' => true, + ), + ), ) + parent::getConfiguration(); } diff --git a/src/applications/phame/storage/PhamePost.php b/src/applications/phame/storage/PhamePost.php index a60b9d361c..bef665b7d6 100644 --- a/src/applications/phame/storage/PhamePost.php +++ b/src/applications/phame/storage/PhamePost.php @@ -88,6 +88,27 @@ final class PhamePost extends PhameDAO self::CONFIG_SERIALIZATION => array( 'configData' => self::SERIALIZATION_JSON, ), + self::CONFIG_COLUMN_SCHEMA => array( + 'title' => 'text255', + 'phameTitle' => 'text64', + 'body' => 'text', + 'visibility' => 'uint32', + 'datePublished' => 'epoch?', + ), + self::CONFIG_KEY_SCHEMA => array( + 'key_phid' => null, + 'phid' => array( + 'columns' => array('phid'), + 'unique' => true, + ), + 'phameTitle' => array( + 'columns' => array('bloggerPHID', 'phameTitle'), + 'unique' => true, + ), + 'bloggerPosts' => array( + 'columns' => array('bloggerPHID', 'visibility', 'datePublished'), + ), + ), ) + parent::getConfiguration(); } diff --git a/src/applications/phame/storage/PhameSchemaSpec.php b/src/applications/phame/storage/PhameSchemaSpec.php new file mode 100644 index 0000000000..7897316bf2 --- /dev/null +++ b/src/applications/phame/storage/PhameSchemaSpec.php @@ -0,0 +1,11 @@ +buildLiskSchemata('PhameDAO'); + $this->buildEdgeSchemata(new PhameBlog()); + } + +} diff --git a/src/applications/phlux/storage/PhluxSchemaSpec.php b/src/applications/phlux/storage/PhluxSchemaSpec.php new file mode 100644 index 0000000000..b243d94fe1 --- /dev/null +++ b/src/applications/phlux/storage/PhluxSchemaSpec.php @@ -0,0 +1,11 @@ +buildLiskSchemata('PhluxDAO'); + $this->buildTransactionSchema(new PhluxTransaction()); + } + +} diff --git a/src/applications/phlux/storage/PhluxVariable.php b/src/applications/phlux/storage/PhluxVariable.php index 88aa3ac22a..23a0ffcc82 100644 --- a/src/applications/phlux/storage/PhluxVariable.php +++ b/src/applications/phlux/storage/PhluxVariable.php @@ -16,6 +16,15 @@ final class PhluxVariable extends PhluxDAO self::CONFIG_SERIALIZATION => array( 'variableValue' => self::SERIALIZATION_JSON ), + self::CONFIG_COLUMN_SCHEMA => array( + 'variableKey' => 'text64', + ), + self::CONFIG_KEY_SCHEMA => array( + 'key_key' => array( + 'columns' => array('variableKey'), + 'unique' => true, + ), + ), ) + parent::getConfiguration(); } From 9777a1b4d1f56a0d03790a2a43d80d564688c62e Mon Sep 17 00:00:00 2001 From: Nipunn Koorapati Date: Wed, 24 Sep 2014 13:57:12 -0700 Subject: [PATCH 08/24] Revisionss -> revision Summary: Looks like a typo Test Plan: Careful inspection. Reviewers: epriestley, #blessed_reviewers Reviewed By: epriestley, #blessed_reviewers Subscribers: epriestley, Korvin Differential Revision: https://secure.phabricator.com/D10540 --- .../translation/PhabricatorBaseEnglishTranslation.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/infrastructure/internationalization/translation/PhabricatorBaseEnglishTranslation.php b/src/infrastructure/internationalization/translation/PhabricatorBaseEnglishTranslation.php index 8b1f4d1235..ccf452215a 100644 --- a/src/infrastructure/internationalization/translation/PhabricatorBaseEnglishTranslation.php +++ b/src/infrastructure/internationalization/translation/PhabricatorBaseEnglishTranslation.php @@ -1030,7 +1030,7 @@ abstract class PhabricatorBaseEnglishTranslation '%s added %s revision(s): %s.' => array( array( '%s added a revision: %3$s.', - '%s added revisionss: %3$s.', + '%s added revisions: %3$s.', ), ), From 66950a84b2e17b0bc866a1120cfa561679196adc Mon Sep 17 00:00:00 2001 From: James Rhodes Date: Thu, 25 Sep 2014 09:46:17 +1000 Subject: [PATCH 09/24] Fix failing test in PhabricatorPolicyDataTestCase caused by membership locking Summary: This fixes a unit test failure that started occurring due to the new membership locking feature. Test Plan: Ran the unit tests. Reviewers: btrahan, epriestley, #blessed_reviewers Reviewed By: epriestley, #blessed_reviewers Subscribers: epriestley, Korvin Differential Revision: https://secure.phabricator.com/D10546 --- .../policy/__tests__/PhabricatorPolicyDataTestCase.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/applications/policy/__tests__/PhabricatorPolicyDataTestCase.php b/src/applications/policy/__tests__/PhabricatorPolicyDataTestCase.php index 1e74f8bc9e..7f3c22666d 100644 --- a/src/applications/policy/__tests__/PhabricatorPolicyDataTestCase.php +++ b/src/applications/policy/__tests__/PhabricatorPolicyDataTestCase.php @@ -16,12 +16,14 @@ final class PhabricatorPolicyDataTestCase extends PhabricatorTestCase { ->setAuthorPHID($author->getPHID()) ->setIcon(PhabricatorProject::DEFAULT_ICON) ->setColor(PhabricatorProject::DEFAULT_COLOR) + ->setIsMembershipLocked(0) ->save(); $proj_b = id(new PhabricatorProject()) ->setName('B') ->setAuthorPHID($author->getPHID()) ->setIcon(PhabricatorProject::DEFAULT_ICON) ->setColor(PhabricatorProject::DEFAULT_COLOR) + ->setIsMembershipLocked(0) ->save(); $proj_a->setViewPolicy($proj_b->getPHID())->save(); From 4277123060764d78ff1b282413857e17ba7acc3b Mon Sep 17 00:00:00 2001 From: James Rhodes Date: Thu, 25 Sep 2014 09:46:47 +1000 Subject: [PATCH 10/24] Increase Drydock worker time to 24 hours Summary: Ref T2015. This increases the Drydock worker lease time to 24 hours. We noticed that some leases took longer than 2 hours when leasing from AWS (the actual resource was successfully leased at around 2 hours, 19 minutes). 24 hours should be plenty enough time to actually lease anything from EC2 (or any other leases during builds). Test Plan: Have not yet tested this. Reviewers: #blessed_reviewers, epriestley Reviewed By: #blessed_reviewers, epriestley Subscribers: epriestley, Korvin Maniphest Tasks: T2015 Differential Revision: https://secure.phabricator.com/D10544 --- src/applications/drydock/worker/DrydockAllocatorWorker.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/applications/drydock/worker/DrydockAllocatorWorker.php b/src/applications/drydock/worker/DrydockAllocatorWorker.php index 3b955f16fe..6d8e740e18 100644 --- a/src/applications/drydock/worker/DrydockAllocatorWorker.php +++ b/src/applications/drydock/worker/DrydockAllocatorWorker.php @@ -4,6 +4,10 @@ final class DrydockAllocatorWorker extends PhabricatorWorker { private $lease; + public function getRequiredLeaseTime() { + return 3600 * 24; + } + public function getMaximumRetryCount() { // TODO: Allow Drydock allocations to retry. For now, every failure is // permanent and most of them are because I am bad at programming, so fail From e64612f0d045a112bf672f19d34e9ef37ef13b8d Mon Sep 17 00:00:00 2001 From: Chad Little Date: Thu, 25 Sep 2014 10:57:44 -0700 Subject: [PATCH 11/24] Add actions to mobile Passphrase Summary: Take my secrets on the road Test Plan: View Passphrase on mobile device, see action list. Reviewers: epriestley Reviewed By: epriestley Subscribers: epriestley, Korvin Differential Revision: https://secure.phabricator.com/D10562 --- .../controller/PassphraseCredentialViewController.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/applications/passphrase/controller/PassphraseCredentialViewController.php b/src/applications/passphrase/controller/PassphraseCredentialViewController.php index 12dcd64287..e99484a61b 100644 --- a/src/applications/passphrase/controller/PassphraseCredentialViewController.php +++ b/src/applications/passphrase/controller/PassphraseCredentialViewController.php @@ -47,6 +47,8 @@ final class PassphraseCredentialViewController extends PassphraseController { $actions = $this->buildActionView($credential, $type); $properties = $this->buildPropertyView($credential, $type, $actions); + $crumbs->setActionList($actions); + $box = id(new PHUIObjectBoxView()) ->setHeader($header) ->addPropertyList($properties); From 3c527cc4721713be61d5e02a14d019feb16c3822 Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 25 Sep 2014 11:21:11 -0700 Subject: [PATCH 12/24] Add a setup issue to detect systems vulnerable to "Shellshock" Summary: Ref T6185. Although it seems that we can't easily defuse or mitigate this, we can at least warn administrators. Test Plan: Ran on my (unpatched, local) system, got a setup warning. Reviewers: btrahan, chad Reviewed By: chad Subscribers: epriestley Maniphest Tasks: T6185 Differential Revision: https://secure.phabricator.com/D10561 --- src/__phutil_library_map__.php | 2 + .../check/PhabricatorSetupCheckSecurity.php | 49 +++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 src/applications/config/check/PhabricatorSetupCheckSecurity.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index a8f81bc6f6..ff0d0bb903 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2256,6 +2256,7 @@ phutil_register_library_map(array( 'PhabricatorSetupCheckPath' => 'applications/config/check/PhabricatorSetupCheckPath.php', 'PhabricatorSetupCheckPygment' => 'applications/config/check/PhabricatorSetupCheckPygment.php', 'PhabricatorSetupCheckRepositories' => 'applications/config/check/PhabricatorSetupCheckRepositories.php', + 'PhabricatorSetupCheckSecurity' => 'applications/config/check/PhabricatorSetupCheckSecurity.php', 'PhabricatorSetupCheckStorage' => 'applications/config/check/PhabricatorSetupCheckStorage.php', 'PhabricatorSetupCheckTimezone' => 'applications/config/check/PhabricatorSetupCheckTimezone.php', 'PhabricatorSetupIssue' => 'applications/config/issue/PhabricatorSetupIssue.php', @@ -5240,6 +5241,7 @@ phutil_register_library_map(array( 'PhabricatorSetupCheckPath' => 'PhabricatorSetupCheck', 'PhabricatorSetupCheckPygment' => 'PhabricatorSetupCheck', 'PhabricatorSetupCheckRepositories' => 'PhabricatorSetupCheck', + 'PhabricatorSetupCheckSecurity' => 'PhabricatorSetupCheck', 'PhabricatorSetupCheckStorage' => 'PhabricatorSetupCheck', 'PhabricatorSetupCheckTimezone' => 'PhabricatorSetupCheck', 'PhabricatorSetupIssueExample' => 'PhabricatorUIExample', diff --git a/src/applications/config/check/PhabricatorSetupCheckSecurity.php b/src/applications/config/check/PhabricatorSetupCheckSecurity.php new file mode 100644 index 0000000000..f399d5302d --- /dev/null +++ b/src/applications/config/check/PhabricatorSetupCheckSecurity.php @@ -0,0 +1,49 @@ + '() { :;} ; echo VULNERABLE', + ); + + list($err, $stdout) = id(new ExecFuture('echo shellshock-test')) + ->setEnv($payload, $wipe_process_env = true) + ->resolve(); + + if (!$err && preg_match('/VULNERABLE/', $stdout)) { + $summary = pht( + 'This system has an unpatched version of Bash with a severe, widely '. + 'disclosed vulnerability.'); + + $message = pht( + 'The version of %s on this system is out of date and contains a '. + 'major, widely disclosed vulnerability (the "Shellshock" '. + 'vulnerability).'. + "\n\n". + 'Upgrade %s to a patched version.'. + "\n\n". + 'To learn more about how this issue affects Phabricator, see %s.', + phutil_tag('tt', array(), 'bash'), + phutil_tag('tt', array(), 'bash'), + phutil_tag( + 'a', + array( + 'href' => 'https://secure.phabricator.com/T6185', + 'target' => '_blank', + ), + pht('T6185 "Shellshock" Bash Vulnerability'))); + + $this + ->newIssue('security.shellshock') + ->setName(pht('Severe Security Vulnerability: Unpatched Bash')) + ->setSummary($summary) + ->setMessage($message); + } + + } +} From 9dee67618d5e5cdb0a09b4983fdc8b5b5d9fb19f Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 25 Sep 2014 13:42:38 -0700 Subject: [PATCH 13/24] Allow pastes to be destroyed Summary: Fixes T6186. Test Plan: - Used `bin/remove destroy Pxxx` to destroy a paste. - Verified file, transactions, etc., were destroyed. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T6186 Differential Revision: https://secure.phabricator.com/D10563 --- src/__phutil_library_map__.php | 2 + .../paste/storage/PhabricatorPaste.php | 40 ++++++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index ff0d0bb903..9b5f3ad6ef 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -4855,6 +4855,8 @@ phutil_register_library_map(array( 'PhabricatorMentionableInterface', 'PhabricatorPolicyInterface', 'PhabricatorProjectInterface', + 'PhabricatorDestructibleInterface', + 'PhabricatorApplicationTransactionInterface', ), 'PhabricatorPasteApplication' => 'PhabricatorApplication', 'PhabricatorPasteCommentController' => 'PhabricatorPasteController', diff --git a/src/applications/paste/storage/PhabricatorPaste.php b/src/applications/paste/storage/PhabricatorPaste.php index 0b725c7a90..9191f316a2 100644 --- a/src/applications/paste/storage/PhabricatorPaste.php +++ b/src/applications/paste/storage/PhabricatorPaste.php @@ -7,7 +7,9 @@ final class PhabricatorPaste extends PhabricatorPasteDAO PhabricatorFlaggableInterface, PhabricatorMentionableInterface, PhabricatorPolicyInterface, - PhabricatorProjectInterface { + PhabricatorProjectInterface, + PhabricatorDestructibleInterface, + PhabricatorApplicationTransactionInterface { protected $title; protected $authorPHID; @@ -152,4 +154,40 @@ final class PhabricatorPaste extends PhabricatorPasteDAO return pht('The author of a paste can always view and edit it.'); } + +/* -( PhabricatorDestructibleInterface )----------------------------------- */ + + + public function destroyObjectPermanently( + PhabricatorDestructionEngine $engine) { + + if ($this->filePHID) { + $file = id(new PhabricatorFileQuery()) + ->setViewer(PhabricatorUser::getOmnipotentUser()) + ->withPHIDs(array($this->filePHID)) + ->executeOne(); + if ($file) { + $engine->destroyObject($file); + } + } + + $this->delete(); + } + + +/* -( PhabricatorApplicationTransactionInterface )------------------------- */ + + + public function getApplicationTransactionEditor() { + return new PhabricatorPasteEditor(); + } + + public function getApplicationTransactionObject() { + return $this; + } + + public function getApplicationTransactionTemplate() { + return new PhabricatorPasteTransaction(); + } + } From f605780893b3e57a04ac7c72b618b83828f6e45d Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 25 Sep 2014 13:42:46 -0700 Subject: [PATCH 14/24] Export Ponder question and answer bodies as remarkup blocks during transactions Summary: Fixes T6189. We currently don't raise these to the editor level, so files, mentions, and project stuff get ignored. Test Plan: Verified that files added to question and answer bodies end up attached to the relevant objects. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T6189 Differential Revision: https://secure.phabricator.com/D10564 --- .../ponder/storage/PonderAnswerTransaction.php | 12 ++++++++++++ .../ponder/storage/PonderQuestionTransaction.php | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/applications/ponder/storage/PonderAnswerTransaction.php b/src/applications/ponder/storage/PonderAnswerTransaction.php index e1a7c029a2..b9c7bf2190 100644 --- a/src/applications/ponder/storage/PonderAnswerTransaction.php +++ b/src/applications/ponder/storage/PonderAnswerTransaction.php @@ -33,6 +33,18 @@ final class PonderAnswerTransaction return $phids; } + public function getRemarkupBlocks() { + $blocks = parent::getRemarkupBlocks(); + + switch ($this->getTransactionType()) { + case self::TYPE_CONTENT: + $blocks[] = $this->getNewValue(); + break; + } + + return $blocks; + } + public function getTitle() { $author_phid = $this->getAuthorPHID(); $object_phid = $this->getObjectPHID(); diff --git a/src/applications/ponder/storage/PonderQuestionTransaction.php b/src/applications/ponder/storage/PonderQuestionTransaction.php index 9bfaf6a741..19590838c4 100644 --- a/src/applications/ponder/storage/PonderQuestionTransaction.php +++ b/src/applications/ponder/storage/PonderQuestionTransaction.php @@ -37,6 +37,18 @@ final class PonderQuestionTransaction return $phids; } + public function getRemarkupBlocks() { + $blocks = parent::getRemarkupBlocks(); + + switch ($this->getTransactionType()) { + case self::TYPE_CONTENT: + $blocks[] = $this->getNewValue(); + break; + } + + return $blocks; + } + public function getTitle() { $author_phid = $this->getAuthorPHID(); $object_phid = $this->getObjectPHID(); From 5f04bb6dd9582e2021f41c3f5ec2caea73bef2eb Mon Sep 17 00:00:00 2001 From: Chad Little Date: Fri, 26 Sep 2014 09:28:37 -0700 Subject: [PATCH 15/24] Check calendar is installed on profile Summary: Fixes T6199, checks if Calendar is installed and displays if so. Test Plan: Turned Calendar on and off, tested both layouts. Reviewers: btrahan, epriestley Reviewed By: epriestley Subscribers: epriestley, Korvin Maniphest Tasks: T6199 Differential Revision: https://secure.phabricator.com/D10574 --- resources/celerity/map.php | 4 ++-- .../PhabricatorPeopleProfileController.php | 13 +++++++++++-- .../rsrc/css/application/profile/profile-view.css | 4 ++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 9e171e90a6..67464e67a0 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -93,7 +93,7 @@ return array( 'rsrc/css/application/ponder/feed.css' => 'e62615b6', 'rsrc/css/application/ponder/post.css' => 'ebab8a70', 'rsrc/css/application/ponder/vote.css' => '8ed6ed8b', - 'rsrc/css/application/profile/profile-view.css' => 'b459416e', + 'rsrc/css/application/profile/profile-view.css' => '28f433ef', 'rsrc/css/application/projects/project-icon.css' => 'c2ecb7f1', 'rsrc/css/application/releeph/releeph-core.css' => '9b3c5733', 'rsrc/css/application/releeph/releeph-preview-branch.css' => 'b7a6f4a5', @@ -732,7 +732,7 @@ return array( 'phabricator-object-selector-css' => '029a133d', 'phabricator-phtize' => 'd254d646', 'phabricator-prefab' => 'bbae734c', - 'phabricator-profile-css' => 'b459416e', + 'phabricator-profile-css' => '28f433ef', 'phabricator-remarkup-css' => '45313445', 'phabricator-search-results-css' => 'f240504c', 'phabricator-shaped-request' => '7cbe244b', diff --git a/src/applications/people/controller/PhabricatorPeopleProfileController.php b/src/applications/people/controller/PhabricatorPeopleProfileController.php index 398ffe8f4c..4a4524d8aa 100644 --- a/src/applications/people/controller/PhabricatorPeopleProfileController.php +++ b/src/applications/people/controller/PhabricatorPeopleProfileController.php @@ -133,11 +133,20 @@ final class PhabricatorPeopleProfileController $crumbs->addTextCrumb($user->getUsername()); $crumbs->setActionList($actions); $feed = $this->renderUserFeed($user); - $calendar = $this->renderUserCalendar($user); + $cal_class = 'PhabricatorCalendarApplication'; + $classes = array(); + $classes[] = 'profile-activity-view'; + if (PhabricatorApplication::isClassInstalledForViewer($cal_class, $user)) { + $calendar = $this->renderUserCalendar($user); + $classes[] = 'profile-has-calendar'; + $classes[] = 'grouped'; + } else { + $calendar = null; + } $activity = phutil_tag( 'div', array( - 'class' => 'profile-activity-view grouped' + 'class' => implode($classes, ' '), ), array( $calendar, diff --git a/webroot/rsrc/css/application/profile/profile-view.css b/webroot/rsrc/css/application/profile/profile-view.css index 47214d9d68..a51fa5a195 100644 --- a/webroot/rsrc/css/application/profile/profile-view.css +++ b/webroot/rsrc/css/application/profile/profile-view.css @@ -30,6 +30,10 @@ } .profile-activity-view .profile-feed { + margin-left: 16px; +} + +.profile-activity-view.profile-has-calendar .profile-feed { margin-left: 332px; } From 313468cef0dd0880417bd56cab3429cd0df2aaba Mon Sep 17 00:00:00 2001 From: cburroughs Date: Fri, 26 Sep 2014 09:29:54 -0700 Subject: [PATCH 16/24] fix misc diviner formatting errors Summary: fix misc diviner formatting errors Test Plan: Read the docs. Reviewers: #blessed_reviewers, epriestley Reviewed By: #blessed_reviewers, epriestley Subscribers: epriestley Differential Revision: https://secure.phabricator.com/D10559 --- src/docs/user/userguide/arcanist.diviner | 2 +- src/docs/user/userguide/phame.diviner | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/docs/user/userguide/arcanist.diviner b/src/docs/user/userguide/arcanist.diviner index 8f8ba37eb5..cccdbaf243 100644 --- a/src/docs/user/userguide/arcanist.diviner +++ b/src/docs/user/userguide/arcanist.diviner @@ -158,7 +158,7 @@ several sources: # User can specify the settings in `~/.arcrc` (JSON) through the `config` key. This file can be modified also by `arc set-config --global`. # Machine can specify the settings with `/etc/arcconfig` (JSON). On Windows, - the file path is 'C:\ProgramData\Phabricator\Arcanist\config`. + the file path is `C:\ProgramData\Phabricator\Arcanist\config`. The first place where the setting is defined wins. diff --git a/src/docs/user/userguide/phame.diviner b/src/docs/user/userguide/phame.diviner index 8422a8e8c7..28635886d8 100644 --- a/src/docs/user/userguide/phame.diviner +++ b/src/docs/user/userguide/phame.diviner @@ -59,4 +59,5 @@ of whether that post is being viewed in the context of a blog. = Next Steps = - Phame is extremely new and very basic for now. Give us feedback on -what you'd like to see improve! See @{article:Give Feedback! Get Support!}. + what you'd like to see improve! See @{article:Give Feedback! Get + Support!}. From aefdf3122156d82f0dfe042bc2ce9a090b56f119 Mon Sep 17 00:00:00 2001 From: cburroughs Date: Fri, 26 Sep 2014 09:30:22 -0700 Subject: [PATCH 17/24] use nav markup in userguide Summary: An explicit navigation markup was recenty added. Use it in the userguide instead of ad-hoc -> or `->` chains. Test Plan: Read the docs. Reviewers: #blessed_reviewers, epriestley Reviewed By: #blessed_reviewers, epriestley Subscribers: epriestley Differential Revision: https://secure.phabricator.com/D10560 Conflicts: src/docs/user/userguide/diffusion_hosting.diviner --- src/docs/user/userguide/diffusion_hosting.diviner | 9 ++++----- src/docs/user/userguide/diffusion_symbols.diviner | 2 +- src/docs/user/userguide/external_editor.diviner | 4 ++-- src/docs/user/userguide/mail_rules.diviner | 2 +- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/docs/user/userguide/diffusion_hosting.diviner b/src/docs/user/userguide/diffusion_hosting.diviner index 1639639831..ecf7e1c3e3 100644 --- a/src/docs/user/userguide/diffusion_hosting.diviner +++ b/src/docs/user/userguide/diffusion_hosting.diviner @@ -127,7 +127,7 @@ If you plan to use authenticated HTTP, you need to set use only anonymous HTTP, you can leave this setting disabled. If you plan to use authenticated HTTP, you'll also need to configure a VCS -password in "Settings" -> "VCS Password". This is a different password than +password in {nav Settings > VCS Password}. This is a different password than your main Phabricator password primarily for security reasons. Otherwise, if you've configured system accounts above, you're all set. No @@ -254,9 +254,9 @@ Some general tips for troubleshooting problems with HTTP: - Make sure `diffusion.allow-http-auth` is enabled in your Phabricator config. - Make sure HTTP serving is enabled for the repository you're trying to clone. - You can find this in "Edit Repository" -> "Hosting". + You can find this in {nav Edit Repository > Hosting}. - Make sure you've configured a VCS password. This is separate from your main - account password. You can configure this in "Settings" -> "VCS Password". + account password. You can configure this in {nav Settings > VCS Password}. - Make sure the main repository screen in Diffusion shows a clone/checkout command for HTTP. If it doesn't, something above isn't set up correctly: double-check your configuration. You should see a `svn checkout http://...`, @@ -291,8 +291,7 @@ Some general tips for troubleshooting problems with SSH: SSH Read Only or Read/Write > Save Changes}. - Make sure you've added an SSH public key to your account. You can do this - in {nav Settings > - SSH Public Keys}. + in {nav Settings > SSH Public Keys}. - Make sure the main repository screen in Diffusion shows a clone/checkout command for SSH. If it doesn't, something above isn't set up correctly. You should see an `svn checkout svn+ssh://...`, `git clone ssh://...` or diff --git a/src/docs/user/userguide/diffusion_symbols.diviner b/src/docs/user/userguide/diffusion_symbols.diviner index b9b96ec209..0a212055d5 100644 --- a/src/docs/user/userguide/diffusion_symbols.diviner +++ b/src/docs/user/userguide/diffusion_symbols.diviner @@ -77,7 +77,7 @@ configuration. To configure Differential integration, you need to tell Phabricator which projects have symbol indexes you want to use, and which other projects they should pull symbols from. To do this, go to -`Repositories -> Arcanist Projects -> Edit` as an administrator. You need to +{nav Repositories > Arcanist Projects > Edit} as an administrator. You need to fill out these fields: - **Repository**: Associate the project with a tracked repository. diff --git a/src/docs/user/userguide/external_editor.diviner b/src/docs/user/userguide/external_editor.diviner index 675ed7eb1f..c98ccb1903 100644 --- a/src/docs/user/userguide/external_editor.diviner +++ b/src/docs/user/userguide/external_editor.diviner @@ -10,8 +10,8 @@ and Diffusion in your preferred text editor. = Configuring Editors = -To configure an external editor, go to Settings -> Application Settings -> -Display Preferences and set "Editor Link" to a URI pattern (see below). This +To configure an external editor, go to {nav Settings > Application Settings > +Display Preferences} and set "Editor Link" to a URI pattern (see below). This will enable an "Open in Editor" link in Differential, and an "Edit" button in Diffusion. diff --git a/src/docs/user/userguide/mail_rules.diviner b/src/docs/user/userguide/mail_rules.diviner index cc0860a1ae..64d0723fdb 100644 --- a/src/docs/user/userguide/mail_rules.diviner +++ b/src/docs/user/userguide/mail_rules.diviner @@ -16,7 +16,7 @@ write sophisticated rules to route, categorize, or delete email. = Reducing Email = You can reduce the amount of email you receive by turning off some types of -email in ##Settings -> Email Preferences##. For example, you can turn off email +email in {nav Settings > Email Preferences}. For example, you can turn off email produced by your own actions (like when you comment on a revision), and some types of less-important notifications about events. From 3ce107fc429e81dccadf8b2e13cdad673c92e054 Mon Sep 17 00:00:00 2001 From: Chad Little Date: Fri, 26 Sep 2014 14:27:37 -0700 Subject: [PATCH 18/24] Remove Date from Diff hovercard Summary: Fixes T6184. On a Revision page we don't show the date as an important piece of information, so it's also not likely useful on a Hovercard (and confusing as to what the date means). Test Plan: Hover over a linked Diff Reviewers: btrahan, epriestley Reviewed By: epriestley Subscribers: epriestley, Korvin Maniphest Tasks: T6184 Differential Revision: https://secure.phabricator.com/D10579 --- .../differential/event/DifferentialHovercardEventListener.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/applications/differential/event/DifferentialHovercardEventListener.php b/src/applications/differential/event/DifferentialHovercardEventListener.php index 5e7556cbc3..80ef4eb249 100644 --- a/src/applications/differential/event/DifferentialHovercardEventListener.php +++ b/src/applications/differential/event/DifferentialHovercardEventListener.php @@ -56,9 +56,6 @@ final class DifferentialHovercardEventListener $hovercard->addField(pht('Author'), $handles[$rev->getAuthorPHID()]->renderLink()); - $hovercard->addField(pht('Date'), - phabricator_datetime($rev->getDateModified(), $viewer)); - $hovercard->addField(pht('Reviewers'), implode_selected_handle_links(', ', $handles, $reviewer_phids)); From f74082aecd06f2a5df8859cbbcd39254f529d00d Mon Sep 17 00:00:00 2001 From: Chad Little Date: Fri, 26 Sep 2014 17:40:09 -0700 Subject: [PATCH 19/24] Update AphrontRequestFailure to common display libs Summary: Moves to PHUIObjectBox, removes old CSS Test Plan: Pull up 404 page. Reviewers: epriestley Reviewed By: epriestley Subscribers: epriestley, Korvin Differential Revision: https://secure.phabricator.com/D10578 --- resources/celerity/map.php | 2 - src/__phutil_library_map__.php | 2 - src/aphront/response/Aphront403Response.php | 23 ++++++---- src/aphront/response/Aphront404Response.php | 18 +++++--- .../PhabricatorDisabledUserController.php | 15 +++---- src/view/page/AphrontRequestFailureView.php | 27 ----------- .../rsrc/css/aphront/request-failure-view.css | 45 ------------------- 7 files changed, 32 insertions(+), 100 deletions(-) delete mode 100644 src/view/page/AphrontRequestFailureView.php delete mode 100644 webroot/rsrc/css/aphront/request-failure-view.css diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 67464e67a0..15e4691c7e 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -28,7 +28,6 @@ return array( 'rsrc/css/aphront/pager-view.css' => '2e3539af', 'rsrc/css/aphront/panel-view.css' => '5846dfa2', 'rsrc/css/aphront/phabricator-nav-view.css' => '9283c2df', - 'rsrc/css/aphront/request-failure-view.css' => '7a83dc3a', 'rsrc/css/aphront/table-view.css' => 'b22b7216', 'rsrc/css/aphront/tokenizer.css' => '82ce2142', 'rsrc/css/aphront/tooltip.css' => '9c90229d', @@ -506,7 +505,6 @@ return array( 'aphront-multi-column-view-css' => '1b95ab2e', 'aphront-pager-view-css' => '2e3539af', 'aphront-panel-view-css' => '5846dfa2', - 'aphront-request-failure-view-css' => '7a83dc3a', 'aphront-table-view-css' => 'b22b7216', 'aphront-tokenizer-control-css' => '82ce2142', 'aphront-tooltip-css' => '9c90229d', diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 9b5f3ad6ef..0fd51a691a 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -79,7 +79,6 @@ phutil_register_library_map(array( 'AphrontRedirectResponseTestCase' => 'aphront/response/__tests__/AphrontRedirectResponseTestCase.php', 'AphrontReloadResponse' => 'aphront/response/AphrontReloadResponse.php', 'AphrontRequest' => 'aphront/AphrontRequest.php', - 'AphrontRequestFailureView' => 'view/page/AphrontRequestFailureView.php', 'AphrontRequestTestCase' => 'aphront/__tests__/AphrontRequestTestCase.php', 'AphrontResponse' => 'aphront/response/AphrontResponse.php', 'AphrontSideNavFilterView' => 'view/layout/AphrontSideNavFilterView.php', @@ -2923,7 +2922,6 @@ phutil_register_library_map(array( 'AphrontRedirectResponse' => 'AphrontResponse', 'AphrontRedirectResponseTestCase' => 'PhabricatorTestCase', 'AphrontReloadResponse' => 'AphrontRedirectResponse', - 'AphrontRequestFailureView' => 'AphrontView', 'AphrontRequestTestCase' => 'PhabricatorTestCase', 'AphrontSideNavFilterView' => 'AphrontView', 'AphrontStackTraceView' => 'AphrontView', diff --git a/src/aphront/response/Aphront403Response.php b/src/aphront/response/Aphront403Response.php index 8866b0ec0b..3f7f6d73ca 100644 --- a/src/aphront/response/Aphront403Response.php +++ b/src/aphront/response/Aphront403Response.php @@ -19,16 +19,23 @@ final class Aphront403Response extends AphrontHTMLResponse { $forbidden_text = $this->getForbiddenText(); if (!$forbidden_text) { $forbidden_text = - 'You do not have privileges to access the requested page.'; + pht('You do not have privileges to access the requested page.'); } - $failure = new AphrontRequestFailureView(); - $failure->setHeader('403 Forbidden'); - $failure->appendChild(phutil_tag('p', array(), $forbidden_text)); - $view = new PhabricatorStandardPageView(); - $view->setTitle('403 Forbidden'); - $view->setRequest($this->getRequest()); - $view->appendChild($failure); + $request = $this->getRequest(); + $user = $request->getUser(); + + $dialog = id(new AphrontDialogView()) + ->setUser($user) + ->setTitle(pht('403 Forbidden')) + ->addCancelButton('/', pht('Peace Out')) + ->appendParagraph($forbidden_text); + + $view = id(new PhabricatorStandardPageView()) + ->setTitle(pht('403 Forbidden')) + ->setRequest($request) + ->setDeviceReady(true) + ->appendChild($dialog); return $view->render(); } diff --git a/src/aphront/response/Aphront404Response.php b/src/aphront/response/Aphront404Response.php index 1dddc7a01f..85dec30555 100644 --- a/src/aphront/response/Aphront404Response.php +++ b/src/aphront/response/Aphront404Response.php @@ -7,16 +7,22 @@ final class Aphront404Response extends AphrontHTMLResponse { } public function buildResponseString() { - $failure = id(new AphrontRequestFailureView()) - ->setHeader(pht('404 Not Found')) - ->appendChild(phutil_tag('p', array(), pht( - 'The page you requested was not found.'))); + $request = $this->getRequest(); + $user = $request->getUser(); + + $dialog = id(new AphrontDialogView()) + ->setUser($user) + ->setTitle(pht('404 Not Found')) + ->addCancelButton('/', pht('Focus')) + ->appendParagraph(pht( + 'Do not dwell in the past, do not dream of the future, '. + 'concentrate the mind on the present moment.')); $view = id(new PhabricatorStandardPageView()) ->setTitle('404 Not Found') - ->setRequest($this->getRequest()) + ->setRequest($request) ->setDeviceReady(true) - ->appendChild($failure); + ->appendChild($dialog); return $view->render(); } diff --git a/src/applications/auth/controller/PhabricatorDisabledUserController.php b/src/applications/auth/controller/PhabricatorDisabledUserController.php index 364a9a61ec..842f2daad6 100644 --- a/src/applications/auth/controller/PhabricatorDisabledUserController.php +++ b/src/applications/auth/controller/PhabricatorDisabledUserController.php @@ -14,16 +14,11 @@ final class PhabricatorDisabledUserController return new Aphront404Response(); } - $failure_view = new AphrontRequestFailureView(); - $failure_view->setHeader(pht('Account Disabled')); - $failure_view->appendChild(phutil_tag('p', array(), pht( - 'Your account has been disabled.'))); - - return $this->buildStandardPageResponse( - $failure_view, - array( - 'title' => pht('Account Disabled'), - )); + return id(new AphrontDialogView()) + ->setUser($user) + ->setTitle(pht('Account Disabled')) + ->addCancelButton('/logout/', pht('Okay')) + ->appendParagraph(pht('Your account has been disabled.')); } } diff --git a/src/view/page/AphrontRequestFailureView.php b/src/view/page/AphrontRequestFailureView.php deleted file mode 100644 index 5910b4468f..0000000000 --- a/src/view/page/AphrontRequestFailureView.php +++ /dev/null @@ -1,27 +0,0 @@ -header = $header; - return $this; - } - - - final public function render() { - require_celerity_resource('aphront-request-failure-view-css'); - - $head = phutil_tag_div( - 'aphront-request-failure-head', - phutil_tag('h1', array(), $this->header)); - - $body = phutil_tag_div( - 'aphront-request-failure-body', - $this->renderChildren()); - - return phutil_tag_div('aphront-request-failure-view', array($head, $body)); - } - -} diff --git a/webroot/rsrc/css/aphront/request-failure-view.css b/webroot/rsrc/css/aphront/request-failure-view.css deleted file mode 100644 index 7a2cca8063..0000000000 --- a/webroot/rsrc/css/aphront/request-failure-view.css +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @provides aphront-request-failure-view-css - */ - -.aphront-request-failure-view { - margin: 16px auto; - background: #eff2f7; - width: 600px; -} - -.device .aphront-request-failure-view { - width: 90%; -} - -.aphront-request-failure-view .aphront-request-failure-head { - padding: 1em 2em; - border-bottom: 1px solid #afb2b7; - background: #dfe2e7; -} - -.aphront-request-failure-view .aphront-request-failure-head h1 { - font-size: 24px; -} - -.aphront-request-failure-view .aphront-request-failure-body { - padding: 1em 2em 1.5em; -} - -.aphront-request-failure-view .aphront-request-failure-body p { - margin: .5em 0; -} - -.aphront-failure-continue { - margin-top: 1.5em; - text-align: right; -} - -.aphront-failure-continue a.button { - margin-left: 1em; -} - -.aphront-request-failure-view ul { - list-style: disc; - margin-left: 3em; -} From b149cb7e99e5be54129428026669b37840c397d7 Mon Sep 17 00:00:00 2001 From: epriestley Date: Sun, 28 Sep 2014 15:12:21 -0700 Subject: [PATCH 20/24] Generate expected schemata for Repository Summary: Ref T1191. Add specs for repository tables. Test Plan: Saw ~300 fewer schema warnings. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T1191 Differential Revision: https://secure.phabricator.com/D10575 --- src/__phutil_library_map__.php | 2 + .../schema/PhabricatorConfigSchemaSpec.php | 10 + .../storage/PhabricatorRepository.php | 26 +++ .../PhabricatorRepositoryArcanistProject.php | 15 ++ .../PhabricatorRepositoryAuditRequest.php | 11 ++ .../storage/PhabricatorRepositoryBranch.php | 15 ++ .../storage/PhabricatorRepositoryCommit.php | 28 +++ .../PhabricatorRepositoryCommitData.php | 13 ++ .../storage/PhabricatorRepositoryMirror.php | 9 + .../PhabricatorRepositoryPushEvent.php | 11 ++ .../storage/PhabricatorRepositoryPushLog.php | 27 +++ .../PhabricatorRepositoryRefCursor.php | 11 ++ .../PhabricatorRepositorySchemaSpec.php | 185 ++++++++++++++++++ .../PhabricatorRepositoryStatusMessage.php | 10 + .../storage/PhabricatorRepositorySymbol.php | 14 ++ .../PhabricatorRepositoryVCSPassword.php | 14 ++ 16 files changed, 401 insertions(+) create mode 100644 src/applications/repository/storage/PhabricatorRepositorySchemaSpec.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 0fd51a691a..bd49877f45 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2143,6 +2143,7 @@ phutil_register_library_map(array( 'PhabricatorRepositoryRefCursorQuery' => 'applications/repository/query/PhabricatorRepositoryRefCursorQuery.php', 'PhabricatorRepositoryRefEngine' => 'applications/repository/engine/PhabricatorRepositoryRefEngine.php', 'PhabricatorRepositoryRepositoryPHIDType' => 'applications/repository/phid/PhabricatorRepositoryRepositoryPHIDType.php', + 'PhabricatorRepositorySchemaSpec' => 'applications/repository/storage/PhabricatorRepositorySchemaSpec.php', 'PhabricatorRepositorySearchEngine' => 'applications/repository/query/PhabricatorRepositorySearchEngine.php', 'PhabricatorRepositoryStatusMessage' => 'applications/repository/storage/PhabricatorRepositoryStatusMessage.php', 'PhabricatorRepositorySvnCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/PhabricatorRepositorySvnCommitChangeParserWorker.php', @@ -5139,6 +5140,7 @@ phutil_register_library_map(array( 'PhabricatorRepositoryRefCursorQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorRepositoryRefEngine' => 'PhabricatorRepositoryEngine', 'PhabricatorRepositoryRepositoryPHIDType' => 'PhabricatorPHIDType', + 'PhabricatorRepositorySchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorRepositorySearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorRepositoryStatusMessage' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositorySvnCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker', diff --git a/src/applications/config/schema/PhabricatorConfigSchemaSpec.php b/src/applications/config/schema/PhabricatorConfigSchemaSpec.php index bd4eb3075e..d44705f45b 100644 --- a/src/applications/config/schema/PhabricatorConfigSchemaSpec.php +++ b/src/applications/config/schema/PhabricatorConfigSchemaSpec.php @@ -246,6 +246,11 @@ abstract class PhabricatorConfigSchemaSpec extends Phobject { $charset = 'binary'; $collation = 'binary'; break; + case 'bytes32': + $column_type = 'char(32)'; + $charset = 'binary'; + $collation = 'binary'; + break; case 'bytes12': $column_type = 'char(12)'; $charset = 'binary'; @@ -266,6 +271,11 @@ abstract class PhabricatorConfigSchemaSpec extends Phobject { $charset = $this->getUTF8Charset(); $collation = $this->getUTF8Collation(); break; + case 'text80': + $column_type = 'varchar(80)'; + $charset = $this->getUTF8Charset(); + $collation = $this->getUTF8Collation(); + break; case 'text64': $column_type = 'varchar(64)'; $charset = $this->getUTF8Charset(); diff --git a/src/applications/repository/storage/PhabricatorRepository.php b/src/applications/repository/storage/PhabricatorRepository.php index 10f225173f..858729d6dd 100644 --- a/src/applications/repository/storage/PhabricatorRepository.php +++ b/src/applications/repository/storage/PhabricatorRepository.php @@ -29,6 +29,7 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO const TABLE_BADCOMMIT = 'repository_badcommit'; const TABLE_LINTMESSAGE = 'repository_lintmessage'; const TABLE_PARENTS = 'repository_parents'; + const TABLE_COVERAGE = 'repository_coverage'; const SERVE_OFF = 'off'; const SERVE_READONLY = 'readonly'; @@ -77,6 +78,31 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO self::CONFIG_SERIALIZATION => array( 'details' => self::SERIALIZATION_JSON, ), + self::CONFIG_COLUMN_SCHEMA => array( + 'name' => 'text255', + 'callsign' => 'text32', + 'versionControlSystem' => 'text32', + 'uuid' => 'text64?', + 'pushPolicy' => 'policy', + 'credentialPHID' => 'phid?', + ), + self::CONFIG_KEY_SCHEMA => array( + 'key_phid' => null, + 'phid' => array( + 'columns' => array('phid'), + 'unique' => true, + ), + 'callsign' => array( + 'columns' => array('callsign'), + 'unique' => true, + ), + 'key_name' => array( + 'columns' => array('name'), + ), + 'key_vcs' => array( + 'columns' => array('versionControlSystem'), + ), + ), ) + parent::getConfiguration(); } diff --git a/src/applications/repository/storage/PhabricatorRepositoryArcanistProject.php b/src/applications/repository/storage/PhabricatorRepositoryArcanistProject.php index b325cc245a..9f51be32c1 100644 --- a/src/applications/repository/storage/PhabricatorRepositoryArcanistProject.php +++ b/src/applications/repository/storage/PhabricatorRepositoryArcanistProject.php @@ -22,6 +22,21 @@ final class PhabricatorRepositoryArcanistProject 'symbolIndexLanguages' => self::SERIALIZATION_JSON, 'symbolIndexProjects' => self::SERIALIZATION_JSON, ), + self::CONFIG_COLUMN_SCHEMA => array( + 'name' => 'text255', + 'repositoryID' => 'id?', + ), + self::CONFIG_KEY_SCHEMA => array( + 'key_phid' => null, + 'phid' => array( + 'columns' => array('phid'), + 'unique' => true, + ), + 'name' => array( + 'columns' => array('name'), + 'unique' => true, + ), + ), ) + parent::getConfiguration(); } diff --git a/src/applications/repository/storage/PhabricatorRepositoryAuditRequest.php b/src/applications/repository/storage/PhabricatorRepositoryAuditRequest.php index 78d969f746..9752529253 100644 --- a/src/applications/repository/storage/PhabricatorRepositoryAuditRequest.php +++ b/src/applications/repository/storage/PhabricatorRepositoryAuditRequest.php @@ -17,6 +17,17 @@ final class PhabricatorRepositoryAuditRequest self::CONFIG_SERIALIZATION => array( 'auditReasons' => self::SERIALIZATION_JSON, ), + self::CONFIG_COLUMN_SCHEMA => array( + 'auditStatus' => 'text64', + ), + self::CONFIG_KEY_SCHEMA => array( + 'commitPHID' => array( + 'columns' => array('commitPHID'), + ), + 'auditorPHID' => array( + 'columns' => array('auditorPHID', 'auditStatus'), + ), + ), ) + parent::getConfiguration(); } diff --git a/src/applications/repository/storage/PhabricatorRepositoryBranch.php b/src/applications/repository/storage/PhabricatorRepositoryBranch.php index 5eb4d1f46f..c6eccb902a 100644 --- a/src/applications/repository/storage/PhabricatorRepositoryBranch.php +++ b/src/applications/repository/storage/PhabricatorRepositoryBranch.php @@ -6,6 +6,21 @@ final class PhabricatorRepositoryBranch extends PhabricatorRepositoryDAO { protected $name; protected $lintCommit; + public function getConfiguration() { + return array( + self::CONFIG_COLUMN_SCHEMA => array( + 'name' => 'text255', + 'lintCommit' => 'text40?', + ), + self::CONFIG_KEY_SCHEMA => array( + 'repositoryID' => array( + 'columns' => array('repositoryID', 'name'), + 'unique' => true, + ), + ), + ) + parent::getConfiguration(); + } + public static function loadBranch($repository_id, $branch_name) { return id(new PhabricatorRepositoryBranch())->loadOneWhere( 'repositoryID = %d AND name = %s', diff --git a/src/applications/repository/storage/PhabricatorRepositoryCommit.php b/src/applications/repository/storage/PhabricatorRepositoryCommit.php index cea1c9ad39..159177c8e9 100644 --- a/src/applications/repository/storage/PhabricatorRepositoryCommit.php +++ b/src/applications/repository/storage/PhabricatorRepositoryCommit.php @@ -66,6 +66,34 @@ final class PhabricatorRepositoryCommit return array( self::CONFIG_AUX_PHID => true, self::CONFIG_TIMESTAMPS => false, + self::CONFIG_COLUMN_SCHEMA => array( + 'commitIdentifier' => 'text40', + 'mailKey' => 'bytes20', + 'authorPHID' => 'phid?', + 'auditStatus' => 'uint32', + 'summary' => 'text80', + 'importStatus' => 'uint32', + ), + self::CONFIG_KEY_SCHEMA => array( + 'key_phid' => null, + 'phid' => array( + 'columns' => array('phid'), + 'unique' => true, + ), + 'repositoryID' => array( + 'columns' => array('repositoryID', 'importStatus'), + ), + 'authorPHID' => array( + 'columns' => array('authorPHID', 'auditStatus', 'epoch'), + ), + 'repositoryID_2' => array( + 'columns' => array('repositoryID', 'epoch'), + ), + 'key_commit_identity' => array( + 'columns' => array('commitIdentifier', 'repositoryID'), + 'unique' => true, + ), + ), ) + parent::getConfiguration(); } diff --git a/src/applications/repository/storage/PhabricatorRepositoryCommitData.php b/src/applications/repository/storage/PhabricatorRepositoryCommitData.php index 499e16ab78..474a8a239d 100644 --- a/src/applications/repository/storage/PhabricatorRepositoryCommitData.php +++ b/src/applications/repository/storage/PhabricatorRepositoryCommitData.php @@ -19,6 +19,19 @@ final class PhabricatorRepositoryCommitData extends PhabricatorRepositoryDAO { self::CONFIG_SERIALIZATION => array( 'commitDetails' => self::SERIALIZATION_JSON, ), + self::CONFIG_COLUMN_SCHEMA => array( + 'authorName' => 'text255', + 'commitMessage' => 'text', + ), + self::CONFIG_KEY_SCHEMA => array( + 'commitID' => array( + 'columns' => array('commitID'), + 'unique' => true, + ), + 'authorName' => array( + 'columns' => array('authorName'), + ), + ), ) + parent::getConfiguration(); } diff --git a/src/applications/repository/storage/PhabricatorRepositoryMirror.php b/src/applications/repository/storage/PhabricatorRepositoryMirror.php index d215a83d03..b778806f33 100644 --- a/src/applications/repository/storage/PhabricatorRepositoryMirror.php +++ b/src/applications/repository/storage/PhabricatorRepositoryMirror.php @@ -17,6 +17,15 @@ final class PhabricatorRepositoryMirror extends PhabricatorRepositoryDAO public function getConfiguration() { return array( self::CONFIG_AUX_PHID => true, + self::CONFIG_COLUMN_SCHEMA => array( + 'remoteURI' => 'text255', + 'credentialPHID' => 'phid?', + ), + self::CONFIG_KEY_SCHEMA => array( + 'key_repository' => array( + 'columns' => array('repositoryPHID'), + ), + ), ) + parent::getConfiguration(); } diff --git a/src/applications/repository/storage/PhabricatorRepositoryPushEvent.php b/src/applications/repository/storage/PhabricatorRepositoryPushEvent.php index b2539a2283..cb8cfe057f 100644 --- a/src/applications/repository/storage/PhabricatorRepositoryPushEvent.php +++ b/src/applications/repository/storage/PhabricatorRepositoryPushEvent.php @@ -28,6 +28,17 @@ final class PhabricatorRepositoryPushEvent return array( self::CONFIG_AUX_PHID => true, self::CONFIG_TIMESTAMPS => false, + self::CONFIG_COLUMN_SCHEMA => array( + 'remoteAddress' => 'uint32?', + 'remoteProtocol' => 'text32?', + 'rejectCode' => 'uint32', + 'rejectDetails' => 'text64?', + ), + self::CONFIG_KEY_SCHEMA => array( + 'key_repository' => array( + 'columns' => array('repositoryPHID'), + ), + ), ) + parent::getConfiguration(); } diff --git a/src/applications/repository/storage/PhabricatorRepositoryPushLog.php b/src/applications/repository/storage/PhabricatorRepositoryPushLog.php index a96f89c498..721003f933 100644 --- a/src/applications/repository/storage/PhabricatorRepositoryPushLog.php +++ b/src/applications/repository/storage/PhabricatorRepositoryPushLog.php @@ -71,6 +71,33 @@ final class PhabricatorRepositoryPushLog self::CONFIG_BINARY => array( 'refNameRaw' => true, ), + self::CONFIG_COLUMN_SCHEMA => array( + 'refType' => 'text12', + 'refNameHash' => 'bytes12?', + 'refNameRaw' => 'bytes?', + 'refNameEncoding' => 'text16?', + 'refOld' => 'text40?', + 'refNew' => 'text40', + 'mergeBase' => 'text40?', + 'changeFlags' => 'uint32', + ), + self::CONFIG_KEY_SCHEMA => array( + 'key_repository' => array( + 'columns' => array('repositoryPHID'), + ), + 'key_ref' => array( + 'columns' => array('repositoryPHID', 'refNew'), + ), + 'key_name' => array( + 'columns' => array('repositoryPHID', 'refNameHash'), + ), + 'key_event' => array( + 'columns' => array('pushEventPHID'), + ), + 'key_pusher' => array( + 'columns' => array('pusherPHID'), + ), + ), ) + parent::getConfiguration(); } diff --git a/src/applications/repository/storage/PhabricatorRepositoryRefCursor.php b/src/applications/repository/storage/PhabricatorRepositoryRefCursor.php index 7cc6eeaa9e..7a9acb9912 100644 --- a/src/applications/repository/storage/PhabricatorRepositoryRefCursor.php +++ b/src/applications/repository/storage/PhabricatorRepositoryRefCursor.php @@ -27,6 +27,17 @@ final class PhabricatorRepositoryRefCursor extends PhabricatorRepositoryDAO self::CONFIG_BINARY => array( 'refNameRaw' => true, ), + self::CONFIG_COLUMN_SCHEMA => array( + 'refType' => 'text32', + 'refNameHash' => 'bytes12', + 'refNameEncoding' => 'text16', + 'commitIdentifier' => 'text40', + ), + self::CONFIG_KEY_SCHEMA => array( + 'key_cursor' => array( + 'columns' => array('repositoryPHID', 'refType', 'refNameHash'), + ), + ), ) + parent::getConfiguration(); } diff --git a/src/applications/repository/storage/PhabricatorRepositorySchemaSpec.php b/src/applications/repository/storage/PhabricatorRepositorySchemaSpec.php new file mode 100644 index 0000000000..92014e738e --- /dev/null +++ b/src/applications/repository/storage/PhabricatorRepositorySchemaSpec.php @@ -0,0 +1,185 @@ +buildLiskSchemata('PhabricatorRepositoryDAO'); + + $this->buildEdgeSchemata(new PhabricatorRepository()); + + $this->buildTransactionSchema( + new PhabricatorRepositoryTransaction()); + + $this->buildRawSchema( + id(new PhabricatorRepository())->getApplicationName(), + PhabricatorRepository::TABLE_BADCOMMIT, + array( + 'fullCommitName' => 'text255', + 'description' => 'text', + ), + array( + 'PRIMARY' => array( + 'columns' => array('fullCommitName'), + 'unique' => true, + ), + )); + + $this->buildRawSchema( + id(new PhabricatorRepository())->getApplicationName(), + PhabricatorRepository::TABLE_COVERAGE, + array( + 'id' => 'id', + 'branchID' => 'id', + 'commitID' => 'id', + 'pathID' => 'id', + 'coverage' => 'bytes', + ), + array( + 'PRIMARY' => array( + 'columns' => array('id'), + 'unique' => true, + ), + 'key_path' => array( + 'columns' => array('branchID', 'pathID', 'commitID'), + ), + )); + + $this->buildRawSchema( + id(new PhabricatorRepository())->getApplicationName(), + PhabricatorRepository::TABLE_FILESYSTEM, + array( + 'repositoryID' => 'id', + 'parentID' => 'id', + 'svnCommit' => 'uint32', + 'pathID' => 'id', + 'existed' => 'bool', + 'fileType' => 'uint32', + ), + array( + 'PRIMARY' => array( + 'columns' => array('repositoryID', 'parentID', 'pathID', 'svnCommit'), + 'unique' => true, + ), + 'repositoryID' => array( + 'columns' => array('repositoryID', 'svnCommit'), + ), + )); + + $this->buildRawSchema( + id(new PhabricatorRepository())->getApplicationName(), + PhabricatorRepository::TABLE_LINTMESSAGE, + array( + 'id' => 'id', + 'branchID' => 'id', + 'path' => 'text', + 'line' => 'uint32', + 'authorPHID' => 'phid?', + 'code' => 'text32', + 'severity' => 'text16', + 'name' => 'text255', + 'description' => 'text', + ), + array( + 'PRIMARY' => array( + 'columns' => array('id'), + 'unique' => true, + ), + 'branchID' => array( + 'columns' => array('branchID', 'path(64)'), + ), + 'branchID_2' => array( + 'columns' => array('branchID', 'code', 'path(64)'), + ), + 'key_author' => array( + 'columns' => array('authorPHID'), + ), + )); + + $this->buildRawSchema( + id(new PhabricatorRepository())->getApplicationName(), + PhabricatorRepository::TABLE_PARENTS, + array( + 'id' => 'id', + 'childCommitID' => 'id', + 'parentCommitID' => 'id', + ), + array( + 'PRIMARY' => array( + 'columns' => array('id'), + 'unique' => true, + ), + 'key_child' => array( + 'columns' => array('childCommitID', 'parentCommitID'), + 'unique' => true, + ), + 'key_parent' => array( + 'columns' => array('parentCommitID'), + ), + )); + + $this->buildRawSchema( + id(new PhabricatorRepository())->getApplicationName(), + PhabricatorRepository::TABLE_PATH, + array( + 'id' => 'id', + 'path' => 'text', + 'pathHash' => 'bytes32', + ), + array( + 'PRIMARY' => array( + 'columns' => array('id'), + 'unique' => true, + ), + 'pathHash' => array( + 'columns' => array('pathHash'), + 'unique' => true, + ), + )); + + $this->buildRawSchema( + id(new PhabricatorRepository())->getApplicationName(), + PhabricatorRepository::TABLE_PATHCHANGE, + array( + 'repositoryID' => 'id', + 'pathID' => 'id', + 'commitID' => 'id', + 'targetPathID' => 'id?', + 'targetCommitID' => 'id?', + 'changeType' => 'uint32', + 'fileType' => 'uint32', + 'isDirect' => 'bool', + 'commitSequence' => 'uint32', + ), + array( + 'PRIMARY' => array( + 'columns' => array('commitID', 'pathID'), + 'unique' => true, + ), + 'repositoryID' => array( + 'columns' => array('repositoryID', 'pathID', 'commitSequence'), + ), + )); + + $this->buildRawSchema( + id(new PhabricatorRepository())->getApplicationName(), + PhabricatorRepository::TABLE_SUMMARY, + array( + 'repositoryID' => 'id', + 'size' => 'uint32', + 'lastCommitID' => 'id', + 'epoch' => 'epoch?', + ), + array( + 'PRIMARY' => array( + 'columns' => array('repositoryID'), + 'unique' => true, + ), + 'key_epoch' => array( + 'columns' => array('epoch'), + ), + )); + + } + +} diff --git a/src/applications/repository/storage/PhabricatorRepositoryStatusMessage.php b/src/applications/repository/storage/PhabricatorRepositoryStatusMessage.php index f35eec1cf2..967aec7911 100644 --- a/src/applications/repository/storage/PhabricatorRepositoryStatusMessage.php +++ b/src/applications/repository/storage/PhabricatorRepositoryStatusMessage.php @@ -23,6 +23,16 @@ final class PhabricatorRepositoryStatusMessage self::CONFIG_SERIALIZATION => array( 'parameters' => self::SERIALIZATION_JSON, ), + self::CONFIG_COLUMN_SCHEMA => array( + 'statusType' => 'text32', + 'statusCode' => 'text32', + ), + self::CONFIG_KEY_SCHEMA => array( + 'repositoryID' => array( + 'columns' => array('repositoryID', 'statusType'), + 'unique' => true, + ), + ), ) + parent::getConfiguration(); } diff --git a/src/applications/repository/storage/PhabricatorRepositorySymbol.php b/src/applications/repository/storage/PhabricatorRepositorySymbol.php index 9adde51cc9..353ff5ba5e 100644 --- a/src/applications/repository/storage/PhabricatorRepositorySymbol.php +++ b/src/applications/repository/storage/PhabricatorRepositorySymbol.php @@ -24,6 +24,20 @@ final class PhabricatorRepositorySymbol extends PhabricatorRepositoryDAO { return array( self::CONFIG_IDS => self::IDS_MANUAL, self::CONFIG_TIMESTAMPS => false, + self::CONFIG_COLUMN_SCHEMA => array( + 'id' => null, + 'symbolContext' => 'text128', + 'symbolName' => 'text128', + 'symbolType' => 'text12', + 'symbolLanguage' => 'text32', + 'lineNumber' => 'uint32', + ), + self::CONFIG_KEY_SCHEMA => array( + 'PRIMARY' => null, + 'symbolName' => array( + 'columns' => array('symbolName'), + ), + ), ) + parent::getConfiguration(); } diff --git a/src/applications/repository/storage/PhabricatorRepositoryVCSPassword.php b/src/applications/repository/storage/PhabricatorRepositoryVCSPassword.php index f3ba350282..cafbfa22ba 100644 --- a/src/applications/repository/storage/PhabricatorRepositoryVCSPassword.php +++ b/src/applications/repository/storage/PhabricatorRepositoryVCSPassword.php @@ -6,6 +6,20 @@ final class PhabricatorRepositoryVCSPassword extends PhabricatorRepositoryDAO { protected $userPHID; protected $passwordHash; + public function getConfiguration() { + return array( + self::CONFIG_COLUMN_SCHEMA => array( + 'passwordHash' => 'text128', + ), + self::CONFIG_KEY_SCHEMA => array( + 'key_phid' => array( + 'columns' => array('userPHID'), + 'unique' => true, + ), + ), + ) + parent::getConfiguration(); + } + public function setPassword( PhutilOpaqueEnvelope $password, PhabricatorUser $user) { From 9be2bf211904deb65b164d678d032a556bb494e9 Mon Sep 17 00:00:00 2001 From: epriestley Date: Sun, 28 Sep 2014 15:12:41 -0700 Subject: [PATCH 21/24] Generate expected schemata for Releeph Summary: Ref T1191. - This drops two tables. - Both tables were migrated to transactions a very long time ago and no longer have readers or writers. Test Plan: Saw ~150 fewer warnings. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T1191 Differential Revision: https://secure.phabricator.com/D10576 --- .../20140926.schema.01.droprelev.sql | 1 + .../20140926.schema.02.droprelreqev.sql | 1 + src/__phutil_library_map__.php | 2 ++ .../releeph/storage/ReleephBranch.php | 20 +++++++++++++++ .../releeph/storage/ReleephProject.php | 11 ++++++++ .../releeph/storage/ReleephRequest.php | 25 +++++++++++++++++++ .../releeph/storage/ReleephSchemaSpec.php | 20 +++++++++++++++ 7 files changed, 80 insertions(+) create mode 100644 resources/sql/autopatches/20140926.schema.01.droprelev.sql create mode 100644 resources/sql/autopatches/20140926.schema.02.droprelreqev.sql create mode 100644 src/applications/releeph/storage/ReleephSchemaSpec.php diff --git a/resources/sql/autopatches/20140926.schema.01.droprelev.sql b/resources/sql/autopatches/20140926.schema.01.droprelev.sql new file mode 100644 index 0000000000..7542e2b209 --- /dev/null +++ b/resources/sql/autopatches/20140926.schema.01.droprelev.sql @@ -0,0 +1 @@ +DROP TABLE {$NAMESPACE}_releeph.releeph_event; diff --git a/resources/sql/autopatches/20140926.schema.02.droprelreqev.sql b/resources/sql/autopatches/20140926.schema.02.droprelreqev.sql new file mode 100644 index 0000000000..de0218ef2d --- /dev/null +++ b/resources/sql/autopatches/20140926.schema.02.droprelreqev.sql @@ -0,0 +1 @@ +DROP TABLE {$NAMESPACE}_releeph.releeph_requestevent; diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index bd49877f45..89f3334e51 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2802,6 +2802,7 @@ phutil_register_library_map(array( 'ReleephRequestViewController' => 'applications/releeph/controller/request/ReleephRequestViewController.php', 'ReleephRequestorFieldSpecification' => 'applications/releeph/field/specification/ReleephRequestorFieldSpecification.php', 'ReleephRevisionFieldSpecification' => 'applications/releeph/field/specification/ReleephRevisionFieldSpecification.php', + 'ReleephSchemaSpec' => 'applications/releeph/storage/ReleephSchemaSpec.php', 'ReleephSeverityFieldSpecification' => 'applications/releeph/field/specification/ReleephSeverityFieldSpecification.php', 'ReleephSummaryFieldSpecification' => 'applications/releeph/field/specification/ReleephSummaryFieldSpecification.php', 'ReleephWorkCanPushConduitAPIMethod' => 'applications/releeph/conduit/work/ReleephWorkCanPushConduitAPIMethod.php', @@ -5894,6 +5895,7 @@ phutil_register_library_map(array( 'ReleephRequestViewController' => 'ReleephBranchController', 'ReleephRequestorFieldSpecification' => 'ReleephFieldSpecification', 'ReleephRevisionFieldSpecification' => 'ReleephFieldSpecification', + 'ReleephSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'ReleephSeverityFieldSpecification' => 'ReleephLevelFieldSpecification', 'ReleephSummaryFieldSpecification' => 'ReleephFieldSpecification', 'ReleephWorkCanPushConduitAPIMethod' => 'ReleephConduitAPIMethod', diff --git a/src/applications/releeph/storage/ReleephBranch.php b/src/applications/releeph/storage/ReleephBranch.php index 647406f1a2..f6cb1834c9 100644 --- a/src/applications/releeph/storage/ReleephBranch.php +++ b/src/applications/releeph/storage/ReleephBranch.php @@ -29,6 +29,26 @@ final class ReleephBranch extends ReleephDAO self::CONFIG_SERIALIZATION => array( 'details' => self::SERIALIZATION_JSON, ), + self::CONFIG_COLUMN_SCHEMA => array( + 'basename' => 'text64', + 'isActive' => 'bool', + 'symbolicName' => 'text64?', + 'name' => 'text128', + ), + self::CONFIG_KEY_SCHEMA => array( + 'releephProjectID' => array( + 'columns' => array('releephProjectID', 'symbolicName'), + 'unique' => true, + ), + 'releephProjectID_2' => array( + 'columns' => array('releephProjectID', 'basename'), + 'unique' => true, + ), + 'releephProjectID_name' => array( + 'columns' => array('releephProjectID', 'name'), + 'unique' => true, + ), + ), ) + parent::getConfiguration(); } diff --git a/src/applications/releeph/storage/ReleephProject.php b/src/applications/releeph/storage/ReleephProject.php index f52b847eb0..0465541c60 100644 --- a/src/applications/releeph/storage/ReleephProject.php +++ b/src/applications/releeph/storage/ReleephProject.php @@ -29,6 +29,17 @@ final class ReleephProject extends ReleephDAO self::CONFIG_SERIALIZATION => array( 'details' => self::SERIALIZATION_JSON, ), + self::CONFIG_COLUMN_SCHEMA => array( + 'name' => 'text255', + 'trunkBranch' => 'text255', + 'isActive' => 'bool', + ), + self::CONFIG_KEY_SCHEMA => array( + 'projectName' => array( + 'columns' => array('name'), + 'unique' => true, + ), + ), ) + parent::getConfiguration(); } diff --git a/src/applications/releeph/storage/ReleephRequest.php b/src/applications/releeph/storage/ReleephRequest.php index 2c495099b6..09cc903d48 100644 --- a/src/applications/releeph/storage/ReleephRequest.php +++ b/src/applications/releeph/storage/ReleephRequest.php @@ -153,6 +153,31 @@ final class ReleephRequest extends ReleephDAO 'details' => self::SERIALIZATION_JSON, 'userIntents' => self::SERIALIZATION_JSON, ), + self::CONFIG_COLUMN_SCHEMA => array( + 'summary' => 'text', + 'requstCommitPHID' => 'phid?', + 'commitIdentifier' => 'text40', + 'pickStatus' => 'uint32', + 'inBranch' => 'bool', + 'mailKey' => 'bytes20', + ), + self::CONFIG_KEY_SCHEMA => array( + 'key_phid' => null, + 'phid' => array( + 'columns' => array('phid'), + 'unique' => true, + ), + 'requestIdentifierBranch' => array( + 'columns' => array('requestCommitPHID', 'branchID'), + 'unique' => true, + ), + 'branchID' => array( + 'columns' => array('branchID'), + ), + 'key_requestedObject' => array( + 'columns' => array('requestedObjectPHID'), + ), + ), ) + parent::getConfiguration(); } diff --git a/src/applications/releeph/storage/ReleephSchemaSpec.php b/src/applications/releeph/storage/ReleephSchemaSpec.php new file mode 100644 index 0000000000..346c4355fc --- /dev/null +++ b/src/applications/releeph/storage/ReleephSchemaSpec.php @@ -0,0 +1,20 @@ +buildLiskSchemata('ReleephDAO'); + + $this->buildTransactionSchema( + new ReleephProductTransaction()); + + $this->buildTransactionSchema( + new ReleephBranchTransaction()); + + $this->buildTransactionSchema( + new ReleephRequestTransaction(), + new ReleephRequestTransactionComment()); + } + +} From 93681fcdbc5c1d1d6739a7ac5c00e8212c509f25 Mon Sep 17 00:00:00 2001 From: epriestley Date: Sun, 28 Sep 2014 15:12:58 -0700 Subject: [PATCH 22/24] Generate expected schemata for Differential Summary: Ref T1191. No major issues here. Test Plan: Saw ~150 fewer issues. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T1191 Differential Revision: https://secure.phabricator.com/D10577 --- .../schema/PhabricatorConfigSchemaSpec.php | 16 ++++- .../storage/DifferentialAffectedPath.php | 12 ++++ .../storage/DifferentialChangeset.php | 16 ++++- .../differential/storage/DifferentialDiff.php | 24 +++++++ .../storage/DifferentialDiffProperty.php | 12 +++- .../storage/DifferentialDraft.php | 14 ++++ .../storage/DifferentialHunkLegacy.php | 17 +++++ .../storage/DifferentialHunkModern.php | 17 +++++ .../storage/DifferentialRevision.php | 27 ++++++++ .../storage/DifferentialSchemaSpec.php | 69 ++++++++++++++++++- .../DifferentialTransactionComment.php | 26 +++++++ 11 files changed, 245 insertions(+), 5 deletions(-) diff --git a/src/applications/config/schema/PhabricatorConfigSchemaSpec.php b/src/applications/config/schema/PhabricatorConfigSchemaSpec.php index d44705f45b..22fbea4117 100644 --- a/src/applications/config/schema/PhabricatorConfigSchemaSpec.php +++ b/src/applications/config/schema/PhabricatorConfigSchemaSpec.php @@ -138,6 +138,10 @@ abstract class PhabricatorConfigSchemaSpec extends Phobject { 'src' => array( 'columns' => array('src', 'type', 'dateCreated', 'seq'), ), + 'key_dst' => array( + 'columns' => array('dst', 'type', 'src'), + 'unique' => true, + ), )); $this->buildRawSchema( @@ -251,16 +255,24 @@ abstract class PhabricatorConfigSchemaSpec extends Phobject { $charset = 'binary'; $collation = 'binary'; break; + case 'bytes20': + $column_type = 'char(20)'; + $charset = 'binary'; + $collation = 'binary'; + break; case 'bytes12': $column_type = 'char(12)'; $charset = 'binary'; $collation = 'binary'; break; - case 'bytes': - $column_type = 'longblob'; + case 'bytes4': + $column_type = 'char(4)'; $charset = 'binary'; $collation = 'binary'; break; + case 'bytes': + $column_type = 'longblob'; + break; case 'text255': $column_type = 'varchar(255)'; $charset = $this->getUTF8Charset(); diff --git a/src/applications/differential/storage/DifferentialAffectedPath.php b/src/applications/differential/storage/DifferentialAffectedPath.php index ac0e9c23ec..35e7ba5d70 100644 --- a/src/applications/differential/storage/DifferentialAffectedPath.php +++ b/src/applications/differential/storage/DifferentialAffectedPath.php @@ -14,6 +14,18 @@ final class DifferentialAffectedPath extends DifferentialDAO { public function getConfiguration() { return array( self::CONFIG_TIMESTAMPS => false, + self::CONFIG_COLUMN_SCHEMA => array( + 'id' => null, + ), + self::CONFIG_KEY_SCHEMA => array( + 'PRIMARY' => null, + 'repositoryID' => array( + 'columns' => array('repositoryID', 'pathID', 'epoch'), + ), + 'revisionID' => array( + 'columns' => array('revisionID'), + ), + ), ) + parent::getConfiguration(); } diff --git a/src/applications/differential/storage/DifferentialChangeset.php b/src/applications/differential/storage/DifferentialChangeset.php index 743bf172b1..5ae22d8a2c 100644 --- a/src/applications/differential/storage/DifferentialChangeset.php +++ b/src/applications/differential/storage/DifferentialChangeset.php @@ -28,7 +28,21 @@ final class DifferentialChangeset extends DifferentialDAO 'oldProperties' => self::SERIALIZATION_JSON, 'newProperties' => self::SERIALIZATION_JSON, 'awayPaths' => self::SERIALIZATION_JSON, - )) + parent::getConfiguration(); + ), + self::CONFIG_COLUMN_SCHEMA => array( + 'oldFile' => 'text255?', + 'filename' => 'text255', + 'changeType' => 'uint32', + 'fileType' => 'uint32', + 'addLines' => 'uint32', + 'delLines' => 'uint32', + ), + self::CONFIG_KEY_SCHEMA => array( + 'diffID' => array( + 'columns' => array('diffID'), + ), + ), + ) + parent::getConfiguration(); } public function getAffectedLineCount() { diff --git a/src/applications/differential/storage/DifferentialDiff.php b/src/applications/differential/storage/DifferentialDiff.php index 863312520d..7828510f80 100644 --- a/src/applications/differential/storage/DifferentialDiff.php +++ b/src/applications/differential/storage/DifferentialDiff.php @@ -42,6 +42,30 @@ final class DifferentialDiff public function getConfiguration() { return array( self::CONFIG_AUX_PHID => true, + self::CONFIG_COLUMN_SCHEMA => array( + 'revisionID' => 'id?', + 'authorPHID' => 'phid?', + 'repositoryPHID' => 'phid?', + 'sourceMachine' => 'text255?', + 'sourcePath' => 'text255?', + 'sourceControlSystem' => 'text64?', + 'sourceControlBaseRevision' => 'text255?', + 'sourceControlPath' => 'text255?', + 'lintStatus' => 'uint32', + 'unitStatus' => 'uint32', + 'lineCount' => 'uint32', + 'branch' => 'text255?', + 'bookmark' => 'text255?', + 'arcanistProjectPHID' => 'phid?', + 'creationMethod' => 'text255', + 'description' => 'text255', + 'repositoryUUID' => 'text64?', + ), + self::CONFIG_KEY_SCHEMA => array( + 'revisionID' => array( + 'columns' => array('revisionID'), + ), + ), ) + parent::getConfiguration(); } diff --git a/src/applications/differential/storage/DifferentialDiffProperty.php b/src/applications/differential/storage/DifferentialDiffProperty.php index 11be887eb4..a7286bfec1 100644 --- a/src/applications/differential/storage/DifferentialDiffProperty.php +++ b/src/applications/differential/storage/DifferentialDiffProperty.php @@ -10,7 +10,17 @@ final class DifferentialDiffProperty extends DifferentialDAO { return array( self::CONFIG_SERIALIZATION => array( 'data' => self::SERIALIZATION_JSON, - )) + parent::getConfiguration(); + ), + self::CONFIG_COLUMN_SCHEMA => array( + 'name' => 'text255', + ), + self::CONFIG_KEY_SCHEMA => array( + 'diffID' => array( + 'columns' => array('diffID', 'name'), + 'unique' => true, + ), + ), + ) + parent::getConfiguration(); } } diff --git a/src/applications/differential/storage/DifferentialDraft.php b/src/applications/differential/storage/DifferentialDraft.php index 6ad406d3f0..8ea12f73e0 100644 --- a/src/applications/differential/storage/DifferentialDraft.php +++ b/src/applications/differential/storage/DifferentialDraft.php @@ -6,6 +6,20 @@ final class DifferentialDraft extends DifferentialDAO { protected $authorPHID; protected $draftKey; + public function getConfiguration() { + return array( + self::CONFIG_COLUMN_SCHEMA => array( + 'draftKey' => 'text64', + ), + self::CONFIG_KEY_SCHEMA => array( + 'key_unique' => array( + 'columns' => array('objectPHID', 'authorPHID', 'draftKey'), + 'unique' => true, + ), + ), + ) + parent::getConfiguration(); + } + public static function markHasDraft( $author_phid, $object_phid, diff --git a/src/applications/differential/storage/DifferentialHunkLegacy.php b/src/applications/differential/storage/DifferentialHunkLegacy.php index 7eedd770c1..c64a4f1c9d 100644 --- a/src/applications/differential/storage/DifferentialHunkLegacy.php +++ b/src/applications/differential/storage/DifferentialHunkLegacy.php @@ -4,6 +4,23 @@ final class DifferentialHunkLegacy extends DifferentialHunk { protected $changes; + public function getConfiguration() { + return array( + self::CONFIG_COLUMN_SCHEMA => array( + 'changes' => 'text?', + 'oldOffset' => 'uint32', + 'oldLen' => 'uint32', + 'newOffset' => 'uint32', + 'newLen' => 'uint32', + ), + self::CONFIG_KEY_SCHEMA => array( + 'changesetID' => array( + 'columns' => array('changesetID'), + ), + ), + ) + parent::getConfiguration(); + } + public function getTableName() { return 'differential_hunk'; } diff --git a/src/applications/differential/storage/DifferentialHunkModern.php b/src/applications/differential/storage/DifferentialHunkModern.php index eae36a6f7f..0279dd5f78 100644 --- a/src/applications/differential/storage/DifferentialHunkModern.php +++ b/src/applications/differential/storage/DifferentialHunkModern.php @@ -25,6 +25,23 @@ final class DifferentialHunkModern extends DifferentialHunk { self::CONFIG_BINARY => array( 'data' => true, ), + self::CONFIG_COLUMN_SCHEMA => array( + 'dataType' => 'bytes4', + 'dataEncoding' => 'text16?', + 'dataFormat' => 'bytes4', + 'oldOffset' => 'uint32', + 'oldLen' => 'uint32', + 'newOffset' => 'uint32', + 'newLen' => 'uint32', + ), + self::CONFIG_KEY_SCHEMA => array( + 'key_changeset' => array( + 'columns' => array('changesetID'), + ), + 'key_created' => array( + 'columns' => array('dateCreated'), + ), + ), ) + parent::getConfiguration(); } diff --git a/src/applications/differential/storage/DifferentialRevision.php b/src/applications/differential/storage/DifferentialRevision.php index 428536a0e1..c8b3fa17af 100644 --- a/src/applications/differential/storage/DifferentialRevision.php +++ b/src/applications/differential/storage/DifferentialRevision.php @@ -74,6 +74,33 @@ final class DifferentialRevision extends DifferentialDAO 'attached' => self::SERIALIZATION_JSON, 'unsubscribed' => self::SERIALIZATION_JSON, ), + self::CONFIG_COLUMN_SCHEMA => array( + 'title' => 'text255', + 'originalTitle' => 'text255', + 'status' => 'text32', + 'summary' => 'text', + 'testPlan' => 'text', + 'authorPHID' => 'phid?', + 'lastReviewerPHID' => 'phid?', + 'lineCount' => 'uint32?', + 'mailKey' => 'bytes40', + 'branchName' => 'text255', + 'arcanistProjectPHID' => 'phid?', + 'repositoryPHID' => 'phid?', + ), + self::CONFIG_KEY_SCHEMA => array( + 'key_phid' => null, + 'phid' => array( + 'columns' => array('phid'), + 'unique' => true, + ), + 'authorPHID' => array( + 'columns' => array('authorPHID', 'status'), + ), + 'repositoryPHID' => array( + 'columns' => array('repositoryPHID'), + ), + ), ) + parent::getConfiguration(); } diff --git a/src/applications/differential/storage/DifferentialSchemaSpec.php b/src/applications/differential/storage/DifferentialSchemaSpec.php index e568da0a45..fc75096381 100644 --- a/src/applications/differential/storage/DifferentialSchemaSpec.php +++ b/src/applications/differential/storage/DifferentialSchemaSpec.php @@ -4,7 +4,74 @@ final class DifferentialSchemaSpec extends PhabricatorConfigSchemaSpec { public function buildSchemata() { $this->buildLiskSchemata('DifferentialDAO'); -// $this->addEdgeSchemata($server, new DifferentialRevision()); + + $this->buildEdgeSchemata(new DifferentialRevision()); + + $this->buildTransactionSchema( + new DifferentialTransaction(), + new DifferentialTransactionComment()); + + $this->buildCustomFieldSchemata( + new DifferentialCustomFieldStorage(), + array( + new DifferentialCustomFieldNumericIndex(), + new DifferentialCustomFieldStringIndex(), + )); + + $this->buildRawSchema( + id(new DifferentialRevision())->getApplicationName(), + DifferentialChangeset::TABLE_CACHE, + array( + 'id' => 'id', + 'cache' => 'bytes', + 'dateCreated' => 'epoch', + ), + array( + 'PRIMARY' => array( + 'columns' => array('id'), + 'unique' => true, + ), + 'dateCreated' => array( + 'columns' => array('dateCreated'), + ), + )); + + $this->buildRawSchema( + id(new DifferentialRevision())->getApplicationName(), + DifferentialRevision::TABLE_COMMIT, + array( + 'revisionID' => 'id', + 'commitPHID' => 'phid', + ), + array( + 'PRIMARY' => array( + 'columns' => array('revisionID', 'commitPHID'), + 'unique' => true, + ), + 'commitPHID' => array( + 'columns' => array('commitPHID'), + 'unique' => true, + ), + )); + + $this->buildRawSchema( + id(new DifferentialRevision())->getApplicationName(), + ArcanistDifferentialRevisionHash::TABLE_NAME, + array( + 'revisionID' => 'id', + 'type' => 'bytes4', + 'hash' => 'bytes40', + ), + array( + 'type' => array( + 'columns' => array('type', 'hash'), + ), + 'revisionID' => array( + 'columns' => array('revisionID'), + ), + )); + + } } diff --git a/src/applications/differential/storage/DifferentialTransactionComment.php b/src/applications/differential/storage/DifferentialTransactionComment.php index 90086618ec..d8835e3b1a 100644 --- a/src/applications/differential/storage/DifferentialTransactionComment.php +++ b/src/applications/differential/storage/DifferentialTransactionComment.php @@ -16,6 +16,32 @@ final class DifferentialTransactionComment return new DifferentialTransaction(); } + public function getConfiguration() { + $config = parent::getConfiguration(); + $config[self::CONFIG_COLUMN_SCHEMA] = array( + 'revisionPHID' => 'phid?', + 'changesetID' => 'id?', + 'isNewFile' => 'bool', + 'lineNumber' => 'uint32', + 'lineLength' => 'uint32', + 'fixedState' => 'text12?', + 'hasReplies' => 'bool', + 'replyToCommentPHID' => 'phid?', + ) + $config[self::CONFIG_COLUMN_SCHEMA]; + $config[self::CONFIG_KEY_SCHEMA] = array( + 'key_draft' => array( + 'columns' => array('authorPHID', 'transactionPHID'), + ), + 'key_changeset' => array( + 'columns' => array('changesetID'), + ), + 'key_revision' => array( + 'columns' => array('revisionPHID'), + ), + ) + $config[self::CONFIG_KEY_SCHEMA]; + return $config; + } + public function shouldUseMarkupCache($field) { // Only cache submitted comments. return ($this->getTransactionPHID() != null); From 644ca4c3a3e704ba1d38ada628366ce90bcd75af Mon Sep 17 00:00:00 2001 From: epriestley Date: Mon, 29 Sep 2014 08:10:48 -0700 Subject: [PATCH 23/24] Use --single-transaction in `bin/storage dump` Summary: See . From reading documentation, this seems dramatically better for InnoDB tables than the default behavior. Test Plan: Ran `bin/storage dump`, got a reasonable-looking dump. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Differential Revision: https://secure.phabricator.com/D10606 --- .../workflow/PhabricatorStorageManagementDumpWorkflow.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDumpWorkflow.php b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDumpWorkflow.php index fa47ca2133..4e01446929 100644 --- a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDumpWorkflow.php +++ b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDumpWorkflow.php @@ -43,10 +43,8 @@ final class PhabricatorStorageManagementDumpWorkflow : ''; return phutil_passthru( - - 'mysqldump --default-character-set=utf8 '. + 'mysqldump --single-transaction --default-character-set=utf8 '. '-u %s %C -h %s %C --databases %Ls', - $api->getUser(), $flag_password, $host, From 855f752814eb7ef05960d2ca3178909a0814b2d4 Mon Sep 17 00:00:00 2001 From: epriestley Date: Mon, 29 Sep 2014 08:31:00 -0700 Subject: [PATCH 24/24] Support `:emoji:` in Remarkup Summary: Ref T1191. This actually works without T1191, but makes emoji use on the desktop easier. Test Plan: {F210416} Reviewers: chad, btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T1191 Differential Revision: https://secure.phabricator.com/D10605 --- src/__phutil_library_map__.php | 2 + .../PhabricatorMacroApplication.php | 1 + .../markup/PhabricatorEmojiRemarkupRule.php | 903 ++++++++++++++++++ 3 files changed, 906 insertions(+) create mode 100644 src/applications/macro/markup/PhabricatorEmojiRemarkupRule.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 89f3334e51..74f9e21459 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1539,6 +1539,7 @@ phutil_register_library_map(array( 'PhabricatorEmailLoginController' => 'applications/auth/controller/PhabricatorEmailLoginController.php', 'PhabricatorEmailVerificationController' => 'applications/auth/controller/PhabricatorEmailVerificationController.php', 'PhabricatorEmbedFileRemarkupRule' => 'applications/files/markup/PhabricatorEmbedFileRemarkupRule.php', + 'PhabricatorEmojiRemarkupRule' => 'applications/macro/markup/PhabricatorEmojiRemarkupRule.php', 'PhabricatorEmptyQueryException' => 'infrastructure/query/PhabricatorEmptyQueryException.php', 'PhabricatorEnglishTranslation' => 'infrastructure/internationalization/translation/PhabricatorEnglishTranslation.php', 'PhabricatorEnv' => 'infrastructure/env/PhabricatorEnv.php', @@ -4482,6 +4483,7 @@ phutil_register_library_map(array( 'PhabricatorEmailLoginController' => 'PhabricatorAuthController', 'PhabricatorEmailVerificationController' => 'PhabricatorAuthController', 'PhabricatorEmbedFileRemarkupRule' => 'PhabricatorObjectRemarkupRule', + 'PhabricatorEmojiRemarkupRule' => 'PhutilRemarkupRule', 'PhabricatorEmptyQueryException' => 'Exception', 'PhabricatorEnglishTranslation' => 'PhabricatorBaseEnglishTranslation', 'PhabricatorEnvTestCase' => 'PhabricatorTestCase', diff --git a/src/applications/macro/application/PhabricatorMacroApplication.php b/src/applications/macro/application/PhabricatorMacroApplication.php index 51b1152ba6..384d9fa951 100644 --- a/src/applications/macro/application/PhabricatorMacroApplication.php +++ b/src/applications/macro/application/PhabricatorMacroApplication.php @@ -45,6 +45,7 @@ final class PhabricatorMacroApplication extends PhabricatorApplication { public function getRemarkupRules() { return array( new PhabricatorIconRemarkupRule(), + new PhabricatorEmojiRemarkupRule(), ); } diff --git a/src/applications/macro/markup/PhabricatorEmojiRemarkupRule.php b/src/applications/macro/markup/PhabricatorEmojiRemarkupRule.php new file mode 100644 index 0000000000..b1e24c23ff --- /dev/null +++ b/src/applications/macro/markup/PhabricatorEmojiRemarkupRule.php @@ -0,0 +1,903 @@ +isFlatText($matches[0])) { + return $matches[0]; + } + + static $map = array( + 'watch' => "\xE2\x8C\x9A", + 'hourglass' => "\xE2\x8C\x9B", + 'fast_forward' => "\xE2\x8F\xA9", + 'rewind' => "\xE2\x8F\xAA", + 'arrow_double_up' => "\xE2\x8F\xAB", + 'arrow_double_down' => "\xE2\x8F\xAC", + 'alarm_clock' => "\xE2\x8F\xB0", + 'hourglass_flowing_sand' => "\xE2\x8F\xB3", + 'white_medium_small_square' => "\xE2\x97\xBD", + 'black_medium_small_square' => "\xE2\x97\xBE", + 'umbrella' => "\xE2\x98\x94", + 'coffee' => "\xE2\x98\x95", + 'aries' => "\xE2\x99\x88", + 'taurus' => "\xE2\x99\x89", + 'gemini' => "\xE2\x99\x8A", + 'cancer' => "\xE2\x99\x8B", + 'leo' => "\xE2\x99\x8C", + 'virgo' => "\xE2\x99\x8D", + 'libra' => "\xE2\x99\x8E", + 'scorpius' => "\xE2\x99\x8F", + 'sagittarius' => "\xE2\x99\x90", + 'capricorn' => "\xE2\x99\x91", + 'aquarius' => "\xE2\x99\x92", + 'pisces' => "\xE2\x99\x93", + 'wheelchair' => "\xE2\x99\xBF", + 'anchor' => "\xE2\x9A\x93", + 'zap' => "\xE2\x9A\xA1", + 'white_circle' => "\xE2\x9A\xAA", + 'black_circle' => "\xE2\x9A\xAB", + 'soccer' => "\xE2\x9A\xBD", + 'snowman' => "\xE2\x9B\x84", + 'partly_sunny' => "\xE2\x9B\x85", + 'ophiuchus' => "\xE2\x9B\x8E", + 'no_entry' => "\xE2\x9B\x94", + 'church' => "\xE2\x9B\xAA", + 'fountain' => "\xE2\x9B\xB2", + 'golf' => "\xE2\x9B\xB3", + 'sailboat' => "\xE2\x9B\xB5", + 'boat' => "\xE2\x9B\xB5", + 'tent' => "\xE2\x9B\xBA", + 'fuelpump' => "\xE2\x9B\xBD", + 'white_check_mark' => "\xE2\x9C\x85", + 'fist' => "\xE2\x9C\x8A", + 'hand' => "\xE2\x9C\x8B", + 'raised_hand' => "\xE2\x9C\x8B", + 'sparkles' => "\xE2\x9C\xA8", + 'x' => "\xE2\x9D\x8C", + 'negative_squared_cross_mark' => "\xE2\x9D\x8E", + 'question' => "\xE2\x9D\x93", + 'grey_question' => "\xE2\x9D\x94", + 'grey_exclamation' => "\xE2\x9D\x95", + 'exclamation' => "\xE2\x9D\x97", + 'heavy_exclamation_mark' => "\xE2\x9D\x97", + 'heavy_plus_sign' => "\xE2\x9E\x95", + 'heavy_minus_sign' => "\xE2\x9E\x96", + 'heavy_division_sign' => "\xE2\x9E\x97", + 'curly_loop' => "\xE2\x9E\xB0", + 'loop' => "\xE2\x9E\xBF", + 'black_large_square' => "\xE2\xAC\x9B", + 'white_large_square' => "\xE2\xAC\x9C", + 'star' => "\xE2\xAD\x90", + 'o' => "\xE2\xAD\x95", + 'mahjong' => "\xF0\x9F\x80\x84", + 'black_joker' => "\xF0\x9F\x83\x8F", + 'ab' => "\xF0\x9F\x86\x8E", + 'cl' => "\xF0\x9F\x86\x91", + 'cool' => "\xF0\x9F\x86\x92", + 'free' => "\xF0\x9F\x86\x93", + 'id' => "\xF0\x9F\x86\x94", + 'new' => "\xF0\x9F\x86\x95", + 'ng' => "\xF0\x9F\x86\x96", + 'ok' => "\xF0\x9F\x86\x97", + 'sos' => "\xF0\x9F\x86\x98", + 'up' => "\xF0\x9F\x86\x99", + 'vs' => "\xF0\x9F\x86\x9A", + 'koko' => "\xF0\x9F\x88\x81", + 'u7121' => "\xF0\x9F\x88\x9A", + 'u6307' => "\xF0\x9F\x88\xAF", + 'u7981' => "\xF0\x9F\x88\xB2", + 'u7a7a' => "\xF0\x9F\x88\xB3", + 'u5408' => "\xF0\x9F\x88\xB4", + 'u6e80' => "\xF0\x9F\x88\xB5", + 'u6709' => "\xF0\x9F\x88\xB6", + 'u7533' => "\xF0\x9F\x88\xB8", + 'u5272' => "\xF0\x9F\x88\xB9", + 'u55b6' => "\xF0\x9F\x88\xBA", + 'ideograph_advantage' => "\xF0\x9F\x89\x90", + 'accept' => "\xF0\x9F\x89\x91", + 'cyclone' => "\xF0\x9F\x8C\x80", + 'foggy' => "\xF0\x9F\x8C\x81", + 'closed_umbrella' => "\xF0\x9F\x8C\x82", + 'night_with_stars' => "\xF0\x9F\x8C\x83", + 'sunrise_over_mountains' => "\xF0\x9F\x8C\x84", + 'sunrise' => "\xF0\x9F\x8C\x85", + 'city_sunset' => "\xF0\x9F\x8C\x86", + 'city_sunrise' => "\xF0\x9F\x8C\x87", + 'rainbow' => "\xF0\x9F\x8C\x88", + 'bridge_at_night' => "\xF0\x9F\x8C\x89", + 'ocean' => "\xF0\x9F\x8C\x8A", + 'volcano' => "\xF0\x9F\x8C\x8B", + 'milky_way' => "\xF0\x9F\x8C\x8C", + 'earth_africa' => "\xF0\x9F\x8C\x8D", + 'earth_americas' => "\xF0\x9F\x8C\x8E", + 'earth_asia' => "\xF0\x9F\x8C\x8F", + 'globe_with_meridians' => "\xF0\x9F\x8C\x90", + 'new_moon' => "\xF0\x9F\x8C\x91", + 'waxing_crescent_moon' => "\xF0\x9F\x8C\x92", + 'first_quarter_moon' => "\xF0\x9F\x8C\x93", + 'waxing_gibbous_moon' => "\xF0\x9F\x8C\x94", + 'moon' => "\xF0\x9F\x8C\x94", + 'full_moon' => "\xF0\x9F\x8C\x95", + 'waning_gibbous_moon' => "\xF0\x9F\x8C\x96", + 'last_quarter_moon' => "\xF0\x9F\x8C\x97", + 'waning_crescent_moon' => "\xF0\x9F\x8C\x98", + 'crescent_moon' => "\xF0\x9F\x8C\x99", + 'new_moon_with_face' => "\xF0\x9F\x8C\x9A", + 'first_quarter_moon_with_face' => "\xF0\x9F\x8C\x9B", + 'last_quarter_moon_with_face' => "\xF0\x9F\x8C\x9C", + 'full_moon_with_face' => "\xF0\x9F\x8C\x9D", + 'sun_with_face' => "\xF0\x9F\x8C\x9E", + 'star2' => "\xF0\x9F\x8C\x9F", + 'stars' => "\xF0\x9F\x8C\xA0", + 'chestnut' => "\xF0\x9F\x8C\xB0", + 'seedling' => "\xF0\x9F\x8C\xB1", + 'evergreen_tree' => "\xF0\x9F\x8C\xB2", + 'deciduous_tree' => "\xF0\x9F\x8C\xB3", + 'palm_tree' => "\xF0\x9F\x8C\xB4", + 'cactus' => "\xF0\x9F\x8C\xB5", + 'tulip' => "\xF0\x9F\x8C\xB7", + 'cherry_blossom' => "\xF0\x9F\x8C\xB8", + 'rose' => "\xF0\x9F\x8C\xB9", + 'hibiscus' => "\xF0\x9F\x8C\xBA", + 'sunflower' => "\xF0\x9F\x8C\xBB", + 'blossom' => "\xF0\x9F\x8C\xBC", + 'corn' => "\xF0\x9F\x8C\xBD", + 'ear_of_rice' => "\xF0\x9F\x8C\xBE", + 'herb' => "\xF0\x9F\x8C\xBF", + 'four_leaf_clover' => "\xF0\x9F\x8D\x80", + 'maple_leaf' => "\xF0\x9F\x8D\x81", + 'fallen_leaf' => "\xF0\x9F\x8D\x82", + 'leaves' => "\xF0\x9F\x8D\x83", + 'mushroom' => "\xF0\x9F\x8D\x84", + 'tomato' => "\xF0\x9F\x8D\x85", + 'eggplant' => "\xF0\x9F\x8D\x86", + 'grapes' => "\xF0\x9F\x8D\x87", + 'melon' => "\xF0\x9F\x8D\x88", + 'watermelon' => "\xF0\x9F\x8D\x89", + 'tangerine' => "\xF0\x9F\x8D\x8A", + 'lemon' => "\xF0\x9F\x8D\x8B", + 'banana' => "\xF0\x9F\x8D\x8C", + 'pineapple' => "\xF0\x9F\x8D\x8D", + 'apple' => "\xF0\x9F\x8D\x8E", + 'green_apple' => "\xF0\x9F\x8D\x8F", + 'pear' => "\xF0\x9F\x8D\x90", + 'peach' => "\xF0\x9F\x8D\x91", + 'cherries' => "\xF0\x9F\x8D\x92", + 'strawberry' => "\xF0\x9F\x8D\x93", + 'hamburger' => "\xF0\x9F\x8D\x94", + 'pizza' => "\xF0\x9F\x8D\x95", + 'meat_on_bone' => "\xF0\x9F\x8D\x96", + 'poultry_leg' => "\xF0\x9F\x8D\x97", + 'rice_cracker' => "\xF0\x9F\x8D\x98", + 'rice_ball' => "\xF0\x9F\x8D\x99", + 'rice' => "\xF0\x9F\x8D\x9A", + 'curry' => "\xF0\x9F\x8D\x9B", + 'ramen' => "\xF0\x9F\x8D\x9C", + 'spaghetti' => "\xF0\x9F\x8D\x9D", + 'bread' => "\xF0\x9F\x8D\x9E", + 'fries' => "\xF0\x9F\x8D\x9F", + 'sweet_potato' => "\xF0\x9F\x8D\xA0", + 'dango' => "\xF0\x9F\x8D\xA1", + 'oden' => "\xF0\x9F\x8D\xA2", + 'sushi' => "\xF0\x9F\x8D\xA3", + 'fried_shrimp' => "\xF0\x9F\x8D\xA4", + 'fish_cake' => "\xF0\x9F\x8D\xA5", + 'icecream' => "\xF0\x9F\x8D\xA6", + 'shaved_ice' => "\xF0\x9F\x8D\xA7", + 'ice_cream' => "\xF0\x9F\x8D\xA8", + 'doughnut' => "\xF0\x9F\x8D\xA9", + 'cookie' => "\xF0\x9F\x8D\xAA", + 'chocolate_bar' => "\xF0\x9F\x8D\xAB", + 'candy' => "\xF0\x9F\x8D\xAC", + 'lollipop' => "\xF0\x9F\x8D\xAD", + 'custard' => "\xF0\x9F\x8D\xAE", + 'honey_pot' => "\xF0\x9F\x8D\xAF", + 'cake' => "\xF0\x9F\x8D\xB0", + 'bento' => "\xF0\x9F\x8D\xB1", + 'stew' => "\xF0\x9F\x8D\xB2", + 'egg' => "\xF0\x9F\x8D\xB3", + 'fork_and_knife' => "\xF0\x9F\x8D\xB4", + 'tea' => "\xF0\x9F\x8D\xB5", + 'sake' => "\xF0\x9F\x8D\xB6", + 'wine_glass' => "\xF0\x9F\x8D\xB7", + 'cocktail' => "\xF0\x9F\x8D\xB8", + 'tropical_drink' => "\xF0\x9F\x8D\xB9", + 'beer' => "\xF0\x9F\x8D\xBA", + 'beers' => "\xF0\x9F\x8D\xBB", + 'baby_bottle' => "\xF0\x9F\x8D\xBC", + 'ribbon' => "\xF0\x9F\x8E\x80", + 'gift' => "\xF0\x9F\x8E\x81", + 'birthday' => "\xF0\x9F\x8E\x82", + 'jack_o_lantern' => "\xF0\x9F\x8E\x83", + 'christmas_tree' => "\xF0\x9F\x8E\x84", + 'santa' => "\xF0\x9F\x8E\x85", + 'fireworks' => "\xF0\x9F\x8E\x86", + 'sparkler' => "\xF0\x9F\x8E\x87", + 'balloon' => "\xF0\x9F\x8E\x88", + 'tada' => "\xF0\x9F\x8E\x89", + 'confetti_ball' => "\xF0\x9F\x8E\x8A", + 'tanabata_tree' => "\xF0\x9F\x8E\x8B", + 'crossed_flags' => "\xF0\x9F\x8E\x8C", + 'bamboo' => "\xF0\x9F\x8E\x8D", + 'dolls' => "\xF0\x9F\x8E\x8E", + 'flags' => "\xF0\x9F\x8E\x8F", + 'wind_chime' => "\xF0\x9F\x8E\x90", + 'rice_scene' => "\xF0\x9F\x8E\x91", + 'school_satchel' => "\xF0\x9F\x8E\x92", + 'mortar_board' => "\xF0\x9F\x8E\x93", + 'carousel_horse' => "\xF0\x9F\x8E\xA0", + 'ferris_wheel' => "\xF0\x9F\x8E\xA1", + 'roller_coaster' => "\xF0\x9F\x8E\xA2", + 'fishing_pole_and_fish' => "\xF0\x9F\x8E\xA3", + 'microphone' => "\xF0\x9F\x8E\xA4", + 'movie_camera' => "\xF0\x9F\x8E\xA5", + 'cinema' => "\xF0\x9F\x8E\xA6", + 'headphones' => "\xF0\x9F\x8E\xA7", + 'art' => "\xF0\x9F\x8E\xA8", + 'tophat' => "\xF0\x9F\x8E\xA9", + 'circus_tent' => "\xF0\x9F\x8E\xAA", + 'ticket' => "\xF0\x9F\x8E\xAB", + 'clapper' => "\xF0\x9F\x8E\xAC", + 'performing_arts' => "\xF0\x9F\x8E\xAD", + 'video_game' => "\xF0\x9F\x8E\xAE", + 'dart' => "\xF0\x9F\x8E\xAF", + 'slot_machine' => "\xF0\x9F\x8E\xB0", + '8ball' => "\xF0\x9F\x8E\xB1", + 'game_die' => "\xF0\x9F\x8E\xB2", + 'bowling' => "\xF0\x9F\x8E\xB3", + 'flower_playing_cards' => "\xF0\x9F\x8E\xB4", + 'musical_note' => "\xF0\x9F\x8E\xB5", + 'notes' => "\xF0\x9F\x8E\xB6", + 'saxophone' => "\xF0\x9F\x8E\xB7", + 'guitar' => "\xF0\x9F\x8E\xB8", + 'musical_keyboard' => "\xF0\x9F\x8E\xB9", + 'trumpet' => "\xF0\x9F\x8E\xBA", + 'violin' => "\xF0\x9F\x8E\xBB", + 'musical_score' => "\xF0\x9F\x8E\xBC", + 'running_shirt_with_sash' => "\xF0\x9F\x8E\xBD", + 'tennis' => "\xF0\x9F\x8E\xBE", + 'ski' => "\xF0\x9F\x8E\xBF", + 'basketball' => "\xF0\x9F\x8F\x80", + 'checkered_flag' => "\xF0\x9F\x8F\x81", + 'snowboarder' => "\xF0\x9F\x8F\x82", + 'runner' => "\xF0\x9F\x8F\x83", + 'running' => "\xF0\x9F\x8F\x83", + 'surfer' => "\xF0\x9F\x8F\x84", + 'trophy' => "\xF0\x9F\x8F\x86", + 'horse_racing' => "\xF0\x9F\x8F\x87", + 'football' => "\xF0\x9F\x8F\x88", + 'rugby_football' => "\xF0\x9F\x8F\x89", + 'swimmer' => "\xF0\x9F\x8F\x8A", + 'house' => "\xF0\x9F\x8F\xA0", + 'house_with_garden' => "\xF0\x9F\x8F\xA1", + 'office' => "\xF0\x9F\x8F\xA2", + 'post_office' => "\xF0\x9F\x8F\xA3", + 'european_post_office' => "\xF0\x9F\x8F\xA4", + 'hospital' => "\xF0\x9F\x8F\xA5", + 'bank' => "\xF0\x9F\x8F\xA6", + 'atm' => "\xF0\x9F\x8F\xA7", + 'hotel' => "\xF0\x9F\x8F\xA8", + 'love_hotel' => "\xF0\x9F\x8F\xA9", + 'convenience_store' => "\xF0\x9F\x8F\xAA", + 'school' => "\xF0\x9F\x8F\xAB", + 'department_store' => "\xF0\x9F\x8F\xAC", + 'factory' => "\xF0\x9F\x8F\xAD", + 'lantern' => "\xF0\x9F\x8F\xAE", + 'izakaya_lantern' => "\xF0\x9F\x8F\xAE", + 'japanese_castle' => "\xF0\x9F\x8F\xAF", + 'european_castle' => "\xF0\x9F\x8F\xB0", + 'rat' => "\xF0\x9F\x90\x80", + 'mouse2' => "\xF0\x9F\x90\x81", + 'ox' => "\xF0\x9F\x90\x82", + 'water_buffalo' => "\xF0\x9F\x90\x83", + 'cow2' => "\xF0\x9F\x90\x84", + 'tiger2' => "\xF0\x9F\x90\x85", + 'leopard' => "\xF0\x9F\x90\x86", + 'rabbit2' => "\xF0\x9F\x90\x87", + 'cat2' => "\xF0\x9F\x90\x88", + 'dragon' => "\xF0\x9F\x90\x89", + 'crocodile' => "\xF0\x9F\x90\x8A", + 'whale2' => "\xF0\x9F\x90\x8B", + 'snail' => "\xF0\x9F\x90\x8C", + 'snake' => "\xF0\x9F\x90\x8D", + 'racehorse' => "\xF0\x9F\x90\x8E", + 'ram' => "\xF0\x9F\x90\x8F", + 'goat' => "\xF0\x9F\x90\x90", + 'sheep' => "\xF0\x9F\x90\x91", + 'monkey' => "\xF0\x9F\x90\x92", + 'rooster' => "\xF0\x9F\x90\x93", + 'chicken' => "\xF0\x9F\x90\x94", + 'dog2' => "\xF0\x9F\x90\x95", + 'pig2' => "\xF0\x9F\x90\x96", + 'boar' => "\xF0\x9F\x90\x97", + 'elephant' => "\xF0\x9F\x90\x98", + 'octopus' => "\xF0\x9F\x90\x99", + 'shell' => "\xF0\x9F\x90\x9A", + 'bug' => "\xF0\x9F\x90\x9B", + 'ant' => "\xF0\x9F\x90\x9C", + 'bee' => "\xF0\x9F\x90\x9D", + 'honeybee' => "\xF0\x9F\x90\x9D", + 'beetle' => "\xF0\x9F\x90\x9E", + 'fish' => "\xF0\x9F\x90\x9F", + 'tropical_fish' => "\xF0\x9F\x90\xA0", + 'blowfish' => "\xF0\x9F\x90\xA1", + 'turtle' => "\xF0\x9F\x90\xA2", + 'hatching_chick' => "\xF0\x9F\x90\xA3", + 'baby_chick' => "\xF0\x9F\x90\xA4", + 'hatched_chick' => "\xF0\x9F\x90\xA5", + 'bird' => "\xF0\x9F\x90\xA6", + 'penguin' => "\xF0\x9F\x90\xA7", + 'koala' => "\xF0\x9F\x90\xA8", + 'poodle' => "\xF0\x9F\x90\xA9", + 'dromedary_camel' => "\xF0\x9F\x90\xAA", + 'camel' => "\xF0\x9F\x90\xAB", + 'dolphin' => "\xF0\x9F\x90\xAC", + 'flipper' => "\xF0\x9F\x90\xAC", + 'mouse' => "\xF0\x9F\x90\xAD", + 'cow' => "\xF0\x9F\x90\xAE", + 'tiger' => "\xF0\x9F\x90\xAF", + 'rabbit' => "\xF0\x9F\x90\xB0", + 'cat' => "\xF0\x9F\x90\xB1", + 'dragon_face' => "\xF0\x9F\x90\xB2", + 'whale' => "\xF0\x9F\x90\xB3", + 'horse' => "\xF0\x9F\x90\xB4", + 'monkey_face' => "\xF0\x9F\x90\xB5", + 'dog' => "\xF0\x9F\x90\xB6", + 'pig' => "\xF0\x9F\x90\xB7", + 'frog' => "\xF0\x9F\x90\xB8", + 'hamster' => "\xF0\x9F\x90\xB9", + 'wolf' => "\xF0\x9F\x90\xBA", + 'bear' => "\xF0\x9F\x90\xBB", + 'panda_face' => "\xF0\x9F\x90\xBC", + 'pig_nose' => "\xF0\x9F\x90\xBD", + 'paw_prints' => "\xF0\x9F\x90\xBE", + 'feet' => "\xF0\x9F\x90\xBE", + 'eyes' => "\xF0\x9F\x91\x80", + 'ear' => "\xF0\x9F\x91\x82", + 'nose' => "\xF0\x9F\x91\x83", + 'lips' => "\xF0\x9F\x91\x84", + 'tongue' => "\xF0\x9F\x91\x85", + 'point_up_2' => "\xF0\x9F\x91\x86", + 'point_down' => "\xF0\x9F\x91\x87", + 'point_left' => "\xF0\x9F\x91\x88", + 'point_right' => "\xF0\x9F\x91\x89", + 'punch' => "\xF0\x9F\x91\x8A", + 'facepunch' => "\xF0\x9F\x91\x8A", + 'wave' => "\xF0\x9F\x91\x8B", + 'ok_hand' => "\xF0\x9F\x91\x8C", + '+1' => "\xF0\x9F\x91\x8D", + 'thumbsup' => "\xF0\x9F\x91\x8D", + '_1' => "\xF0\x9F\x91\x8E", + 'thumbsdown' => "\xF0\x9F\x91\x8E", + 'clap' => "\xF0\x9F\x91\x8F", + 'open_hands' => "\xF0\x9F\x91\x90", + 'crown' => "\xF0\x9F\x91\x91", + 'womans_hat' => "\xF0\x9F\x91\x92", + 'eyeglasses' => "\xF0\x9F\x91\x93", + 'necktie' => "\xF0\x9F\x91\x94", + 'tshirt' => "\xF0\x9F\x91\x95", + 'shirt' => "\xF0\x9F\x91\x95", + 'jeans' => "\xF0\x9F\x91\x96", + 'dress' => "\xF0\x9F\x91\x97", + 'kimono' => "\xF0\x9F\x91\x98", + 'bikini' => "\xF0\x9F\x91\x99", + 'womans_clothes' => "\xF0\x9F\x91\x9A", + 'purse' => "\xF0\x9F\x91\x9B", + 'handbag' => "\xF0\x9F\x91\x9C", + 'pouch' => "\xF0\x9F\x91\x9D", + 'mans_shoe' => "\xF0\x9F\x91\x9E", + 'shoe' => "\xF0\x9F\x91\x9E", + 'athletic_shoe' => "\xF0\x9F\x91\x9F", + 'high_heel' => "\xF0\x9F\x91\xA0", + 'sandal' => "\xF0\x9F\x91\xA1", + 'boot' => "\xF0\x9F\x91\xA2", + 'footprints' => "\xF0\x9F\x91\xA3", + 'bust_in_silhouette' => "\xF0\x9F\x91\xA4", + 'busts_in_silhouette' => "\xF0\x9F\x91\xA5", + 'boy' => "\xF0\x9F\x91\xA6", + 'girl' => "\xF0\x9F\x91\xA7", + 'man' => "\xF0\x9F\x91\xA8", + 'woman' => "\xF0\x9F\x91\xA9", + 'family' => "\xF0\x9F\x91\xAA", + 'couple' => "\xF0\x9F\x91\xAB", + 'two_men_holding_hands' => "\xF0\x9F\x91\xAC", + 'two_women_holding_hands' => "\xF0\x9F\x91\xAD", + 'cop' => "\xF0\x9F\x91\xAE", + 'dancers' => "\xF0\x9F\x91\xAF", + 'bride_with_veil' => "\xF0\x9F\x91\xB0", + 'person_with_blond_hair' => "\xF0\x9F\x91\xB1", + 'man_with_gua_pi_mao' => "\xF0\x9F\x91\xB2", + 'man_with_turban' => "\xF0\x9F\x91\xB3", + 'older_man' => "\xF0\x9F\x91\xB4", + 'older_woman' => "\xF0\x9F\x91\xB5", + 'baby' => "\xF0\x9F\x91\xB6", + 'construction_worker' => "\xF0\x9F\x91\xB7", + 'princess' => "\xF0\x9F\x91\xB8", + 'japanese_ogre' => "\xF0\x9F\x91\xB9", + 'japanese_goblin' => "\xF0\x9F\x91\xBA", + 'ghost' => "\xF0\x9F\x91\xBB", + 'angel' => "\xF0\x9F\x91\xBC", + 'alien' => "\xF0\x9F\x91\xBD", + 'space_invader' => "\xF0\x9F\x91\xBE", + 'imp' => "\xF0\x9F\x91\xBF", + 'skull' => "\xF0\x9F\x92\x80", + 'information_desk_person' => "\xF0\x9F\x92\x81", + 'guardsman' => "\xF0\x9F\x92\x82", + 'dancer' => "\xF0\x9F\x92\x83", + 'lipstick' => "\xF0\x9F\x92\x84", + 'nail_care' => "\xF0\x9F\x92\x85", + 'massage' => "\xF0\x9F\x92\x86", + 'haircut' => "\xF0\x9F\x92\x87", + 'barber' => "\xF0\x9F\x92\x88", + 'syringe' => "\xF0\x9F\x92\x89", + 'pill' => "\xF0\x9F\x92\x8A", + 'kiss' => "\xF0\x9F\x92\x8B", + 'love_letter' => "\xF0\x9F\x92\x8C", + 'ring' => "\xF0\x9F\x92\x8D", + 'gem' => "\xF0\x9F\x92\x8E", + 'couplekiss' => "\xF0\x9F\x92\x8F", + 'bouquet' => "\xF0\x9F\x92\x90", + 'couple_with_heart' => "\xF0\x9F\x92\x91", + 'wedding' => "\xF0\x9F\x92\x92", + 'heartbeat' => "\xF0\x9F\x92\x93", + 'broken_heart' => "\xF0\x9F\x92\x94", + 'two_hearts' => "\xF0\x9F\x92\x95", + 'sparkling_heart' => "\xF0\x9F\x92\x96", + 'heartpulse' => "\xF0\x9F\x92\x97", + 'cupid' => "\xF0\x9F\x92\x98", + 'blue_heart' => "\xF0\x9F\x92\x99", + 'green_heart' => "\xF0\x9F\x92\x9A", + 'yellow_heart' => "\xF0\x9F\x92\x9B", + 'purple_heart' => "\xF0\x9F\x92\x9C", + 'gift_heart' => "\xF0\x9F\x92\x9D", + 'revolving_hearts' => "\xF0\x9F\x92\x9E", + 'heart_decoration' => "\xF0\x9F\x92\x9F", + 'diamond_shape_with_a_dot_inside' => "\xF0\x9F\x92\xA0", + 'bulb' => "\xF0\x9F\x92\xA1", + 'anger' => "\xF0\x9F\x92\xA2", + 'bomb' => "\xF0\x9F\x92\xA3", + 'zzz' => "\xF0\x9F\x92\xA4", + 'boom' => "\xF0\x9F\x92\xA5", + 'collision' => "\xF0\x9F\x92\xA5", + 'sweat_drops' => "\xF0\x9F\x92\xA6", + 'droplet' => "\xF0\x9F\x92\xA7", + 'dash' => "\xF0\x9F\x92\xA8", + 'poop' => "\xF0\x9F\x92\xA9", + 'shit' => "\xF0\x9F\x92\xA9", + 'hankey' => "\xF0\x9F\x92\xA9", + 'muscle' => "\xF0\x9F\x92\xAA", + 'dizzy' => "\xF0\x9F\x92\xAB", + 'speech_balloon' => "\xF0\x9F\x92\xAC", + 'thought_balloon' => "\xF0\x9F\x92\xAD", + 'white_flower' => "\xF0\x9F\x92\xAE", + '100' => "\xF0\x9F\x92\xAF", + 'moneybag' => "\xF0\x9F\x92\xB0", + 'currency_exchange' => "\xF0\x9F\x92\xB1", + 'heavy_dollar_sign' => "\xF0\x9F\x92\xB2", + 'credit_card' => "\xF0\x9F\x92\xB3", + 'yen' => "\xF0\x9F\x92\xB4", + 'dollar' => "\xF0\x9F\x92\xB5", + 'euro' => "\xF0\x9F\x92\xB6", + 'pound' => "\xF0\x9F\x92\xB7", + 'money_with_wings' => "\xF0\x9F\x92\xB8", + 'chart' => "\xF0\x9F\x92\xB9", + 'seat' => "\xF0\x9F\x92\xBA", + 'computer' => "\xF0\x9F\x92\xBB", + 'briefcase' => "\xF0\x9F\x92\xBC", + 'minidisc' => "\xF0\x9F\x92\xBD", + 'floppy_disk' => "\xF0\x9F\x92\xBE", + 'cd' => "\xF0\x9F\x92\xBF", + 'dvd' => "\xF0\x9F\x93\x80", + 'file_folder' => "\xF0\x9F\x93\x81", + 'open_file_folder' => "\xF0\x9F\x93\x82", + 'page_with_curl' => "\xF0\x9F\x93\x83", + 'page_facing_up' => "\xF0\x9F\x93\x84", + 'date' => "\xF0\x9F\x93\x85", + 'calendar' => "\xF0\x9F\x93\x86", + 'card_index' => "\xF0\x9F\x93\x87", + 'chart_with_upwards_trend' => "\xF0\x9F\x93\x88", + 'chart_with_downwards_trend' => "\xF0\x9F\x93\x89", + 'bar_chart' => "\xF0\x9F\x93\x8A", + 'clipboard' => "\xF0\x9F\x93\x8B", + 'pushpin' => "\xF0\x9F\x93\x8C", + 'round_pushpin' => "\xF0\x9F\x93\x8D", + 'paperclip' => "\xF0\x9F\x93\x8E", + 'straight_ruler' => "\xF0\x9F\x93\x8F", + 'triangular_ruler' => "\xF0\x9F\x93\x90", + 'bookmark_tabs' => "\xF0\x9F\x93\x91", + 'ledger' => "\xF0\x9F\x93\x92", + 'notebook' => "\xF0\x9F\x93\x93", + 'notebook_with_decorative_cover' => "\xF0\x9F\x93\x94", + 'closed_book' => "\xF0\x9F\x93\x95", + 'book' => "\xF0\x9F\x93\x96", + 'open_book' => "\xF0\x9F\x93\x96", + 'green_book' => "\xF0\x9F\x93\x97", + 'blue_book' => "\xF0\x9F\x93\x98", + 'orange_book' => "\xF0\x9F\x93\x99", + 'books' => "\xF0\x9F\x93\x9A", + 'name_badge' => "\xF0\x9F\x93\x9B", + 'scroll' => "\xF0\x9F\x93\x9C", + 'pencil' => "\xF0\x9F\x93\x9D", + 'memo' => "\xF0\x9F\x93\x9D", + 'telephone_receiver' => "\xF0\x9F\x93\x9E", + 'pager' => "\xF0\x9F\x93\x9F", + 'fax' => "\xF0\x9F\x93\xA0", + 'satellite' => "\xF0\x9F\x93\xA1", + 'loudspeaker' => "\xF0\x9F\x93\xA2", + 'mega' => "\xF0\x9F\x93\xA3", + 'outbox_tray' => "\xF0\x9F\x93\xA4", + 'inbox_tray' => "\xF0\x9F\x93\xA5", + 'package' => "\xF0\x9F\x93\xA6", + 'e_mail' => "\xF0\x9F\x93\xA7", + 'incoming_envelope' => "\xF0\x9F\x93\xA8", + 'envelope_with_arrow' => "\xF0\x9F\x93\xA9", + 'mailbox_closed' => "\xF0\x9F\x93\xAA", + 'mailbox' => "\xF0\x9F\x93\xAB", + 'mailbox_with_mail' => "\xF0\x9F\x93\xAC", + 'mailbox_with_no_mail' => "\xF0\x9F\x93\xAD", + 'postbox' => "\xF0\x9F\x93\xAE", + 'postal_horn' => "\xF0\x9F\x93\xAF", + 'newspaper' => "\xF0\x9F\x93\xB0", + 'iphone' => "\xF0\x9F\x93\xB1", + 'calling' => "\xF0\x9F\x93\xB2", + 'vibration_mode' => "\xF0\x9F\x93\xB3", + 'mobile_phone_off' => "\xF0\x9F\x93\xB4", + 'no_mobile_phones' => "\xF0\x9F\x93\xB5", + 'signal_strength' => "\xF0\x9F\x93\xB6", + 'camera' => "\xF0\x9F\x93\xB7", + 'video_camera' => "\xF0\x9F\x93\xB9", + 'tv' => "\xF0\x9F\x93\xBA", + 'radio' => "\xF0\x9F\x93\xBB", + 'vhs' => "\xF0\x9F\x93\xBC", + 'twisted_rightwards_arrows' => "\xF0\x9F\x94\x80", + 'repeat' => "\xF0\x9F\x94\x81", + 'repeat_one' => "\xF0\x9F\x94\x82", + 'arrows_clockwise' => "\xF0\x9F\x94\x83", + 'arrows_counterclockwise' => "\xF0\x9F\x94\x84", + 'low_brightness' => "\xF0\x9F\x94\x85", + 'high_brightness' => "\xF0\x9F\x94\x86", + 'mute' => "\xF0\x9F\x94\x87", + 'speaker' => "\xF0\x9F\x94\x88", + 'sound' => "\xF0\x9F\x94\x89", + 'loud_sound' => "\xF0\x9F\x94\x8A", + 'battery' => "\xF0\x9F\x94\x8B", + 'electric_plug' => "\xF0\x9F\x94\x8C", + 'mag' => "\xF0\x9F\x94\x8D", + 'mag_right' => "\xF0\x9F\x94\x8E", + 'lock_with_ink_pen' => "\xF0\x9F\x94\x8F", + 'closed_lock_with_key' => "\xF0\x9F\x94\x90", + 'key' => "\xF0\x9F\x94\x91", + 'lock' => "\xF0\x9F\x94\x92", + 'unlock' => "\xF0\x9F\x94\x93", + 'bell' => "\xF0\x9F\x94\x94", + 'no_bell' => "\xF0\x9F\x94\x95", + 'bookmark' => "\xF0\x9F\x94\x96", + 'link' => "\xF0\x9F\x94\x97", + 'radio_button' => "\xF0\x9F\x94\x98", + 'back' => "\xF0\x9F\x94\x99", + 'end' => "\xF0\x9F\x94\x9A", + 'on' => "\xF0\x9F\x94\x9B", + 'soon' => "\xF0\x9F\x94\x9C", + 'top' => "\xF0\x9F\x94\x9D", + 'underage' => "\xF0\x9F\x94\x9E", + 'keycap_ten' => "\xF0\x9F\x94\x9F", + 'capital_abcd' => "\xF0\x9F\x94\xA0", + 'abcd' => "\xF0\x9F\x94\xA1", + '1234' => "\xF0\x9F\x94\xA2", + 'symbols' => "\xF0\x9F\x94\xA3", + 'abc' => "\xF0\x9F\x94\xA4", + 'fire' => "\xF0\x9F\x94\xA5", + 'flashlight' => "\xF0\x9F\x94\xA6", + 'wrench' => "\xF0\x9F\x94\xA7", + 'hammer' => "\xF0\x9F\x94\xA8", + 'nut_and_bolt' => "\xF0\x9F\x94\xA9", + 'knife' => "\xF0\x9F\x94\xAA", + 'hocho' => "\xF0\x9F\x94\xAA", + 'gun' => "\xF0\x9F\x94\xAB", + 'microscope' => "\xF0\x9F\x94\xAC", + 'telescope' => "\xF0\x9F\x94\xAD", + 'crystal_ball' => "\xF0\x9F\x94\xAE", + 'six_pointed_star' => "\xF0\x9F\x94\xAF", + 'beginner' => "\xF0\x9F\x94\xB0", + 'trident' => "\xF0\x9F\x94\xB1", + 'black_square_button' => "\xF0\x9F\x94\xB2", + 'white_square_button' => "\xF0\x9F\x94\xB3", + 'red_circle' => "\xF0\x9F\x94\xB4", + 'large_blue_circle' => "\xF0\x9F\x94\xB5", + 'large_orange_diamond' => "\xF0\x9F\x94\xB6", + 'large_blue_diamond' => "\xF0\x9F\x94\xB7", + 'small_orange_diamond' => "\xF0\x9F\x94\xB8", + 'small_blue_diamond' => "\xF0\x9F\x94\xB9", + 'small_red_triangle' => "\xF0\x9F\x94\xBA", + 'small_red_triangle_down' => "\xF0\x9F\x94\xBB", + 'arrow_up_small' => "\xF0\x9F\x94\xBC", + 'arrow_down_small' => "\xF0\x9F\x94\xBD", + 'clock1' => "\xF0\x9F\x95\x90", + 'clock2' => "\xF0\x9F\x95\x91", + 'clock3' => "\xF0\x9F\x95\x92", + 'clock4' => "\xF0\x9F\x95\x93", + 'clock5' => "\xF0\x9F\x95\x94", + 'clock6' => "\xF0\x9F\x95\x95", + 'clock7' => "\xF0\x9F\x95\x96", + 'clock8' => "\xF0\x9F\x95\x97", + 'clock9' => "\xF0\x9F\x95\x98", + 'clock10' => "\xF0\x9F\x95\x99", + 'clock11' => "\xF0\x9F\x95\x9A", + 'clock12' => "\xF0\x9F\x95\x9B", + 'clock130' => "\xF0\x9F\x95\x9C", + 'clock230' => "\xF0\x9F\x95\x9D", + 'clock330' => "\xF0\x9F\x95\x9E", + 'clock430' => "\xF0\x9F\x95\x9F", + 'clock530' => "\xF0\x9F\x95\xA0", + 'clock630' => "\xF0\x9F\x95\xA1", + 'clock730' => "\xF0\x9F\x95\xA2", + 'clock830' => "\xF0\x9F\x95\xA3", + 'clock930' => "\xF0\x9F\x95\xA4", + 'clock1030' => "\xF0\x9F\x95\xA5", + 'clock1130' => "\xF0\x9F\x95\xA6", + 'clock1230' => "\xF0\x9F\x95\xA7", + 'mount_fuji' => "\xF0\x9F\x97\xBB", + 'tokyo_tower' => "\xF0\x9F\x97\xBC", + 'statue_of_liberty' => "\xF0\x9F\x97\xBD", + 'japan' => "\xF0\x9F\x97\xBE", + 'moyai' => "\xF0\x9F\x97\xBF", + 'grinning' => "\xF0\x9F\x98\x80", + 'grin' => "\xF0\x9F\x98\x81", + 'joy' => "\xF0\x9F\x98\x82", + 'smiley' => "\xF0\x9F\x98\x83", + 'smile' => "\xF0\x9F\x98\x84", + 'sweat_smile' => "\xF0\x9F\x98\x85", + 'satisfied' => "\xF0\x9F\x98\x86", + 'laughing' => "\xF0\x9F\x98\x86", + 'innocent' => "\xF0\x9F\x98\x87", + 'smiling_imp' => "\xF0\x9F\x98\x88", + 'wink' => "\xF0\x9F\x98\x89", + 'blush' => "\xF0\x9F\x98\x8A", + 'yum' => "\xF0\x9F\x98\x8B", + 'relieved' => "\xF0\x9F\x98\x8C", + 'heart_eyes' => "\xF0\x9F\x98\x8D", + 'sunglasses' => "\xF0\x9F\x98\x8E", + 'smirk' => "\xF0\x9F\x98\x8F", + 'neutral_face' => "\xF0\x9F\x98\x90", + 'expressionless' => "\xF0\x9F\x98\x91", + 'unamused' => "\xF0\x9F\x98\x92", + 'sweat' => "\xF0\x9F\x98\x93", + 'pensive' => "\xF0\x9F\x98\x94", + 'confused' => "\xF0\x9F\x98\x95", + 'confounded' => "\xF0\x9F\x98\x96", + 'kissing' => "\xF0\x9F\x98\x97", + 'kissing_heart' => "\xF0\x9F\x98\x98", + 'kissing_smiling_eyes' => "\xF0\x9F\x98\x99", + 'kissing_closed_eyes' => "\xF0\x9F\x98\x9A", + 'stuck_out_tongue' => "\xF0\x9F\x98\x9B", + 'stuck_out_tongue_winking_eye' => "\xF0\x9F\x98\x9C", + 'stuck_out_tongue_closed_eyes' => "\xF0\x9F\x98\x9D", + 'disappointed' => "\xF0\x9F\x98\x9E", + 'worried' => "\xF0\x9F\x98\x9F", + 'angry' => "\xF0\x9F\x98\xA0", + 'rage' => "\xF0\x9F\x98\xA1", + 'cry' => "\xF0\x9F\x98\xA2", + 'persevere' => "\xF0\x9F\x98\xA3", + 'triumph' => "\xF0\x9F\x98\xA4", + 'disappointed_relieved' => "\xF0\x9F\x98\xA5", + 'frowning' => "\xF0\x9F\x98\xA6", + 'anguished' => "\xF0\x9F\x98\xA7", + 'fearful' => "\xF0\x9F\x98\xA8", + 'weary' => "\xF0\x9F\x98\xA9", + 'sleepy' => "\xF0\x9F\x98\xAA", + 'tired_face' => "\xF0\x9F\x98\xAB", + 'grimacing' => "\xF0\x9F\x98\xAC", + 'sob' => "\xF0\x9F\x98\xAD", + 'open_mouth' => "\xF0\x9F\x98\xAE", + 'hushed' => "\xF0\x9F\x98\xAF", + 'cold_sweat' => "\xF0\x9F\x98\xB0", + 'scream' => "\xF0\x9F\x98\xB1", + 'astonished' => "\xF0\x9F\x98\xB2", + 'flushed' => "\xF0\x9F\x98\xB3", + 'sleeping' => "\xF0\x9F\x98\xB4", + 'dizzy_face' => "\xF0\x9F\x98\xB5", + 'no_mouth' => "\xF0\x9F\x98\xB6", + 'mask' => "\xF0\x9F\x98\xB7", + 'smile_cat' => "\xF0\x9F\x98\xB8", + 'joy_cat' => "\xF0\x9F\x98\xB9", + 'smiley_cat' => "\xF0\x9F\x98\xBA", + 'heart_eyes_cat' => "\xF0\x9F\x98\xBB", + 'smirk_cat' => "\xF0\x9F\x98\xBC", + 'kissing_cat' => "\xF0\x9F\x98\xBD", + 'pouting_cat' => "\xF0\x9F\x98\xBE", + 'crying_cat_face' => "\xF0\x9F\x98\xBF", + 'scream_cat' => "\xF0\x9F\x99\x80", + 'no_good' => "\xF0\x9F\x99\x85", + 'ok_woman' => "\xF0\x9F\x99\x86", + 'bow' => "\xF0\x9F\x99\x87", + 'see_no_evil' => "\xF0\x9F\x99\x88", + 'hear_no_evil' => "\xF0\x9F\x99\x89", + 'speak_no_evil' => "\xF0\x9F\x99\x8A", + 'raising_hand' => "\xF0\x9F\x99\x8B", + 'raised_hands' => "\xF0\x9F\x99\x8C", + 'person_frowning' => "\xF0\x9F\x99\x8D", + 'person_with_pouting_face' => "\xF0\x9F\x99\x8E", + 'pray' => "\xF0\x9F\x99\x8F", + 'rocket' => "\xF0\x9F\x9A\x80", + 'helicopter' => "\xF0\x9F\x9A\x81", + 'steam_locomotive' => "\xF0\x9F\x9A\x82", + 'railway_car' => "\xF0\x9F\x9A\x83", + 'bullettrain_side' => "\xF0\x9F\x9A\x84", + 'bullettrain_front' => "\xF0\x9F\x9A\x85", + 'train2' => "\xF0\x9F\x9A\x86", + 'metro' => "\xF0\x9F\x9A\x87", + 'light_rail' => "\xF0\x9F\x9A\x88", + 'station' => "\xF0\x9F\x9A\x89", + 'tram' => "\xF0\x9F\x9A\x8A", + 'train' => "\xF0\x9F\x9A\x8B", + 'bus' => "\xF0\x9F\x9A\x8C", + 'oncoming_bus' => "\xF0\x9F\x9A\x8D", + 'trolleybus' => "\xF0\x9F\x9A\x8E", + 'busstop' => "\xF0\x9F\x9A\x8F", + 'minibus' => "\xF0\x9F\x9A\x90", + 'ambulance' => "\xF0\x9F\x9A\x91", + 'fire_engine' => "\xF0\x9F\x9A\x92", + 'police_car' => "\xF0\x9F\x9A\x93", + 'oncoming_police_car' => "\xF0\x9F\x9A\x94", + 'taxi' => "\xF0\x9F\x9A\x95", + 'oncoming_taxi' => "\xF0\x9F\x9A\x96", + 'red_car' => "\xF0\x9F\x9A\x97", + 'car' => "\xF0\x9F\x9A\x97", + 'oncoming_automobile' => "\xF0\x9F\x9A\x98", + 'blue_car' => "\xF0\x9F\x9A\x99", + 'truck' => "\xF0\x9F\x9A\x9A", + 'articulated_lorry' => "\xF0\x9F\x9A\x9B", + 'tractor' => "\xF0\x9F\x9A\x9C", + 'monorail' => "\xF0\x9F\x9A\x9D", + 'mountain_railway' => "\xF0\x9F\x9A\x9E", + 'suspension_railway' => "\xF0\x9F\x9A\x9F", + 'mountain_cableway' => "\xF0\x9F\x9A\xA0", + 'aerial_tramway' => "\xF0\x9F\x9A\xA1", + 'ship' => "\xF0\x9F\x9A\xA2", + 'rowboat' => "\xF0\x9F\x9A\xA3", + 'speedboat' => "\xF0\x9F\x9A\xA4", + 'traffic_light' => "\xF0\x9F\x9A\xA5", + 'vertical_traffic_light' => "\xF0\x9F\x9A\xA6", + 'construction' => "\xF0\x9F\x9A\xA7", + 'rotating_light' => "\xF0\x9F\x9A\xA8", + 'triangular_flag_on_post' => "\xF0\x9F\x9A\xA9", + 'door' => "\xF0\x9F\x9A\xAA", + 'no_entry_sign' => "\xF0\x9F\x9A\xAB", + 'smoking' => "\xF0\x9F\x9A\xAC", + 'no_smoking' => "\xF0\x9F\x9A\xAD", + 'put_litter_in_its_place' => "\xF0\x9F\x9A\xAE", + 'do_not_litter' => "\xF0\x9F\x9A\xAF", + 'potable_water' => "\xF0\x9F\x9A\xB0", + 'non_potable_water' => "\xF0\x9F\x9A\xB1", + 'bike' => "\xF0\x9F\x9A\xB2", + 'no_bicycles' => "\xF0\x9F\x9A\xB3", + 'bicyclist' => "\xF0\x9F\x9A\xB4", + 'mountain_bicyclist' => "\xF0\x9F\x9A\xB5", + 'walking' => "\xF0\x9F\x9A\xB6", + 'no_pedestrians' => "\xF0\x9F\x9A\xB7", + 'children_crossing' => "\xF0\x9F\x9A\xB8", + 'mens' => "\xF0\x9F\x9A\xB9", + 'womens' => "\xF0\x9F\x9A\xBA", + 'restroom' => "\xF0\x9F\x9A\xBB", + 'baby_symbol' => "\xF0\x9F\x9A\xBC", + 'toilet' => "\xF0\x9F\x9A\xBD", + 'wc' => "\xF0\x9F\x9A\xBE", + 'shower' => "\xF0\x9F\x9A\xBF", + 'bath' => "\xF0\x9F\x9B\x80", + 'bathtub' => "\xF0\x9F\x9B\x81", + 'passport_control' => "\xF0\x9F\x9B\x82", + 'customs' => "\xF0\x9F\x9B\x83", + 'baggage_claim' => "\xF0\x9F\x9B\x84", + 'left_luggage' => "\xF0\x9F\x9B\x85", + 'copyright' => "\xC2\xA9\xEF\xB8\x8F", + 'registered' => "\xC2\xAE\xEF\xB8\x8F", + 'bangbang' => "\xE2\x80\xBC\xEF\xB8\x8F", + 'interrobang' => "\xE2\x81\x89\xEF\xB8\x8F", + 'tm' => "\xE2\x84\xA2\xEF\xB8\x8F", + 'information_source' => "\xE2\x84\xB9\xEF\xB8\x8F", + 'left_right_arrow' => "\xE2\x86\x94\xEF\xB8\x8F", + 'arrow_up_down' => "\xE2\x86\x95\xEF\xB8\x8F", + 'arrow_upper_left' => "\xE2\x86\x96\xEF\xB8\x8F", + 'arrow_upper_right' => "\xE2\x86\x97\xEF\xB8\x8F", + 'arrow_lower_right' => "\xE2\x86\x98\xEF\xB8\x8F", + 'arrow_lower_left' => "\xE2\x86\x99\xEF\xB8\x8F", + 'leftwards_arrow_with_hook' => "\xE2\x86\xA9\xEF\xB8\x8F", + 'arrow_right_hook' => "\xE2\x86\xAA\xEF\xB8\x8F", + 'm' => "\xE2\x93\x82\xEF\xB8\x8F", + 'black_small_square' => "\xE2\x96\xAA\xEF\xB8\x8F", + 'white_small_square' => "\xE2\x96\xAB\xEF\xB8\x8F", + 'arrow_forward' => "\xE2\x96\xB6\xEF\xB8\x8F", + 'arrow_backward' => "\xE2\x97\x80\xEF\xB8\x8F", + 'white_medium_square' => "\xE2\x97\xBB\xEF\xB8\x8F", + 'black_medium_square' => "\xE2\x97\xBC\xEF\xB8\x8F", + 'sunny' => "\xE2\x98\x80\xEF\xB8\x8F", + 'cloud' => "\xE2\x98\x81\xEF\xB8\x8F", + 'telephone' => "\xE2\x98\x8E\xEF\xB8\x8F", + 'phone' => "\xE2\x98\x8E\xEF\xB8\x8F", + 'ballot_box_with_check' => "\xE2\x98\x91\xEF\xB8\x8F", + 'point_up' => "\xE2\x98\x9D\xEF\xB8\x8F", + 'relaxed' => "\xE2\x98\xBA\xEF\xB8\x8F", + 'spades' => "\xE2\x99\xA0\xEF\xB8\x8F", + 'clubs' => "\xE2\x99\xA3\xEF\xB8\x8F", + 'hearts' => "\xE2\x99\xA5\xEF\xB8\x8F", + 'diamonds' => "\xE2\x99\xA6\xEF\xB8\x8F", + 'hotsprings' => "\xE2\x99\xA8\xEF\xB8\x8F", + 'recycle' => "\xE2\x99\xBB\xEF\xB8\x8F", + 'warning' => "\xE2\x9A\xA0\xEF\xB8\x8F", + 'baseball' => "\xE2\x9A\xBE\xEF\xB8\x8F", + 'scissors' => "\xE2\x9C\x82\xEF\xB8\x8F", + 'airplane' => "\xE2\x9C\x88\xEF\xB8\x8F", + 'email' => "\xE2\x9C\x89\xEF\xB8\x8F", + 'envelope' => "\xE2\x9C\x89\xEF\xB8\x8F", + 'v' => "\xE2\x9C\x8C\xEF\xB8\x8F", + 'pencil2' => "\xE2\x9C\x8F\xEF\xB8\x8F", + 'black_nib' => "\xE2\x9C\x92\xEF\xB8\x8F", + 'heavy_check_mark' => "\xE2\x9C\x94\xEF\xB8\x8F", + 'heavy_multiplication_x' => "\xE2\x9C\x96\xEF\xB8\x8F", + 'eight_spoked_asterisk' => "\xE2\x9C\xB3\xEF\xB8\x8F", + 'eight_pointed_black_star' => "\xE2\x9C\xB4\xEF\xB8\x8F", + 'snowflake' => "\xE2\x9D\x84\xEF\xB8\x8F", + 'sparkle' => "\xE2\x9D\x87\xEF\xB8\x8F", + 'heart' => "\xE2\x9D\xA4\xEF\xB8\x8F", + 'arrow_right' => "\xE2\x9E\xA1\xEF\xB8\x8F", + 'arrow_heading_up' => "\xE2\xA4\xB4\xEF\xB8\x8F", + 'arrow_heading_down' => "\xE2\xA4\xB5\xEF\xB8\x8F", + 'arrow_left' => "\xE2\xAC\x85\xEF\xB8\x8F", + 'arrow_up' => "\xE2\xAC\x86\xEF\xB8\x8F", + 'arrow_down' => "\xE2\xAC\x87\xEF\xB8\x8F", + 'wavy_dash' => "\xE3\x80\xB0\xEF\xB8\x8F", + 'part_alternation_mark' => "\xE3\x80\xBD\xEF\xB8\x8F", + 'congratulations' => "\xE3\x8A\x97\xEF\xB8\x8F", + 'secret' => "\xE3\x8A\x99\xEF\xB8\x8F", + 'hash' => "\x23\xEF\xB8\x8F\xE2\x83\xA3", + 'zero' => "\x30\xEF\xB8\x8F\xE2\x83\xA3", + 'one' => "\x31\xEF\xB8\x8F\xE2\x83\xA3", + 'two' => "\x32\xEF\xB8\x8F\xE2\x83\xA3", + 'three' => "\x33\xEF\xB8\x8F\xE2\x83\xA3", + 'four' => "\x34\xEF\xB8\x8F\xE2\x83\xA3", + 'five' => "\x35\xEF\xB8\x8F\xE2\x83\xA3", + 'six' => "\x36\xEF\xB8\x8F\xE2\x83\xA3", + 'seven' => "\x37\xEF\xB8\x8F\xE2\x83\xA3", + 'eight' => "\x38\xEF\xB8\x8F\xE2\x83\xA3", + 'nine' => "\x39\xEF\xB8\x8F\xE2\x83\xA3", + 'a' => "\xF0\x9F\x85\xB0\xEF\xB8\x8F", + 'b' => "\xF0\x9F\x85\xB1\xEF\xB8\x8F", + 'o2' => "\xF0\x9F\x85\xBE\xEF\xB8\x8F", + 'parking' => "\xF0\x9F\x85\xBF\xEF\xB8\x8F", + 'sa' => "\xF0\x9F\x88\x82\xEF\xB8\x8F", + 'u6708' => "\xF0\x9F\x88\xB7\xEF\xB8\x8F", + 'cn' => "\xF0\x9F\x87\xA8\xF0\x9F\x87\xB3", + 'de' => "\xF0\x9F\x87\xA9\xF0\x9F\x87\xAA", + 'es' => "\xF0\x9F\x87\xAA\xF0\x9F\x87\xB8", + 'fr' => "\xF0\x9F\x87\xAB\xF0\x9F\x87\xB7", + 'uk' => "\xF0\x9F\x87\xAC\xF0\x9F\x87\xA7", + 'gb' => "\xF0\x9F\x87\xAC\xF0\x9F\x87\xA7", + 'it' => "\xF0\x9F\x87\xAE\xF0\x9F\x87\xB9", + 'jp' => "\xF0\x9F\x87\xAF\xF0\x9F\x87\xB5", + 'kr' => "\xF0\x9F\x87\xB0\xF0\x9F\x87\xB7", + 'ru' => "\xF0\x9F\x87\xB7\xF0\x9F\x87\xBA", + 'us' => "\xF0\x9F\x87\xBA\xF0\x9F\x87\xB8", + ); + + $matches[1] = str_replace('-', '_', $matches[1]); + + if (isset($map[$matches[1]])) { + return $map[$matches[1]]; + } + + return $matches[0]; + } + +}