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'; }
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)); }
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."); }