public static function getPatchList()
 {
     $root = dirname(phutil_get_library_root('phabricator'));
     // Find the patch files
     $patches_dir = $root . '/resources/sql/patches/';
     $finder = new FileFinder($patches_dir);
     $results = $finder->find();
     $versions = array();
     $patches = array();
     foreach ($results as $path) {
         $matches = array();
         if (!preg_match('/(\\d+)\\..*\\.(sql|php)$/', $path, $matches)) {
             continue;
         }
         $version = (int) $matches[1];
         $patches[] = array('version' => $version, 'path' => $patches_dir . $path);
         if (empty($versions[$version])) {
             $versions[$version] = true;
         } else {
             throw new Exception("Two patches have version {$version}!");
         }
     }
     // Files are in some 'random' order returned by the operating system
     // We need to apply them in proper order
     $patches = isort($patches, 'version');
     return $patches;
 }
 public function run()
 {
     $roots = array();
     $roots['libphutil'] = dirname(phutil_get_library_root('phutil'));
     $roots['arcanist'] = dirname(phutil_get_library_root('arcanist'));
     foreach ($roots as $lib => $root) {
         echo "Upgrading {$lib}...\n";
         if (!Filesystem::pathExists($root . '/.git')) {
             throw new ArcanistUsageException("{$lib} must be in its git working copy to be automatically " . "upgraded. This copy of {$lib} (in '{$root}') is not in a git " . "working copy.");
         }
         $working_copy = ArcanistWorkingCopyIdentity::newFromPath($root);
         $repository_api = ArcanistRepositoryAPI::newAPIFromWorkingCopyIdentity($working_copy);
         // Force the range to HEAD^..HEAD, which is meaningless but keeps us
         // from triggering "base" rules or other commit range resolution rules
         // that might prompt the user when we pull the working copy status.
         $repository_api->setRelativeCommit('HEAD^');
         $this->setRepositoryAPI($repository_api);
         // Require no local changes.
         $this->requireCleanWorkingCopy();
         // Require the library be on master.
         $branch_name = $repository_api->getBranchName();
         if ($branch_name != 'master') {
             throw new ArcanistUsageException("{$lib} must be on branch 'master' to be automatically upgraded. " . "This copy of {$lib} (in '{$root}') is on branch '{$branch_name}'.");
         }
         chdir($root);
         try {
             phutil_passthru('git pull --rebase');
         } catch (Exception $ex) {
             phutil_passthru('git rebase --abort');
             throw $ex;
         }
     }
     echo phutil_console_wrap(phutil_console_format("**Updated!** Your copy of arc is now up to date.\n"));
     return 0;
 }
 public function processRequest()
 {
     $root = dirname(phutil_get_library_root('phabricator'));
     require_once $root . '/support/phame/libskin.php';
     $this->cssResources = array();
     $css = $this->getPath('css/');
     if (Filesystem::pathExists($css)) {
         foreach (Filesystem::listDirectory($css) as $path) {
             if (!preg_match('/.css$/', $path)) {
                 continue;
             }
             $this->cssResources[] = phutil_tag('link', array('rel' => 'stylesheet', 'type' => 'text/css', 'href' => $this->getResourceURI('css/' . $path)));
         }
     }
     $map = CelerityResourceMap::getNamedInstance('phabricator');
     $resource_symbol = 'syntax-highlighting-css';
     $resource_uri = $map->getURIForSymbol($resource_symbol);
     $this->cssResources[] = phutil_tag('link', array('rel' => 'stylesheet', 'type' => 'text/css', 'href' => PhabricatorEnv::getCDNURI($resource_uri)));
     $this->cssResources = phutil_implode_html("\n", $this->cssResources);
     $request = $this->getRequest();
     // Render page parts in order so the templates execute in order, if we're
     // using templates.
     $header = $this->renderHeader();
     $content = $this->renderContent($request);
     $footer = $this->renderFooter();
     if (!$content) {
         $content = $this->render404Page();
     }
     $content = array($header, $content, $footer);
     $response = new AphrontWebpageResponse();
     $response->setContent(phutil_implode_html("\n", $content));
     return $response;
 }
 /**
  * Calculate the DiffMatchPatch patch between two Phabricator files.
  *
  * @phutil-external-symbol class diff_match_patch
  */
 public static function calculatePatch(PhabricatorFile $old = null, PhabricatorFile $new = null)
 {
     $root = dirname(phutil_get_library_root('phabricator'));
     require_once $root . '/externals/diff_match_patch/diff_match_patch.php';
     $old_hash = self::EMPTY_HASH;
     $new_hash = self::EMPTY_HASH;
     if ($old !== null) {
         $old_hash = $old->getContentHash();
     }
     if ($new !== null) {
         $new_hash = $new->getContentHash();
     }
     $old_content = '';
     $new_content = '';
     if ($old_hash === $new_hash) {
         return null;
     }
     if ($old_hash !== self::EMPTY_HASH) {
         $old_content = $old->loadFileData();
     } else {
         $old_content = '';
     }
     if ($new_hash !== self::EMPTY_HASH) {
         $new_content = $new->loadFileData();
     } else {
         $new_content = '';
     }
     $dmp = new diff_match_patch();
     $dmp_patches = $dmp->patch_make($old_content, $new_content);
     return $dmp->patch_toText($dmp_patches);
 }
 public function run()
 {
     $roots = array();
     $roots['libphutil'] = dirname(phutil_get_library_root('phutil'));
     $roots['arcanist'] = dirname(phutil_get_library_root('arcanist'));
     foreach ($roots as $lib => $root) {
         echo "Upgrading {$lib}...\n";
         if (!Filesystem::pathExists($root . '/.git')) {
             throw new ArcanistUsageException("{$lib} must be in its git working copy to be automatically " . "upgraded. This copy of {$lib} (in '{$root}') is not in a git " . "working copy.");
         }
         $working_copy = ArcanistWorkingCopyIdentity::newFromPath($root);
         $configuration_manager = clone $this->getConfigurationManager();
         $configuration_manager->setWorkingCopyIdentity($working_copy);
         $repository_api = ArcanistRepositoryAPI::newAPIFromConfigurationManager($configuration_manager);
         $this->setRepositoryAPI($repository_api);
         // Require no local changes.
         $this->requireCleanWorkingCopy();
         // Require the library be on master.
         $branch_name = $repository_api->getBranchName();
         if ($branch_name != 'master') {
             throw new ArcanistUsageException("{$lib} must be on branch 'master' to be automatically upgraded. " . "This copy of {$lib} (in '{$root}') is on branch '{$branch_name}'.");
         }
         chdir($root);
         try {
             phutil_passthru('git pull --rebase');
         } catch (Exception $ex) {
             phutil_passthru('git rebase --abort');
             throw $ex;
         }
     }
     echo phutil_console_wrap(phutil_console_format("**Updated!** Your copy of arc is now up to date.\n"));
     return 0;
 }
 private function buildBootSequence()
 {
     if (!$this->bootSequence) {
         $files = array('utils/utils.php', 'object/Phobject.php', 'utils/PhutilRope.php', 'xsprintf/xsprintf.php', 'xsprintf/csprintf.php', 'xsprintf/PhutilCommandString.php', 'future/Future.php', 'future/FutureIterator.php', 'future/exec/ExecFuture.php', 'future/exec/CommandException.php', 'channel/PhutilChannel.php', 'channel/PhutilSocketChannel.php', 'channel/PhutilChannelChannel.php', 'channel/PhutilProtocolChannel.php', 'channel/PhutilJSONProtocolChannel.php', 'phage/agent/PhagePHPAgent.php');
         $main_sequence = new PhutilBallOfPHP();
         $root = phutil_get_library_root('phutil');
         foreach ($files as $file) {
             $main_sequence->addFile($root . '/' . $file);
         }
         $main_sequence->addText('id(new PhagePHPAgent($I))->execute();');
         $main_length = strlen($main_sequence->toString());
         $boot_sequence = new PhutilBallOfPHP();
         $boot = '
     $length = ' . $main_length . ';
     $buffer = "";
     while (strlen($buffer) < $length) {
       $data = fread($I, $length - strlen($buffer));
       if (!strlen($data)) {
         exit(1);
       }
       $buffer .= $data;
     }
     eval($buffer);';
         $boot_sequence->addText($boot);
         $boot_length = strlen($boot_sequence->toString());
         $boot_sequence->addText($main_sequence->toString());
         if (strlen($boot_length) > 8192) {
             throw new Exception("Stage 1 bootloader is too large!");
         }
         $this->bootSequence = $boot_sequence;
         $this->bootLength = $boot_length;
         $this->mainLength = $main_length;
     }
     return $this->bootSequence;
 }
 public function run()
 {
     $roots = array('libphutil' => dirname(phutil_get_library_root('phutil')), 'arcanist' => dirname(phutil_get_library_root('arcanist')));
     foreach ($roots as $lib => $root) {
         echo phutil_console_format("%s\n", pht('Upgrading %s...', $lib));
         $working_copy = ArcanistWorkingCopyIdentity::newFromPath($root);
         $configuration_manager = clone $this->getConfigurationManager();
         $configuration_manager->setWorkingCopyIdentity($working_copy);
         $repository = ArcanistRepositoryAPI::newAPIFromConfigurationManager($configuration_manager);
         if (!Filesystem::pathExists($repository->getMetadataPath())) {
             throw new ArcanistUsageException(pht("%s must be in its git working copy to be automatically upgraded. " . "This copy of %s (in '%s') is not in a git working copy.", $lib, $lib, $root));
         }
         $this->setRepositoryAPI($repository);
         // Require no local changes.
         $this->requireCleanWorkingCopy();
         // Require the library be on master.
         $branch_name = $repository->getBranchName();
         if ($branch_name != 'master') {
             throw new ArcanistUsageException(pht("%s must be on branch '%s' to be automatically upgraded. " . "This copy of %s (in '%s') is on branch '%s'.", $lib, 'master', $lib, $root, $branch_name));
         }
         chdir($root);
         try {
             phutil_passthru('git pull --rebase');
         } catch (Exception $ex) {
             phutil_passthru('git rebase --abort');
             throw $ex;
         }
     }
     echo phutil_console_format("**%s** %s\n", pht('Updated!'), pht('Your copy of arc is now up to date.'));
     return 0;
 }
 private function loadVersions(PhabricatorUser $viewer)
 {
     $specs = array('phabricator', 'arcanist', 'phutil');
     $all_libraries = PhutilBootloader::getInstance()->getAllLibraries();
     // This puts the core libraries at the top:
     $other_libraries = array_diff($all_libraries, $specs);
     $specs = array_merge($specs, $other_libraries);
     $futures = array();
     foreach ($specs as $lib) {
         $root = dirname(phutil_get_library_root($lib));
         $futures[$lib] = id(new ExecFuture('git log --format=%s -n 1 --', '%H %ct'))->setCWD($root);
     }
     $results = array();
     foreach ($futures as $key => $future) {
         list($err, $stdout) = $future->resolve();
         if (!$err) {
             list($hash, $epoch) = explode(' ', $stdout);
             $version = pht('%s (%s)', $hash, phabricator_date($epoch, $viewer));
         } else {
             $version = pht('Unknown');
         }
         $results[$key] = $version;
     }
     return $results;
 }
 public static function loadOneSkinSpecification($name)
 {
     // Only allow skins which we know to exist to load. This prevents loading
     // skins like "../../secrets/evil/".
     $all = self::loadAllSkinSpecifications();
     if (empty($all[$name])) {
         throw new Exception(pht('Blog skin "%s" is not a valid skin!', $name));
     }
     $paths = PhabricatorEnv::getEnvConfig('phame.skins');
     $base = dirname(phutil_get_library_root('phabricator'));
     foreach ($paths as $path) {
         $path = Filesystem::resolvePath($path, $base);
         $skin_path = $path . DIRECTORY_SEPARATOR . $name;
         if (is_dir($skin_path)) {
             // Double check that the skin really lives in the skin directory.
             if (!Filesystem::isDescendant($skin_path, $path)) {
                 throw new Exception(pht('Blog skin "%s" is not located in path "%s"!', $name, $path));
             }
             $spec = self::loadSkinSpecification($skin_path);
             if ($spec) {
                 $spec->setName($name);
                 return $spec;
             }
         }
     }
     return null;
 }
 public function getPatches()
 {
     $patches = array();
     foreach ($this->getOldPatches() as $old_name => $old_patch) {
         if (preg_match('/^db\\./', $old_name)) {
             $old_patch['name'] = substr($old_name, 3);
             $old_patch['type'] = 'db';
         } else {
             if (empty($old_patch['name'])) {
                 $old_patch['name'] = $this->getPatchPath($old_name);
             }
             if (empty($old_patch['type'])) {
                 $matches = null;
                 preg_match('/\\.(sql|php)$/', $old_name, $matches);
                 $old_patch['type'] = $matches[1];
             }
         }
         $patches[$old_name] = $old_patch;
     }
     $root = dirname(phutil_get_library_root('phabricator'));
     $auto_root = $root . '/resources/sql/autopatches/';
     $auto_list = Filesystem::listDirectory($auto_root, $include_hidden = false);
     sort($auto_list);
     foreach ($auto_list as $auto_patch) {
         $matches = null;
         if (!preg_match('/\\.(sql|php)$/', $auto_patch, $matches)) {
             throw new Exception(pht('Unknown patch "%s" in "%s", expected ".php" or ".sql" suffix.', $auto_patch, $auto_root));
         }
         $patches[$auto_patch] = array('type' => $matches[1], 'name' => $auto_root . $auto_patch);
     }
     return $patches;
 }
 protected function willRun()
 {
     parent::willRun();
     $phabricator = phutil_get_library_root('phabricator');
     $root = dirname($phabricator);
     require_once $root . '/scripts/__init_script__.php';
 }
