/** * Get a patch-data * * @param string $section * @param string $key * @param string $ask * @param string $default * @param string|callable $validator * @param int|false $attempts * @param bool $throwIfEmpty * @return string * @throws Exception\DomainException */ public function get($section, $key, $ask = null, $default = null, $validator = null, $attempts = 3, $throwIfEmpty = true) { if (!empty($this->data[$section][$key])) { return $this->data[$section][$key]; } if (!$this->io->isInteractive() || empty($ask)) { $result = $default; } else { $question = (string) $ask; if (null !== $default) { $question .= ' (default: <info>' . $default . '</info>)'; } $ask = static::PADDING . $question . ': '; $hidden = false; if (true === $validator) { $hidden = true; $validator = null; } if (is_string($validator) && !function_exists($validator)) { $pattern = (string) $validator; $validator = function ($value) use($pattern) { $matches = array(); if (!preg_match($pattern, $value, $matches)) { throw new LogicException(sprintf('"%s" does not match "%s"', $value, $pattern)); } return $matches[0]; }; } if (is_array($validator) && (count($validator) != 2 || !function_exists($validator))) { $values = (array) $validator; $validator = function ($value) use($values) { if (!in_array($value, $values)) { throw new LogicException(sprintf('"%s" is not available, only "%s" accepted', $value, implode('", "', $values))); } return $value; }; } if (is_callable($validator)) { $result = $this->io->askAndValidate($ask, $validator, $attempts, $default); } else { if ($hidden) { $result = $this->io->askAndHideAnswer($ask) ?: $default; } else { $result = $this->io->ask($ask, $default); } } } if (empty($result)) { if ($throwIfEmpty) { throw new Exception\DomainException(sprintf('%s: patch-data "%s": "%s", asked as "%s" should not be empty', __METHOD__, $section, $key, $ask)); } } else { $this->data[$section][$key] = $result; } return $result; }
public function __construct($version = null, IOInterface $io = null) { if ($io) { $version = $io->askAndValidate('Magento version: ', array($this, 'validateVersion'), 3); } self::validateVersion($version); $this->version = $version; $this->rootDir = dirname(dirname(__DIR__)); $this->filename = $this->rootDir . '/var/magento.tar.gz'; $this->io = $io; }
public static function start(Configuration $configuration, IOInterface $io) { $params = array(); $params['database-model'] = $io->ask("> Database model? (MYSQLI) ", "MYSQLI"); $params['database-host'] = $io->ask("> Database host? (localhost) ", "localhost"); $params['database-port'] = $io->askAndValidate("> Database port? (3306) ", function ($value) { return is_int($value); }, 3, 3306); $params['database-name'] = $io->ask("> Database name? (comodojo) ", "comodojo"); $params['database-user'] = $io->ask("> Database user? (comodojo) ", "comodojo"); $params['database-password'] = $io->askAndHideAnswer("> Database password? "); $params['database-prefix'] = $io->ask("> Common prefix for database tables? (cmdj_) ", "cmdj_"); foreach ($params as $param => $value) { $configuration->set($param, $value); } }
private static function prepareDatabase($params) { $sqlPath = __DIR__ . "/01-first-import.sql"; $sqlFile = file($sqlPath); $params['site_title'] = self::$io->askAndValidate('Title of your Website (Default: Title of new Wordpress Site): ', [self::class, 'returnValue'], null, 'Title of new Wordpress Site'); $params['admin_email'] = self::$io->askAndValidate('Admin email (Default: username@example.local): ', [self::class, 'returnValue'], null, '*****@*****.**'); $params['admin_username'] = self::$io->askAndValidate('Wordpress admin username (Default: admin): ', [self::class, 'returnValue'], null, 'admin'); $params['admin_password'] = self::$io->askAndValidate('Wordpress admin password (Default: admin): ', [self::class, 'returnValue'], null, 'admin'); $params['website_url'] = self::$io->askAndValidate('Url of the website with http:// (Default: http://wordpress.loc): ', [self::class, 'returnValue'], null, 'http://wordpress.loc'); $conn = new \mysqli($params['DB_HOST'], $params['DB_USER'], $params['DB_PASSWORD']); if ($conn->connect_error) { self::$io->write("Connection failed: " . $conn->connect_error); die; } $sql = "CREATE DATABASE IF NOT EXISTS " . $params['DB_NAME']; if ($conn->query($sql) === TRUE) { self::$io->write("Database `" . $params['DB_NAME'] . " created successfully!"); } else { self::$io->write("Error creating database `" . $params['DB_NAME'] . ": " . $conn->error); } $conn->close(); $plainSQL = ""; foreach ($sqlFile as $line_num => $line) { $line = preg_replace('#{{table_prefix}}#', $params['table_prefix'], $line); $line = preg_replace('#{{website_url}}#', $params['website_url'], $line); $line = preg_replace('#{{title-of-the-site}}#', $params['site_title'], $line); $line = preg_replace('#{{admin_email}}#', $params['admin_email'], $line); $line = preg_replace('#{{admin_password}}#', "MD5('" . $params['admin_password'] . "')", $line); $line = preg_replace('#{{admin_username}}#', $params['admin_username'], $line); $plainSQL .= $line; } $mysql_host = $params['DB_HOST']; $mysql_database = $params['DB_NAME']; $mysql_user = $params['DB_USER']; $mysql_password = $params['DB_PASSWORD']; $db = new PDO("mysql:host={$mysql_host};dbname={$mysql_database}", $mysql_user, $mysql_password); $stmt = $db->prepare($plainSQL); if ($stmt->execute()) { self::$io->write('Database query successfully executed!'); } else { self::$io->write('Database query failed!'); self::$io->write(mysqli_stmt_error($stmt)); } }
/** * Asks the user for confirmation on some action to be taken. * * @param IOInterface $io IO interface to write to console. * @param string $question * @param boolean $default Default answer * @return boolean */ protected static function confirmAction(IOInterface $io, $question, $default = true) { if (!$io->isInteractive()) { return $default; } $validator = function ($arg) { if (in_array($arg, ['Y', 'y', 'N', 'n'])) { return $arg; } throw new Exception('This is not a valid answer. Please choose Y or n.'); }; $defaultAnswer = $default ? 'Y' : 'n'; $msg = '<question>' . $question . '</question> ' . '<info>(Default to ' . $defaultAnswer . ')</info> ' . '[<comment>Y,n</comment>]: '; $answer = $io->askAndValidate($msg, $validator, 10, $defaultAnswer); if (in_array($answer, ['Y', 'y'])) { return true; } return $default; }
/** * @param string $question * @param callable $validator * @param string|null $default * @return string */ private function ask($question, callable $validator, $default = null) { return $this->io->askAndValidate($this->formatQuestion($question, $default), $validator, null, $default); }
protected function fetchKeys(IOInterface $io, Config $config) { if (!$io->isInteractive()) { throw new \RuntimeException('Public keys can not be fetched in non-interactive mode, please run Composer interactively'); } $io->write('Open <info>https://composer.github.io/pubkeys.html</info> to find the latest keys'); $validator = function ($value) { if (!preg_match('{^-----BEGIN PUBLIC KEY-----$}', trim($value))) { throw new \UnexpectedValueException('Invalid input'); } return trim($value) . "\n"; }; $devKey = ''; while (!preg_match('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $devKey, $match)) { $devKey = $io->askAndValidate('Enter Dev / Snapshot Public Key (including lines with -----): ', $validator); while ($line = $io->ask('')) { $devKey .= trim($line) . "\n"; if (trim($line) === '-----END PUBLIC KEY-----') { break; } } } file_put_contents($keyPath = $config->get('home') . '/keys.dev.pub', $match[0]); $io->write('Stored key with fingerprint: ' . Keys::fingerprint($keyPath)); $tagsKey = ''; while (!preg_match('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $tagsKey, $match)) { $tagsKey = $io->askAndValidate('Enter Tags Public Key (including lines with -----): ', $validator); while ($line = $io->ask('')) { $tagsKey .= trim($line) . "\n"; if (trim($line) === '-----END PUBLIC KEY-----') { break; } } } file_put_contents($keyPath = $config->get('home') . '/keys.tags.pub', $match[0]); $io->write('Stored key with fingerprint: ' . Keys::fingerprint($keyPath)); $io->write('Public keys stored in ' . $config->get('home')); }
/** * Asks for the project name * * @param IOInterface $io * * @return string */ private static function getProjectName(IOInterface $io) { $io->write(["<fg=cyan>Project name</fg=cyan>", "You need to set a project name before using the application.", "The project name can not be empty, must contain a letter, may only contain lower case letters (a-z) and underscores.", ""]); return $io->askAndValidate("Project name: ", [self::class, "isValidPackageName"]); }
/** * @param Event $event */ public static function install(Event $event) { self::configureIo($event->getIO()); self::$io->write(sprintf('<magenta>%s</magenta>', self::$logo)); self::$io->write(""); // Get composer.json $composerFile = Factory::getComposerFile(); $json = new JsonFile($composerFile); self::$composerDefinition = $json->read(); self::$io->write("<info>Setting up Workshop!</info>"); // Get root package $rootPackage = $event->getComposer()->getPackage(); while ($rootPackage instanceof AliasPackage) { $rootPackage = $rootPackage->getAliasOf(); } $composerName = self::$io->askAndValidate("\n <magenta> Name for composer package (eg php-school/learn-you-php)? </magenta> ", function ($answer) { if (!preg_match('/[a-z0-9-]+\\/[a-z0-9-]+/', $answer)) { throw new Exception('Package name must be in the form: vendor/package. Lowercase, alphanumerical, may include dashes and be must slash separated.'); } return $answer; }, 3); $projectTitle = self::$io->ask("\n <magenta> Workshop title? </magenta> "); $projectDescription = self::$io->ask("\n <magenta> Workshop description? </magenta> "); $namespace = self::$io->askAndValidate("\n <magenta> Namespace for Workshop (eg PhpSchool\\LearnYouPhp)? </magenta> ", function ($answer) { if (!preg_match('/^(\\\\{1,2})?\\w+\\\\{1,2}(?:\\w+\\\\{0,2})+$/', $answer)) { throw new Exception('Package name must be a valid PHP namespace'); } return $answer; }, 3); self::$binaryName = self::$io->askAndValidate("\n <magenta> Binary name (program users will run, eg learnyouphp)? </magenta> ", function ($answer) { if (!preg_match('/[a-z0-9-]+/', $answer)) { throw new Exception('Binary name must lowercase, alphanumerical and can include dashed'); } return $answer; }); self::$io->write(''); self::runTask('Configuring project name and description', function () use($composerName, $projectDescription, $projectTitle) { self::$composerDefinition['name'] = $composerName; self::$composerDefinition['description'] = $projectDescription; $bootstrap = file_get_contents(__DIR__ . '/../../app/bootstrap.php'); $bootstrap = str_replace('___PROJECT_TITLE___', $projectTitle, $bootstrap); file_put_contents(__DIR__ . '/../../app/bootstrap.php', $bootstrap); }); self::runTask('Configuring autoload and namespaces', function () use($namespace) { self::$composerDefinition['autoload']['psr-4'][sprintf('%s\\', trim($namespace, '\\'))] = 'src/'; self::$composerDefinition['autoload-dev']['psr-4'][sprintf('%sTest\\', trim($namespace, '\\'))] = 'test'; }); self::runTask('Updating binary config', function () { self::$composerDefinition['bin'] = [sprintf('bin/%s', self::$binaryName)]; rename(__DIR__ . '/../../bin/my-workshop', __DIR__ . '/../../bin/' . self::$binaryName); }); self::runTask('Removing dev dependencies', function () { foreach (self::$devDependencies as $devDependency) { unset(self::$composerDefinition['require-dev'][$devDependency]); } }); self::runTask('Removing installer autoload and script config', function () { unset(self::$composerDefinition['scripts']['pre-update-cmd']); unset(self::$composerDefinition['scripts']['pre-install-cmd']); unset(self::$composerDefinition['scripts']['post-update-cmd']); unset(self::$composerDefinition['scripts']['post-install-cmd']); if (empty(self::$composerDefinition['scripts'])) { unset(self::$composerDefinition['scripts']); } unset(self::$composerDefinition['autoload']['psr-4']['WorkshopCreator\\']); }); self::runTask('Writing Composer.json file', function () use($json) { $json->write(self::$composerDefinition); }); self::runTask('Removing Workshop installer classes', function () { self::recursiveRmdir(__DIR__); }); }