/** * Serve nginx site configuration file as html * * @param string $filename Name of the nginx site file (without path). * @return void */ public function file($filename) { $content = CakeboxUtility::getFileContent("/etc/nginx/sites-available/{$filename}"); if (!$content) { throw new NotFoundException(); } $this->set(['content' => $content, '_serialize' => ['content']]); }
/** * Install a software package from the Ubuntu Package archive. * * @param string $package Name of package to install as used by `apt-get install`. * @return void */ public function add($package) { $this->logStart("Please wait... installing apt package {$package}"); if (CakeboxUtility::packageInstalled($package)) { $this->exitBashWarning("* Skipping: package already installed"); } if (!$this->Execute->installPackage($package)) { $this->exitBashError('Error installing package.'); } $this->exitBashSuccess("Package installed successfully."); }
/** * Remove/drop a database and related test-database. * * @param string $database Name of main database. * @return void */ public function remove($database) { $this->logStart("Dropping databases {$database} and test_{$database}"); if (!CakeboxUtility::databaseExists($database)) { $this->exitBashWarning("* Skipping: database does not exist."); } if (CakeboxUtility::dropDatabase($database) == false) { $this->exitBashError("Error dropping databases"); } $this->exitBashSuccess("Databases dropped successfully"); }
/** * Box-fix: composer update globally installed cakephp-codesniffer * by updating version in composer.json (if needed) and then running * composer update. * * @return boolean True on success */ protected function _updateCakephpCodeSniffer() { $this->logInfo('Updating CakePHP Code Sniffer'); // update package version in composer.json to 2.* $path = '/opt/composer-libraries/cakephp_codesniffer'; $requiredVersion = '2.*'; $result = CakeboxUtility::updateConfigFile("{$path}/composer.json", ['2.*@dev' => '2.*'], true); // composer update CakePHP Coding Standard $this->logInfo('* Composer updating'); $command = "composer update --no-dev --working-dir {$path}"; if (!$this->Execute->shell($command, 'root')) { return false; } return true; }
/** * Turn cakebox-console debug mode on/off by replacing value in app.php. * * @param string $mode String containing either 'on' or 'off' * @return boolean True on success */ public function debug($mode) { $appConfig = '/cakebox/console/config/app.php'; // enable debug mode if ($mode === 'on') { $this->out("Enabling Cakebox debug mode"); if (!CakeboxUtility::updateConfigFile($appConfig, ["'debug' => false" => "'debug' => true"])) { $this->exitBashError("Error enabling Cakebox debug mode."); } $this->exitBashSuccess("Command completed successfully"); return true; } // disable debug mode $this->out("Disabling Cakebox debug mode"); if (!CakeboxUtility::updateConfigFile($appConfig, ["'debug' => true" => "'debug' => false"])) { $this->exitBashError("Error disabling Cakebox debug mode."); } $this->exitBashSuccess("Command completed successfully"); return true; }
/** * Convenience function to update all required CakePHP2 configuration files. * * @param string $appdir Full path to the application directory (APP). * @param string $url FQDN used to expose the application. * @return boolean True if the file was updated successfully */ public function updateCake2Configuration($appdir, $url) { # Update salt/cipher in core.php $this->_log("Updating core.php"); $coreFile = $appdir . DS . "app" . DS . "Config" . DS . "core.php"; $res = CakeboxUtility::updateConfigFile($coreFile, [$this->Info->frameworkMeta['cakephp2']['salt'] => CakeboxUtility::getSaltCipher($coreFile), $this->Info->frameworkMeta['cakephp2']['cipher'] => CakeboxUtility::getSaltCipher($coreFile)]); if (!$res) { $this->_error("Error updating core file"); return false; } // create database.php $dbFileSource = $appdir . DS . "app" . DS . "Config" . DS . "database.php.default"; $dbFileTarget = $appdir . DS . "app" . DS . "Config" . DS . "database.php"; if (!file_exists($dbFileTarget)) { copy($dbFileSource, $dbFileTarget); $this->_log("Created database file `{$dbFileTarget}`"); } # update database.php $this->_log("Updating database.php"); $database = CakeboxUtility::normalizeDatabaseName($url); $result = CakeboxUtility::updateConfigFile($dbFileTarget, ['test_database_name' => 'test_' . $database, 'database_name' => $database, 'user' => 'cakebox', "'password' => 'password'" => "'password' => 'secret'"]); if (!$result) { $this->_error("Error updating database file"); return false; } # Enable debugkit in bootstrap.php $this->_log("Enabling DebugKit"); $bootstrapFile = $appdir . DS . "app" . DS . "Config" . DS . "bootstrap.php"; $fh = new File($bootstrapFile); $fh->append('CakePlugin::loadAll();'); return true; }
/** * Set permissions on writebale directories for known frameworks. * * @return boolean True if permissions were skipped OR set succesfully * @throws Cake\Core\Exception\Exception */ public function setPermissions() { Log::debug("Updating directory permissions"); # Skip if no framework was detected if (!isset($this->options['framework_short'])) { Log::debug("* Skipping: unsupported/empty framework"); return true; } # Skip if the framework does not use writable directories if (!isset($this->Info->frameworkMeta[$this->options['framework_short']]['writable_dirs'])) { Log::debug("* Skipping: framework does not use writeable directories"); return true; } # Set permissions Log::debug("* Applying " . $this->options['framework_short'] . " folder permissions"); foreach ($this->Info->frameworkMeta[$this->options['framework_short']]['writable_dirs'] as $directory) { if (!CakeboxUtility::setFolderPermissions($this->options['path'] . DS . $directory)) { throw new Exception("Error setting permissions."); } } return true; }
/** * Get the common framework name used by an application by concatenating it's * framework name and major version (e.g. cakephp2, cakephp3, laravel4) * * @param string $appdir Full path to the application's root directory. * @return array|bool Single dimensional array with key/value pair collections, false on fails */ public function getFrameworkCommonName($appdir) { $framework = $this->getFrameworkName($appdir); $majorVersion = CakeboxUtility::getMajorVersion($this->getFrameworkVersion($appdir)); return $framework . $majorVersion; }
/** * Install and configure a PHP framework application using Nginx and MySQL. * * @param string $url Fully Qualified Domain Name used to expose the site. * @return void */ public function add($url) { if ($this->params['repair']) { $this->logStart("Repairing application http://{$url}"); } else { $this->logStart("Creating application http://{$url}"); } if ($url == 'default') { $this->exitBashError("Cannot use 'default' as <url> as this would overwrite the default Cakebox site."); } # Feed the installer with all required information $installer = new CakeboxFrameworkInstaller(); $this->out('Configuring installer'); if (!$installer->setup(array_merge(['url' => $url], $this->params))) { $this->exitBashError('Error setting up installer.'); } # Check: custom applications require the --webroot option to prevent # generating an invalid Nginx vhost preventing Nginx reload and thus # breaking yaml-provisioning if ($installer->option('framework_short') === 'custom' && !isset($this->params['webroot'])) { $this->exitBashError('Error: custom applications require the --webroot parameter'); } # Only method-detect if target dir is available once (present and/or empty) $targetDirAvailable = CakeboxUtility::dirAvailable($installer->option('path')); # Check: stop provisioning if the target directory is not # available/empty AND and we are not in --repair mode if (!$targetDirAvailable && !$this->params['repair']) { $this->exitBashError('Error: target directory ' . $installer->option('path') . ' contains data'); } # ------------------------------------------------------------ # Create installation directory if needed # ------------------------------------------------------------ $dirHasData = false; $this->out('Creating installation directory'); if (!$targetDirAvailable) { $dirHasData = true; $this->out('* Skipping: target directory contains data'); } if ($targetDirAvailable && is_dir($installer->option('path'))) { $this->out('* Skipping: directory already created'); } if (!$targetDirAvailable && !$dirHasData) { if (!$this->Execute->mkVagrantDir($installer->option('path'))) { $this->exitBashError('Error creating target directory ' . $installer->option('path')); } } # ------------------------------------------------------------ # Install sources if needed # ------------------------------------------------------------ if (!$dirHasData) { $this->out(Inflector::camelize($installer->option('installation_method')) . ' installing ' . $installer->option('framework_human') . ' application sources'); if (!$installer->installSources()) { $this->exitBashError('Error installing application sources.'); } } if (!$dirHasData && $installer->option('installation_method') !== 'composer') { if (file_exists($installer->option('path') . DS . 'composer.json')) { $this->logInfo('Composer installing detected composer.json'); if (!$this->Execute->composerInstall($installer->option('path'))) { $this->exitBashError('Error Composer installing detected composer.json.'); } } } # ------------------------------------------------------------ # Create Nginx virtual host if needed # ------------------------------------------------------------ $this->out('Creating virtual host'); if ($this->params['hhvm']) { $vhostType = 'HHVM'; } else { $vhostType = 'PHP-FPM'; } // remove existing (assumed orphaned) vhost when not in --repair mode if (CakeboxUtility::vhostAvailable($url) && !$this->params['repair']) { $this->out('* Removing existing (assumed orphaned) virtual host'); if (!$this->Execute->removeVhost($url)) { $this->exitBashError('Error removing virtual host'); } } $vhostAvailable = CakeboxUtility::vhostAvailable($url); $vhostEnabled = CakeboxUtility::vhostEnabled($url); if ($vhostAvailable && $vhostEnabled) { $this->out("* Skipping: {$vhostType} virtual host already up and running"); } if ($vhostAvailable && !$vhostEnabled) { $this->out('* Skipping: configuration file already exists'); } if (!$vhostAvailable) { if (!$this->Execute->addVhost($url, $installer->option('webroot'), ['force' => true, 'hhvm' => $this->params['hhvm']])) { $this->exitBashError("Error creating {$vhostType} virtual host"); } $this->out("* Successfully created {$vhostType} virtual host"); } // recheck symlink since it could have been created above if (!CakeboxUtility::vhostEnabled($url)) { $this->out('* Enabling virtual host'); if (!$this->Execute->enableVhost($url)) { $this->exitBashError('Error creating symbolic link'); } if (!$this->Execute->reloadNginx()) { $this->exitBashError('Error reloading Nginx'); } } # ------------------------------------------------------------ # Create databases if needed # ------------------------------------------------------------ $this->out('Creating databases'); $mainDatabase = $installer->option('database'); $testDatabase = $this->Info->databaseMeta['test_prefix'] . $installer->option('database'); // remove existing (assumed orphaned) databases when not in --repair mode if (CakeboxUtility::databaseExists($mainDatabase) && !$this->params['repair']) { $this->out('* Removing existing (assumed orphaned) databases'); if (!CakeboxUtility::dropDatabase($mainDatabase)) { $this->exitBashError("Error dropping main database {$mainDatabase}"); } if (!CakeboxUtility::dropDatabase($testDatabase)) { $this->exitBashError("Error dropping test database {$testDatabase}"); } } if (CakeboxUtility::databaseExists($mainDatabase)) { $this->out('* Skipping: main database already exists'); } else { if (!CakeboxUtility::createDatabase($mainDatabase, 'cakebox', 'secret', true)) { $this->exitBashError('Error creating main database'); } else { $this->out('* Successfully created main database'); } } if (CakeboxUtility::databaseExists($testDatabase)) { $this->out('* Skipping: test database already exists'); } else { if (!CakeboxUtility::createDatabase($testDatabase, 'cakebox', 'secret', true)) { $this->exitBashError('Error creating test database'); } else { $this->out('* Successfully created test database'); } } # ------------------------------------------------------------ # Configure permissions (for supported frameworks only) # ------------------------------------------------------------ $this->out('Configuring permissions'); if (!$installer->setPermissions()) { $this->exitBashError('Error setting permissions'); } # ------------------------------------------------------ # Only update config files when not in --repair mode # ------------------------------------------------------ $this->out('Updating configuration files'); if ($this->params['repair']) { $this->out('* Skipping: configuration files are not updated in --repair mode'); } else { if (!$installer->updateConfigs()) { $this->exitBashError('Error updating configuration file(s)'); } } # ------------------------------------------------------ # Provide user with feedback # ------------------------------------------------------ if ($this->params['repair']) { $this->out('Application repaired using:'); } else { $this->out('Application created using:'); } $options = $installer->options(); ksort($options); foreach ($options as $key => $value) { $this->out(" {$key} => {$value}"); } if (isset($this->params['source'])) { $this->out("Please note:"); $this->out(" => Configuration files are not automatically updated for user specified applications."); $this->out(" => Make sure to manually update your database credentials, plugins, etc."); } $this->out("\nRemember to update your hosts file with: <info>" . $this->Info->getVmIpAddress() . " http://{$url}</info>\n"); $this->exitBashSuccess('Installation completed successfully'); }
/** * Return LICENSE.TXT as json * * @return void */ public function license() { $this->set(['fileContent' => CakeboxUtility::getFileContent('/cakebox/console/LICENSE.txt'), '_serialize' => ['fileContent']]); }