Example #12
0
 public function getPEP8Path()
 {
     $working_copy = $this->getEngine()->getWorkingCopy();
     $prefix = $working_copy->getConfig('lint.pep8.prefix');
     $bin = $working_copy->getConfig('lint.pep8.bin');
     if ($bin === null && $prefix === null) {
         $bin = csprintf('/usr/bin/env python2.6 %s', phutil_get_library_root('arcanist') . '/../externals/pep8/pep8.py');
     } else {
         if ($bin === null) {
             $bin = 'pep8';
         }
         if ($prefix !== null) {
             if (!Filesystem::pathExists($prefix . '/' . $bin)) {
                 throw new ArcanistUsageException("Unable to find PEP8 binary in a specified directory. Make sure " . "that 'lint.pep8.prefix' and 'lint.pep8.bin' keys are set " . "correctly. If you'd rather use a copy of PEP8 installed " . "globally, you can just remove these keys from your .arcconfig");
             }
             $bin = csprintf("%s/%s", $prefix, $bin);
             return $bin;
         }
         // Look for globally installed PEP8
         list($err) = exec_manual('which %s', $bin);
         if ($err) {
             throw new ArcanistUsageException("PEP8 does not appear to be installed on this system. Install it " . "(e.g., with 'easy_install pep8') or configure " . "'lint.pep8.prefix' in your .arcconfig to point to the directory " . "where it resides.");
         }
     }
     return $bin;
 }
 private function getPatchPath($file)
 {
     $root = dirname(phutil_get_library_root('phabricator'));
     $path = $root . '/resources/sql/patches/' . $file;
     // Make sure it exists.
     Filesystem::readFile($path);
     return $path;
 }
 /**
  * @phutil-external-symbol class PHPMailerLite
  */
 public function __construct()
 {
     $root = phutil_get_library_root('phabricator');
     $root = dirname($root);
     require_once $root . '/externals/phpmailer/class.phpmailer-lite.php';
     $this->mailer = new PHPMailerLite($use_exceptions = true);
     $this->mailer->CharSet = 'utf-8';
 }
 /**
  * @phutil-external-symbol class Services_Twilio
  */
 private function buildClient()
 {
     $root = dirname(phutil_get_library_root('phabricator'));
     require_once $root . '/externals/twilio-php/Services/Twilio.php';
     $account_sid = PhabricatorEnv::getEnvConfig('twilio.account-sid');
     $auth_token = PhabricatorEnv::getEnvConfig('twilio.auth-token');
     return new Services_Twilio($account_sid, $auth_token);
 }
 public function generateData()
 {
     $lib_data = array();
     foreach (PhutilBootloader::getInstance()->getAllLibraries() as $lib) {
         $lib_data[$lib] = phutil_get_library_root($lib);
     }
     return array('config' => PhabricatorEnv::getAllConfigKeys(), 'libraries' => $lib_data);
 }
 /**
  * @phutil-external-symbol function phabricator_read_config_file
  */
 public function __construct($config)
 {
     $root = dirname(phutil_get_library_root('phabricator'));
     require_once $root . '/conf/__init_conf__.php';
     $dictionary = phabricator_read_config_file($config);
     $dictionary['phabricator.env'] = $config;
     $this->setSource(new PhabricatorConfigDictionarySource($dictionary));
 }
 protected function willRunTests()
 {
     $root = dirname(phutil_get_library_root('phabricator'));
     require_once $root . '/scripts/__init_script__.php';
     $config = $this->getComputedConfiguration();
     if ($config[self::PHABRICATOR_TESTCONFIG_ISOLATE_LISK]) {
         LiskDAO::beginIsolateAllLiskEffectsToCurrentProcess();
     }
 }
 public function render()
 {
     $user = $this->getUser();
     $trace = $this->trace;
     $libraries = PhutilBootloader::getInstance()->getAllLibraries();
     // TODO: Make this configurable?
     $path = 'https://secure.phabricator.com/diffusion/%s/browse/master/src/';
     $callsigns = array('arcanist' => 'ARC', 'phutil' => 'PHU', 'phabricator' => 'P');
     $rows = array();
     $depth = count($trace);
     foreach ($trace as $part) {
         $lib = null;
         $file = idx($part, 'file');
         $relative = $file;
         foreach ($libraries as $library) {
             $root = phutil_get_library_root($library);
             if (Filesystem::isDescendant($file, $root)) {
                 $lib = $library;
                 $relative = Filesystem::readablePath($file, $root);
                 break;
             }
         }
         $where = '';
         if (isset($part['class'])) {
             $where .= $part['class'] . '::';
         }
         if (isset($part['function'])) {
             $where .= $part['function'] . '()';
         }
         if ($file) {
             if (isset($callsigns[$lib])) {
                 $attrs = array('title' => $file);
                 try {
                     $attrs['href'] = $user->loadEditorLink('/src/' . $relative, $part['line'], $callsigns[$lib]);
                 } catch (Exception $ex) {
                     // The database can be inaccessible.
                 }
                 if (empty($attrs['href'])) {
                     $attrs['href'] = sprintf($path, $callsigns[$lib]) . str_replace(DIRECTORY_SEPARATOR, '/', $relative) . '$' . $part['line'];
                     $attrs['target'] = '_blank';
                 }
                 $file_name = phutil_tag('a', $attrs, $relative);
             } else {
                 $file_name = phutil_tag('span', array('title' => $file), $relative);
             }
             $file_name = hsprintf('%s : %d', $file_name, $part['line']);
         } else {
             $file_name = phutil_tag('em', array(), '(Internal)');
         }
         $rows[] = array($depth--, $lib, $file_name, $where);
     }
     $table = new AphrontTableView($rows);
     $table->setHeaders(array(pht('Depth'), pht('Library'), pht('File'), pht('Where')));
     $table->setColumnClasses(array('n', '', '', 'wide'));
     return phutil_tag('div', array('class' => 'exception-trace'), $table->render());
 }
 public function executeSend($body)
 {
     $key = PhabricatorEnv::getEnvConfig('amazon-ses.access-key');
     $secret = PhabricatorEnv::getEnvConfig('amazon-ses.secret-key');
     $root = phutil_get_library_root('phabricator');
     $root = dirname($root);
     require_once $root . '/externals/amazon-ses/ses.php';
     $service = newv('SimpleEmailService', array($key, $secret));
     return $service->sendRawEmail($body);
 }
 private function buildResources()
 {
     $paths = $this->getResources();
     $webroot = dirname(phutil_get_library_root('phabricator')) . '/webroot/';
     $resources = array();
     foreach ($paths as $path) {
         $resources[] = phutil_tag('style', array('type' => 'text/css'), phutil_safe_html(Filesystem::readFile($webroot . '/rsrc/' . $path)));
     }
     return phutil_implode_html("\n", $resources);
 }
 protected function willRun()
 {
     parent::willRun();
     // This stores unbounded amounts of log data; make it discard instead so
     // that daemons do not require unbounded amounts of memory.
     DarkConsoleErrorLogPluginAPI::enableDiscardMode();
     $phabricator = phutil_get_library_root('phabricator');
     $root = dirname($phabricator);
     require_once $root . '/scripts/__init_env__.php';
 }
 private function buildResources()
 {
     $css = array('application/config/config-template.css', 'application/config/setup-issue.css');
     $webroot = dirname(phutil_get_library_root('phabricator')) . '/webroot/';
     $resources = array();
     foreach ($css as $path) {
         $resources[] = phutil_tag('style', array('type' => 'text/css'), phutil_safe_html(Filesystem::readFile($webroot . '/rsrc/css/' . $path)));
     }
     return phutil_implode_html("\n", $resources);
 }
 /**
  * This is more of an acceptance test case instead of a unit test. It verifies
  * that all the library map is up-to-date.
  */
 public function testLibraryMap()
 {
     $library = phutil_get_current_library_name();
     $root = phutil_get_library_root($library);
     $new_library_map = id(new PhutilLibraryMapBuilder($root))->buildMap();
     $bootloader = PhutilBootloader::getInstance();
     $old_library_map = $bootloader->getLibraryMapWithoutExtensions($library);
     unset($old_library_map[PhutilLibraryMapBuilder::LIBRARY_MAP_VERSION_KEY]);
     $this->assertEqual($new_library_map, $old_library_map, 'The library map does not appear to be up-to-date. Try ' . 'rebuilding the map with `arc liberate`.');
 }
 private function buildParser()
 {
     // TODO: This is a little hacky beacuse we're using the Arcanist repository
     // itself to execute tests with, but it should be OK until we get proper
     // isolation for repository-oriented test cases.
     $root = dirname(phutil_get_library_root('arcanist'));
     $copy = ArcanistWorkingCopyIdentity::newFromPath($root);
     $repo = ArcanistRepositoryAPI::newAPIFromWorkingCopyIdentity($copy);
     return new ArcanistBaseCommitParser($repo);
 }
 private function getAllBuiltinFiles()
 {
     $root = dirname(phutil_get_library_root('phabricator'));
     $root = $root . '/resources/builtin/';
     $map = array();
     $list = Filesystem::listDirectory($root, $include_hidden = false);
     foreach ($list as $file) {
         $map[$file] = $root . $file;
     }
     return $map;
 }
 public function testPhutilExtensions()
 {
     $root = dirname(phutil_get_library_root('phutil'));
     $path = array($root, 'support', 'phutiltestlib');
     $path = implode(DIRECTORY_SEPARATOR, $path);
     phutil_load_library($path);
     $this->assertEqual(true, class_exists('PhutilTestClassA'));
     $this->assertEqual(true, class_exists('PhutilTestClassB'));
     $this->assertEqual(true, class_exists('PhutilTestClassC'));
     $symbols = id(new PhutilSymbolLoader())->setAncestorClass('PhutilTestClassA')->setConcreteOnly(true)->selectAndLoadSymbols();
     $this->assertEqual(2, count($symbols));
 }
