protected function _populateRecordsForModel($modelName) { Garp_Cli::lineOut("Updating model " . $modelName, Garp_Cli::YELLOW); $model = $this->_getModel($modelName); $i18nModel = $model->getObserver('Translatable')->getI18nModel($model); $foreignKeyColumns = $this->_getForeignKeyColumns($i18nModel, $model); // Trigger an update on the record and let Translatable behavior do the work $records = $this->_fetchRecordsInDefaultLanguage($model); foreach ($records as $record) { $foreignKeyWhereClause = $this->_getForeignKeyWhereClause($record, $model, $foreignKeyColumns); $fkValue = $record[$foreignKeyColumns[0]]; unset($record[$foreignKeyColumns[0]]); $updateData = array_map(function ($value) { return array(Garp_I18n::getDefaultLocale() => $value); }, $record->toArray()); unset($updateData['slug']); // Bit of a hack but if we only select multilingual fields Translatable will strip 'em // out and leave an empty UPDATE statement. Put id in there to give UPDATE statement // some body. $updateData['id'] = $fkValue; // Update with existing data. Translatable should pick up and populate other-language // records where applicable. try { $model->update($updateData, $foreignKeyWhereClause); } catch (Garp_Model_Validator_Exception $e) { Garp_Cli::errorOut('Could not update record ' . $updateData['id'] . ' because of exception:'); Garp_Cli::errorOut($e->getMessage()); } } Garp_Cli::lineOut('Done.'); }
public function remap() { $service = $this->getService(); $status = $service->remap(); $status ? Garp_Cli::lineOut('Index remapped.', Garp_Cli::BLUE) : Garp_Cli::errorOut('Could not remap index.'); return true; }
/** * Minify assets * * @param array $args * @return bool */ public function minifyJs(array $args = array()) { $ini = Zend_Registry::get('config'); if (empty($ini->assets->js)) { Garp_Cli::errorOut("You do not have a valid asset configuration specified in application.ini.\n" . "Configure like this:\n" . 'assets.js.main_js.filename = "main.min.js"' . "\n" . 'assets.js.main_js.sourcefiles[] = "libs/myplugin.js"' . "\n" . 'assets.js.main_js.sourcefiles[] = "main.js"' . "\n" . "This will combine libs/myplugin.js and main.js into main.min.js."); return false; } $jsRoot = ltrim($ini->assets->js->basePath ?: 'js', '/'); $assets = $ini->assets->js->toArray(); unset($assets['basePath']); $selectedKey = null; if (!empty($args)) { $selectedKey = $args[0]; } foreach ($assets as $key => $assetSettings) { if (!is_null($selectedKey) && $key != $selectedKey) { continue; } if (empty($assetSettings['sourcefiles']) || empty($assetSettings['filename'])) { Garp_Cli::errorOut($key . ' is not configured correctly. "sourcefiles" and "filename" are required keys.'); return false; } $minifier = new Garp_Assets_Minifier(APPLICATION_PATH . '/../public/' . $jsRoot); $minifier->minifyJs($assetSettings['sourcefiles'], $assetSettings['filename']); } Garp_Cli::lineOut('Done.'); return true; }
public function _openConnection($environment) { $config = new Garp_Deploy_Config(); $params = $config->getParams($environment); if (!$params) { Garp_Cli::errorOut('No settings found for environment ' . $environment); } if (empty($params['server'])) { Garp_Cli::errorOut("'server' is a required setting."); return false; } // To provide a bit of backward-compatibility, convert to array if (!is_array($params['server'])) { $params['server'] = array(array('server' => $params['server'], 'user' => $params['user'])); } if (count($params['server']) === 1) { $this->_executeSshCommand($params['server'][0]['server'], $params['server'][0]['user']); return true; } $choice = Garp_Cli::prompt("Choose a server to use: \n" . array_reduce($params['server'], function ($output, $server) { $number = count(explode("\n", $output)); $output .= "{$number}) {$server['server']}\n"; return $output; }, '')); if (!array_key_exists($choice - 1, $params['server'])) { Garp_Cli::errorOut('Invalid choice: ' . $choice); return false; } $this->_executeSshCommand($params['server'][$choice - 1]['server'], $params['server'][$choice - 1]['user']); }
/** * Post a message in a Slack channel * * @param array $args * @return bool */ public function send(array $args = array()) { if (!$args || !array_key_exists(0, $args) || empty($args[0])) { Garp_Cli::errorOut(self::ERROR_EMPTY_SEND); return false; } $slack = new Garp_Service_Slack(); return $slack->postMessage($args[0]); }
public function track($args) { if (empty($args)) { Garp_Cli::errorOut('No release version provided.'); return false; } $branch = $args[0]; passthru('git flow release track ' . $branch); return true; }
public function main(array $args = array()) { $domain = isset(Zend_Registry::get('config')->app->domain) ? Zend_Registry::get('config')->app->domain : null; if (!$domain) { Garp_Cli::errorOut('No domain found. Please configure app.domain'); return false; } `open http://{$domain}`; return true; }
public function track($args) { if (empty($args)) { Garp_Cli::errorOut('No feature name provided.'); return false; } $branch = $args[0]; $git_flow_feature_publish_cmd = 'git flow feature track ' . $branch; passthru($git_flow_feature_publish_cmd); return true; }
/** * Display a figlet * * @param array $args * @return bool */ public function display(array $args = array()) { if (empty($args)) { Garp_Cli::errorOut('The least you can do is provide a text...'); } else { $text = implode(' ', $args); $figlet = new Zend_Text_Figlet(); Garp_Cli::lineOut($figlet->render($text)); } return true; }
/** * Set and/or create profile in awscmd. * Also check wether this project actually uses Amazon. * * @param array $args * @return bool */ public function main(array $args = array()) { if (!$this->_usesAmazon()) { Garp_Cli::errorOut('Clearly this environment does not ' . 'use Amazon services. Get outta here!'); return false; } $this->_setProfile(); if (!$this->_profileExists()) { $this->_createProfile(); } return parent::main($args); }
public function delete(array $args = array()) { if (empty($args)) { Garp_Cli::errorOut('No email address given. See g Ses help for help.'); return false; } $email = $args[0]; $ses = new Garp_Service_Amazon_Ses(); $ses->deleteVerifiedEmailAddress($email); Garp_Cli::lineOut('Done.'); return true; }
/** * Generate the slugs * * @param array $args * @return bool */ public function generate(array $args = array()) { if (empty($args)) { $this->help(); return false; } $modelName = $args[0]; if (strpos($modelName, '_') === false) { $modelName = 'Model_' . $modelName; } $overwrite = !empty($args[1]) ? $args[1] : false; $model = new $modelName(); // No reason to cache queries. Use live data. $model->setCacheQueries(false); // Fetch Sluggable thru the model as to use the right slug-configuration list($sluggable, $model) = $this->_resolveSluggableBehavior($model); if (is_null($sluggable)) { Garp_Cli::errorOut('This model is not sluggable.'); return false; } // Array to record fails $fails = array(); $records = $model->fetchAll(); foreach ($records as $record) { if (!$overwrite && $record->slug) { continue; } // Mimic a beforeInsert to create the slug in a separate array $data $args = array($model, $record->toArray()); $sluggable->beforeInsert($args); // Since there might be more than one changed column, we use this loop // to append those columns to the record foreach ($args[1] as $key => $value) { if ($value != $record->{$key}) { $record->{$key} = $value; } } // Save the record with its slug if (!$record->save()) { $pk = implode(', ', (array) $record->getPrimaryKey()); $fails[] = $pk; } } Garp_Cli::lineOut('Done.'); if (count($fails)) { Garp_Cli::errorOut('There were some failures. ' . 'Please perform a manual check on records with the following primary keys:'); Garp_Cli::lineOut(implode("\n-", $fails)); } return true; }
protected function _update() { Garp_Cli::lineOut('Current Capistrano setup of this project:'); $version = $this->_getCurrentCapVersion(); if (!$version) { Garp_Cli::errorOut('No Capistrano setup found in ' . getcwd()); return false; } if ($version === 3) { Garp_Cli::errorOut('Setup is already suited for Capistrano 3.'); return false; } if ($version === 2) { Garp_Cli::lineOut('Capistrano 2 setup found, attempting update.'); return $this->_updateVersionSteps(); } return true; }
public function restore($args = array()) { $mem = new Garp_Util_Memory(); $mem->useHighMemory(); $version = new Garp_Semver(); Garp_Cli::lineOut('Restoring gumball ' . $version, Garp_Cli::PURPLE); $gumball = new Garp_Gumball($version); try { $gumball->restore(); $this->_broadcastGumballInstallation($version); Garp_Cli::lineOut('Done!', Garp_Cli::GREEN); } catch (Garp_Gumball_Exception_SourceEnvNotConfigured $e) { Garp_Cli::errorOut(self::ERROR_SOURCE_ENV_NOT_CONFIGURED); return false; } catch (Exception $e) { Garp_Cli::errorOut('Error: ' . $e->getMessage()); return false; } return true; }
public function rm(array $args = array()) { if (empty(Zend_Registry::get('config')->cdn->s3->bucket)) { Garp_Cli::errorOut('No bucket configured'); return false; } if (empty($args)) { Garp_Cli::errorOut('No path given.'); return false; } $path = rtrim('s3://' . Zend_Registry::get('config')->cdn->s3->bucket, DIRECTORY_SEPARATOR); if (isset($args[0])) { $path .= DIRECTORY_SEPARATOR . $args[0]; } if (!Garp_Cli::confirm('Are you sure you want to permanently remove ' . $path . '?')) { Garp_Cli::lineOut('Changed your mind, huh? Not deleting.'); return true; } $args = array($path); return $this->s3('rm', $args); }
/** * Central start method * * @param array $args * @return bool */ public function main(array $args = array()) { if (1 === count($args) && !empty($args[0]) && 'help' === strtolower($args[0])) { $this->help(); return true; } // check for illegal options $allowedArgs = array('module', 'group'); foreach ($args as $key => $value) { if (!in_array($key, $allowedArgs)) { Garp_Cli::errorOut('Illegal option ' . $key); Garp_Cli::lineOut('Type \'g Test help\' for usage'); return false; } } $command = $this->_command; if (!empty($args['group'])) { $command .= '--group=' . $args['group'] . ' '; } if (array_key_exists('module', $args) && $args['module']) { if ($args['module'] === 'garp') { $path = $this->_garpPath; $command .= '--bootstrap vendor/grrr-amsterdam/garp3/tests/TestHelper.php '; $command .= $path; } elseif ($args['module'] === 'default') { $path = $this->_appPath; $command .= '--bootstrap tests/TestHelper.php '; $command .= $path; } else { throw new Exception("Only 'garp' and 'default' are valid configurable " . "modules for the test environment."); } } else { $command .= '--bootstrap tests/TestHelper.php '; $command .= $this->_appPath . ' && ' . $command . $this->_garpPath; } system($command, $returnValue); return $returnValue; }
/** * Interactively insert a new record * * @param array $args * @return bool */ public function insert($args) { if (empty($args)) { Garp_Cli::errorOut('Please provide a model'); return false; } $className = "Model_{$args[0]}"; $model = new $className(); $fields = $model->getConfiguration('fields'); $fields = array_filter($fields, not(propertyEquals('name', 'id'))); $mode = $this->_getInsertionMode(); if ($mode === 'g') { $newData = $this->_createGibberish($fields); } else { $newData = array_reduce($fields, function ($acc, $cur) { $acc[$cur['name']] = Garp_Cli::prompt($cur['name']) ?: null; return $acc; }, array()); } $id = $model->insert($newData); Garp_Cli::lineOut("Record created: #{$id}"); return true; }
/** * Distributes the public assets on the local server to the configured CDN servers. * * @param array $args * @return void */ public function distribute(array $args) { $filterString = $this->_getFilterString($args); $filterDate = $this->_getFilterDate($args); $filterEnvironments = $this->_getFilterEnvironments($args); $isDryRun = $this->_getDryRunParam($args); $assetList = $this->_distributor->select($filterString, $filterDate); if (!$assetList) { Garp_Cli::errorOut("No files to distribute."); return; } $assetCount = count($assetList); $summary = $assetCount === 1 ? $assetList[0] : $assetCount . ' assets'; $filterDateLabel = $this->_getFilterDateLabel($filterDate, $assetList); $summary .= " since {$filterDateLabel}."; Garp_Cli::lineOut("Distributing {$summary}\n"); if ($isDryRun) { Garp_Cli::lineOut(implode("\n", (array) $assetList)); return; } foreach ($filterEnvironments as $env) { $this->_distributor->distribute($env, $assetList, $assetCount); } }
/** * Force user to confirm a question with yes or no. * * @param string $msg Question or message to display. A prompt (>) will be added. * @return bool Returns true if answer was 'y' or 'Y', no enter needed. */ public static function confirm($msg) { print $msg . ' > '; system('stty -icanon'); $handle = fopen('php://stdin', 'r'); $char = fgetc($handle); system('stty icanon'); print "\n"; $allowedResponses = array('y', 'Y', 'n', 'N'); if (!in_array($char, $allowedResponses)) { // nag 'em some more Garp_Cli::errorOut('Please respond with a clear y or n'); return static::confirm($msg); } return $char === 'y' || $char === 'Y'; }
/** * Replace $subject with $replacement in all textual columns of the table. * * @param string $modelClass The model classname * @param string $subject The string that is to be replaced * @param string $replacement The string that will take its place * @return void */ protected function _replaceString($modelClass, $subject, $replacement) { $model = new $modelClass(); $columns = $this->_getTextualColumns($model); if ($columns) { $adapter = $model->getAdapter(); $updateQuery = 'UPDATE ' . $adapter->quoteIdentifier($model->getName()) . ' SET '; foreach ($columns as $i => $column) { $updateQuery .= $adapter->quoteIdentifier($column) . ' = REPLACE('; $updateQuery .= $adapter->quoteIdentifier($column) . ', '; $updateQuery .= $adapter->quoteInto('?, ', $subject); $updateQuery .= $adapter->quoteInto('?)', $replacement); if ($i < count($columns) - 1) { $updateQuery .= ','; } } if ($response = $adapter->query($updateQuery)) { $affectedRows = $response->rowCount(); Garp_Cli::lineOut('Model: ' . $model->getName()); Garp_Cli::lineOut('Affected rows: ' . $affectedRows); Garp_Cli::lineOut('Involved columns: ' . implode(', ', $columns) . "\n"); } else { Garp_Cli::errorOut('Error: update for table `' . $model->getName() . '` failed.'); } } }
public function displayError($string) { return Garp_Cli::errorOut($string); }
/** * Make sure the method is not inadvertently called with the * wrong arguments. This might indicate the user made a mistake * in calling it. * * @param string $methodName * @param array $args * @return bool */ protected function _validateArguments($methodName, $args) { if (!array_key_exists($methodName, $this->_allowedArguments) || $this->_allowedArguments[$methodName] === '*') { return true; } $unknownArgs = array_diff(array_keys($args), $this->_allowedArguments[$methodName]); if (!count($unknownArgs)) { return true; } // Report the first erroneous argument $errorStr = current($unknownArgs); // Show the value of the argument if the index is numeric if (is_numeric($errorStr)) { $errorStr = $args[$unknownArgs[0]]; } Garp_Cli::errorOut('Unexpected argument ' . $errorStr); return false; }
protected function _validateSyncArguments(array $args) { $valid = false; $argCount = count($args); if (!array_key_exists(0, $args)) { Garp_Cli::errorOut("No source environment provided."); } elseif (!array_key_exists(1, $args)) { Garp_Cli::errorOut("No target environment provided."); } elseif (!in_array($args[0], $this->_environments)) { Garp_Cli::errorOut("Source environment is invalid. Try: " . Garp_Util_String::humanList($this->_environments, null, 'or') . '.'); } elseif (!in_array($args[1], $this->_environments)) { Garp_Cli::errorOut("Target environment is invalid. Try: " . Garp_Util_String::humanList($this->_environments, null, 'or') . '.'); } else { $valid = true; } if (!$valid) { $this->help(); return false; } return true; }
protected function _validateArgs(array $args) { if (!$this->_isFirstArgumentGiven($args)) { return true; } $error = sprintf(self::ERROR_UNKNOWN_ARGUMENT, $args[0]); Garp_Cli::errorOut($error); return false; }
protected function _update($snippetData, $snippetID) { $this->_validateLoadable(); $snippetModel = new Model_Snippet(); try { $snippetModel->update($snippetData, "id = {$snippetID}"); $snippet = $snippetModel->fetchRow($snippetModel->select()->where('id = ?', $snippetID)); return $snippet; } catch (Garp_Model_Validator_Exception $e) { Garp_Cli::errorOut($e->getMessage()); } }
protected function _printError($message) { Garp_Cli::errorOut($message); Garp_Cli::lineOut(""); }
protected function _scaleDatabaseImage(Garp_Db_Table_Row $record, Garp_Image_File $file, Garp_Image_Scaler $scaler, $template, $overwrite) { $id = $record->id; $filename = $record->filename; if (!$file->exists($filename)) { Garp_Cli::errorOut('Warning: ' . $filename . ' is in the database, but not on disk!'); return; } if ($file->exists($scaler->getScaledPath($id, $template, true)) && !$overwrite) { Garp_Cli::lineOut($template . '/' . $id . ' already exists, skipping'); return; } try { $scaler->scaleAndStore($filename, $id, $template, $overwrite); Garp_Cli::lineOut('Scaled image #' . $id . ': ' . $filename); return true; } catch (Exception $e) { Garp_Cli::errorOut("Error scaling " . $filename . " (#" . $id . "): " . $e->getMessage()); } }
$commandNames = array_map(function ($ns) use($classArgument) { return $ns . '_Cli_Command_' . $classArgument; }, $namespaces); $commandNames = array_filter($commandNames, 'class_exists'); // Remove the command name from the argument list $args = array_splice($args, 1); if (!count($commandNames)) { Garp_Cli::errorOut('Silly developer. This is not the command you\'re looking for.'); // @codingStandardsIgnoreStart exit(1); // @codingStandardsIgnoreEnd } $commandName = current($commandNames); $command = new $commandName(); if (!$command instanceof Garp_Cli_Command) { Garp_Cli::errorOut('Error: ' . $commandName . ' is not a valid Command. ' . 'Command must implement Garp_Cli_Command.'); // @codingStandardsIgnoreStart exit(1); // @codingStandardsIgnoreEnd } // Since localisation is based on a URL, and URLs are not part of a commandline, no // translatation is loaded. But we might need it to convert system messages. $commandsWithoutTranslation = array('Spawn', 'Config', 'Gumball', 'Feature', 'Hotfix', 'Release', 'Flow', 'Cdn', 'Ssh', 'Aws', 'Config', 'Figlet', 'Folders', 'Git', 'Open', 'S3', 'Ses', 'Shell', 'Slack'); if (!in_array($classArgument, $commandsWithoutTranslation)) { if (!Zend_Registry::isRegistered('Zend_Translate') && Zend_Registry::isRegistered('Zend_Locale')) { Zend_Registry::set('Zend_Translate', Garp_I18n::getTranslateByLocale(Zend_Registry::get('Zend_Locale'))); } } $command->main($args); // @codingStandardsIgnoreStart exit(0);
protected function _setErrorHandler() { set_error_handler(function ($errno, $errstr, $errfile, $errline) { $errTypes = array(E_USER_ERROR => 'Error', E_USER_WARNING => 'Warning', E_USER_NOTICE => 'Notice'); $errType = isset($errTypes[$errno]) ? $errTypes[$errno] : 'Unknown error'; Garp_Cli::errorOut("{$errType}: {$errstr}"); Garp_Cli::lineOut(" from {$errfile}:{$errline}", Garp_Cli::BLUE); }); }
/** * Check if semver and git flow are installed * * @return bool */ protected function _required_tools_available() { $semver_checker = shell_exec('which semver'); if (empty($semver_checker)) { Garp_Cli::errorOut('semver is not installed'); Garp_Cli::lineOut('Install like this:'); Garp_Cli::lineOut(' gem install semver', Garp_Cli::BLUE); return false; } /* @todo REFACTOR LATER! Check fails on Ubuntu? $gitflow_checker = shell_exec('which git-flow'); if (empty($gitflow_checker)) { Garp_Cli::errorOut('git-flow is not installed'); Garp_Cli::lineOut('Get it from brew'); Garp_Cli::lineOut(' brew install git-flow', Garp_Cli::BLUE); return false; } */ return true; }