Example #28
0
 protected function willRun()
 {
     parent::willRun();
     // This stores unbounded amounts of log data; make it discard instead so
     // that daemons do not require unbounded amounts of memory.
     DarkConsoleErrorLogPluginAPI::enableDiscardMode();
     $phabricator = phutil_get_library_root('phabricator');
     $root = dirname($phabricator);
     require_once $root . '/scripts/__init_env__.php';
     // Daemons may perform writes.
     AphrontWriteGuard::allowDangerousUnguardedWrites(true);
 }
 /**
  * @phutil-external-symbol class SimpleEmailService
  */
 public function executeSend($body)
 {
     $key = PhabricatorEnv::getEnvConfig('amazon-ses.access-key');
     $secret = PhabricatorEnv::getEnvConfig('amazon-ses.secret-key');
     $endpoint = PhabricatorEnv::getEnvConfig('amazon-ses.endpoint');
     $root = phutil_get_library_root('phabricator');
     $root = dirname($root);
     require_once $root . '/externals/amazon-ses/ses.php';
     $service = new SimpleEmailService($key, $secret, $endpoint);
     $service->enableUseExceptions(true);
     return $service->sendRawEmail($body);
 }
 /**
  * @phutil-external-symbol class WePay
  */
 public function processControllerRequest(PhortuneProviderController $controller, AphrontRequest $request)
 {
     $viewer = $request->getUser();
     $cart = $controller->loadCart($request->getInt('cartID'));
     if (!$cart) {
         return new Aphront404Response();
     }
     $cart_uri = '/phortune/cart/' . $cart->getID() . '/';
     $root = dirname(phutil_get_library_root('phabricator'));
     require_once $root . '/externals/wepay/wepay.php';
     WePay::useStaging($this->getWePayClientID(), $this->getWePayClientSecret());
     $wepay = new WePay($this->getWePayAccessToken());
     switch ($controller->getAction()) {
         case 'checkout':
             $return_uri = $this->getControllerURI('charge', array('cartID' => $cart->getID()));
             $cancel_uri = $this->getControllerURI('cancel', array('cartID' => $cart->getID()));
             $total_in_cents = $cart->getTotalPriceInCents();
             $price = PhortuneCurrency::newFromUSDCents($total_in_cents);
             $params = array('account_id' => $this->getWePayAccountID(), 'short_description' => 'Services', 'type' => 'SERVICE', 'amount' => $price->formatBareValue(), 'long_description' => 'Services', 'reference_id' => $cart->getPHID(), 'app_fee' => 0, 'fee_payer' => 'Payee', 'redirect_uri' => $return_uri, 'fallback_uri' => $cancel_uri, 'auto_capture' => true, 'require_shipping' => 0, 'shipping_fee' => 0, 'charge_tax' => 0, 'mode' => 'regular', 'funding_sources' => 'bank,cc');
             $result = $wepay->request('checkout/create', $params);
             // TODO: We must store "$result->checkout_id" on the Cart since the
             // user might not end up back here. Really this needs a bunch of junk.
             $uri = new PhutilURI($result->checkout_uri);
             return id(new AphrontRedirectResponse())->setIsExternal(true)->setURI($uri);
         case 'charge':
             $checkout_id = $request->getInt('checkout_id');
             $params = array('checkout_id' => $checkout_id);
             $checkout = $wepay->request('checkout', $params);
             if ($checkout->reference_id != $cart->getPHID()) {
                 throw new Exception(pht('Checkout reference ID does not match cart PHID!'));
             }
             switch ($checkout->state) {
                 case 'authorized':
                 case 'reserved':
                 case 'captured':
                     break;
                 default:
                     throw new Exception(pht('Checkout is in bad state "%s"!', $result->state));
             }
             $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
             $charge = id(new PhortuneCharge())->setAmountInCents((int) $checkout->gross * 100)->setAccountPHID($cart->getAccount()->getPHID())->setAuthorPHID($viewer->getPHID())->setPaymentProviderKey($this->getProviderKey())->setCartPHID($cart->getPHID())->setStatus(PhortuneCharge::STATUS_CHARGING)->save();
             $cart->openTransaction();
             $charge->setStatus(PhortuneCharge::STATUS_CHARGED);
             $charge->save();
             $cart->setStatus(PhortuneCart::STATUS_PURCHASED);
             $cart->save();
             $cart->saveTransaction();
             unset($unguarded);
             return id(new AphrontRedirectResponse())->setIsExternal(true)->setURI($cart_uri);
         case 'cancel':
             var_dump($_REQUEST);
             break;
     }
     throw new Exception("The rest of this isn't implemented yet.");
 }