/** * Install the application */ public function settings() { $form = new Form(array('id' => 'install-settings-form', 'labelWidth' => '30em', 'fieldsets' => array('global' => array('legend' => Lang::get('install.settings-global-legend', null, null, $this->language), new TextInput(array('name' => 'title', 'required' => true, 'label' => Lang::get('install.settings-title-label', null, null, $this->language), 'default' => DEFAULT_HTML_TITLE)), new TextInput(array('name' => 'rooturl', 'required' => true, 'label' => Lang::get('install.settings-rooturl-label', null, null, $this->language), 'placeholder' => 'http://', 'default' => getenv('REQUEST_SCHEME') . '://' . getenv('SERVER_NAME'))), new SelectInput(array('name' => 'timezone', 'required' => true, 'options' => array_combine(\DateTimeZone::listIdentifiers(), \DateTimeZone::listIdentifiers()), 'default' => DEFAULT_TIMEZONE, 'label' => Lang::get('install.settings-timezone-label')))), 'database' => array('legend' => Lang::get('install.settings-database-legend', null, null, $this->language), new TextInput(array('name' => 'db[host]', 'required' => true, 'label' => Lang::get('install.settings-db-host-label', null, null, $this->language), 'default' => 'localhost')), new TextInput(array('name' => 'db[username]', 'required' => true, 'label' => Lang::get('install.settings-db-username-label', null, null, $this->language))), new PasswordInput(array('name' => 'db[password]', 'required' => true, 'label' => Lang::get('install.settings-db-password-label', null, null, $this->language), 'pattern' => '/^.*$/')), new TextInput(array('name' => 'db[dbname]', 'required' => true, 'pattern' => '/^\\w+$/', 'label' => Lang::get('install.settings-db-dbname-label', null, null, $this->language))), new TextInput(array('name' => 'db[prefix]', 'default' => 'Hawk', 'pattern' => '/^\\w+$/', 'label' => Lang::get('install.settings-db-prefix-label', null, null, $this->language)))), 'admin' => array('legend' => Lang::get('install.settings-admin-legend', null, null, $this->language), new TextInput(array('name' => 'admin[login]', 'required' => true, 'pattern' => '/^\\w+$/', 'label' => Lang::get('install.settings-admin-login-label', null, null, $this->language))), new EmailInput(array('name' => 'admin[email]', 'required' => true, 'label' => Lang::get('install.settings-admin-email-label', null, null, $this->language))), new PasswordInput(array('name' => 'admin[password]', 'required' => true, 'label' => Lang::get('install.settings-admin-password-label', null, null, $this->language))), new PasswordInput(array('name' => 'admin[passagain]', 'required' => true, 'compare' => 'admin[password]', 'label' => Lang::get('install.settings-admin-passagain-label', null, null, $this->language)))), '_submits' => array(new SubmitInput(array('name' => 'valid', 'value' => Lang::get('install.install-button', null, null, $this->language), 'icon' => 'cog')))), 'onsuccess' => 'location.href = data.rooturl;')); if (!$form->submitted()) { // Display the form $body = View::make(Plugin::current()->getView('settings.tpl'), array('form' => $form)); return \Hawk\Plugins\Main\MainController::getInstance()->index($body); } else { // Make the installation if ($form->check()) { /** * Generate Crypto constants */ $salt = Crypto::generateKey(24); $key = Crypto::generateKey(32); $iv = Crypto::generateKey(16); $configMode = 'prod'; /** * Create the database and it tables */ $tmpfile = tempnam(sys_get_temp_dir(), ''); DB::add('tmp', array(array('host' => $form->getData('db[host]'), 'username' => $form->getData('db[username]'), 'password' => $form->getData('db[password]')))); try { DB::get('tmp'); } catch (DBException $e) { return $form->response(Form::STATUS_ERROR, Lang::get('install.install-connection-error')); } try { $param = array('{{ $dbname }}' => $form->getData('db[dbname]'), '{{ $prefix }}' => $form->getData('db[prefix]'), '{{ $language }}' => $this->language, '{{ $timezone }}' => $form->getData('timezone'), '{{ $title }}' => Db::get('tmp')->quote($form->getData('title')), '{{ $email }}' => Db::get('tmp')->quote($form->getData('admin[email]')), '{{ $login }}' => Db::get('tmp')->quote($form->getData('admin[login]')), '{{ $password }}' => Db::get('tmp')->quote(Crypto::saltHash($form->getData('admin[password]'), $salt)), '{{ $ip }}' => Db::get('tmp')->quote(App::request()->clientIp())); $sql = strtr(file_get_contents(Plugin::current()->getRootDir() . 'templates/install.sql.tpl'), $param); // file_put_contents($tmpfile, $sql); Db::get('tmp')->query($sql); /** * Create the config file */ $param = array('{{ $salt }}' => addcslashes($salt, "'"), '{{ $key }}' => addcslashes($key, "'"), '{{ $iv }}' => addcslashes($iv, "'"), '{{ $configMode }}' => $configMode, '{{ $rooturl }}' => $form->getData('rooturl'), '{{ $host }}' => $form->getData('db[host]'), '{{ $username }}' => $form->getData('db[username]'), '{{ $password }}' => $form->getData('db[password]'), '{{ $dbname }}' => $form->getData('db[dbname]'), '{{ $prefix }}' => $form->getData('db[prefix]'), '{{ $sessionEngine }}' => $form->getData('session'), '{{ $version }}' => $form->getData('version')); $config = strtr(file_get_contents(Plugin::current()->getRootDir() . 'templates/config.php.tpl'), $param); file_put_contents(INCLUDES_DIR . 'config.php', $config); /** * Create etc/dev.php */ App::fs()->copy(Plugin::current()->getRootDir() . 'templates/etc-dev.php', ETC_DIR . 'dev.php'); /** * Create etc/prod.php */ App::fs()->copy(Plugin::current()->getRootDir() . 'templates/etc-prod.php', ETC_DIR . 'prod.php'); $form->addReturn('rooturl', $form->getData('rooturl')); return $form->response(Form::STATUS_SUCCESS, Lang::get('install.install-success')); } catch (\Exception $e) { return $form->response(Form::STATUS_ERROR, Lang::get('install.install-error')); } } } }
/** * Find the origin language file * * @return string The path of the origin language file */ private function getOriginFile() { if (is_file(App::cache()->getCacheFilePath(self::ORIGIN_CACHE_FILE)) && empty(self::$originCache)) { self::$originCache = App::cache()->includeCache(self::ORIGIN_CACHE_FILE); } if (isset(self::$originCache["{$this->plugin}.{$this->lang}"])) { // the file is registered in the cache return self::$originCache["{$this->plugin}.{$this->lang}"]; } // The file is not present in the cache, search it. We use the method Autoload::find that already performs this action foreach (array(MAIN_PLUGINS_DIR, PLUGINS_DIR, THEMES_DIR) as $dir) { $files = App::fs()->find($dir, $this->plugin . '.' . $this->lang . '.lang', FileSystem::FIND_FILE_ONLY); if (!empty($files)) { $file = $files[0]; // register it in the cache self::$originCache["{$this->plugin}.{$this->lang}"] = $file; return $file; } } return null; }
/** * Update a theme from the remote platform */ public function update() { $theme = Theme::get($this->theme); if ($theme) { App::fs()->remove($theme->getRootDir()); return $this->download(); } }
/** * Clear the cache and reload the whole page */ public function clearCache() { Event::unbind('process-end'); // Clear the directoty cache foreach (glob(CACHE_DIR . '*') as $elt) { App::fs()->remove($elt); } // Clear the directory of the theme foreach (glob(Theme::getSelected()->getStaticDir() . '*') as $element) { if (basename($element) != 'userfiles') { App::fs()->remove($element); } } App::response()->redirectToAction('index'); }
/** * Update Hawk */ public function updateHawk() { try { $api = new HawkApi(); $nextVersions = $api->getCoreAvailableUpdates(); if (empty($nextVersions)) { throw new \Exception("No newer version is available for Hawk"); } // Update incrementally all newer versions foreach ($nextVersions as $version) { // Download the update archive $archive = $api->getCoreUpdateArchive($version['version']); // Extract the downloaded file $zip = new \ZipArchive(); if ($zip->open($archive) !== true) { throw new \Exception('Impossible to open the zip archive'); } $zip->extractTo(TMP_DIR); // Put all modified or added files in the right folder $folder = TMP_DIR . 'update-v' . $version['version'] . '/'; App::fs()->copy($folder . 'to-update/*', ROOT_DIR); // Delete the files to delete $toDeleteFiles = explode(PHP_EOL, file_get_contents($folder . 'to-delete.txt')); foreach ($toDeleteFiles as $file) { if (is_file(ROOT_DIR . $file)) { unlink(ROOT_DIR . $file); } } // Remove temporary files and folders App::fs()->remove($folder); App::fs()->remove($archive); } // Execute the update method if exist $updater = new HawkUpdater(); $methods = get_class_methods($updater); foreach ($nextVersions as $version) { $method = 'v' . str_replace('.', '_', $version['version']); if (method_exists($updater, $method)) { $updater->{$method}(); } } App::cache()->clear('views'); App::cache()->clear('lang'); App::cache()->clear(Autoload::CACHE_FILE); App::cache()->clear(Lang::ORIGIN_CACHE_FILE); $response = array('status' => true); } catch (\Exception $e) { $response = array('status' => false, 'message' => DEBUG_MODE ? $e->getMessage() : Lang::get('admin.update-hawk-error')); } App::response()->setContentType('json'); return $response; }
/** * Clear a cache file or directory * * @param string $cacheFile The cache file or directory to clear */ public function clear($cacheFile = '*') { App::fs()->remove($this->getCacheFilePath($cacheFile)); }
/** * Build the theme : copy every resource files in themes/{themename} * * @param boolean $force If set to true, the theme will be rebuilt without condition * * @return boole True if the theme has been built, false it it has been taken from cache */ public function build($force = false) { if ($this->getDefinition('extends')) { if (Theme::get($this->getDefinition('extends'))) { Theme::get($this->getDefinition('extends'))->build($force); } } $build = false; if ($force) { $build = true; } if (!file_exists($this->getStaticDir())) { mkdir($this->getStaticDir(), 0755, true); $build = true; } if (!$build) { $dest = $this->getStaticCssFile(); if (!is_file($dest)) { $build = true; } else { // Get all files in less/ $files = App::fs()->find($this->getLessDirname(), '*.less'); $lastUpdate = filemtime($dest); foreach ($files as $file) { if (filemtime($file) > $lastUpdate) { $build = true; break; } } } } if ($build) { // Build the theme => Copy each accessible files in static dir foreach (glob($this->getRootDir() . '*') as $elt) { if (!in_array(basename($elt), array('views', 'start.php'))) { App::fs()->copy($elt, $this->getStaticDir()); } } // In the main less file, replace the editable vars by their customized values $values = $this->getVariablesCustomValues(); $precompiledLess = preg_replace_callback(self::EDITABLE_VARS_PATTERN, function ($m) use($values) { return '@' . $m[1] . ' : ' . (isset($values[$m[1]]) ? $values[$m[1]] : $m[2]) . ';'; }, file_get_contents($this->getBaseLessFile())); file_put_contents($this->getStaticLessFile(), $precompiledLess); Less::compile($this->getStaticLessFile(), $this->getStaticCssFile()); } return $build; }
/** * Complete deletion of plugin */ public function delete() { if ($this->removable) { $directory = $this->getRootDir(); App::fs()->remove($directory); } }
/** * Update a plugin from the API */ public function update() { App::response()->setContentType('json'); try { $plugin = Plugin::get($this->plugin); if (!$plugin) { throw new \Exception('The plugin "' . $this->plugin . '" does not exist'); } $api = new HawkApi(); $updates = $api->getPluginsAvailableUpdates(array($plugin->getName() => $plugin->getDefinition('version'))); if (!empty($updates[$plugin->getName()])) { $file = $api->downloadPlugin($this->plugin); $zip = new \ZipArchive(); if ($zip->open($file) !== true) { throw new \Exception('Impossible to open the zip archive'); } // Copy the actual version of the plugin as backup $backup = TMP_DIR . $plugin->getName() . '.bak'; rename($plugin->getRootDir(), $backup); try { $zip->extractTo(PLUGINS_DIR); unset(Plugin::$instances[$this->plugin]); $plugin = Plugin::get($this->plugin); if (!$plugin) { throw new \Exception('An error occured while downloading the plugin'); } $this->installOrupdateDependencies($plugin); $installer = $plugin->getInstallerInstance(); foreach ($updates[$plugin->getName()] as $version) { $method = str_replace('.', '_', 'updateV' . $version); if (method_exists($installer, $method)) { $installer->{$method}(); } } App::fs()->remove($backup); } catch (\Exception $e) { // An error occured while installing the new version, rollback to the previous version App::fs()->remove($plugin->getRootDir()); rename($backup, $plugin->getRootDir()); App::fs()->remove($file); throw $e; } App::fs()->remove($file); } return array(); } catch (\Exception $e) { throw new InternalErrorException($e->getMessage()); } }
/** * Display the list of the translation keys * * @param array $filters The filters to display the list */ public function listKeys($filters = array()) { if (empty($filters)) { $filters = $this->getFilters(); } // Find all files in main-plugin, plugins dans userfiles $files = array(); $dirs = array(MAIN_PLUGINS_DIR, PLUGINS_DIR, USERFILES_PLUGINS_DIR . Lang::TRANSLATIONS_DIR); foreach ($dirs as $dir) { if (is_dir($dir)) { $result = App::fs()->find($dir, '*.*.lang', FileSystem::FIND_FILE_ONLY); } foreach ($result as $file) { list($plugin, $language, $ext) = explode('.', basename($file)); if (empty($files[$plugin])) { $files[$plugin] = array(); } if (empty($files[$plugin][$language])) { $files[$plugin][$language] = array(); } $files[$plugin][$language][$dir == USERFILES_PLUGINS_DIR . Lang::TRANSLATIONS_DIR ? 'translation' : 'origin'] = $file; } } $keys = array(); foreach ($files as $plugin => $languages) { foreach ($languages as $tag => $paths) { foreach ($paths as $name => $file) { $translations = parse_ini_file($file); foreach ($translations as $key => $value) { if (!is_array($value)) { // This is a single key $langKey = "{$plugin}.{$key}"; if (empty($keys[$langKey])) { $keys[$langKey] = array(); } $keys[$langKey][$tag] = $value; } else { // This is a multiple key foreach ($value as $multiplier => $val) { $langKey = $plugin . '.' . $key . '[' . $multiplier . ']'; if (empty($keys[$langKey])) { $keys[$langKey] = array(); } $keys[$langKey][$tag] = $val; } } } } } } $data = array(); foreach ($keys as $langKey => $values) { if ($filters['keys'] != 'missing' || empty($values[$filters['tag']])) { $data[] = (object) array('langKey' => $langKey, 'origin' => isset($values[Lang::DEFAULT_LANGUAGE]) ? $values[Lang::DEFAULT_LANGUAGE] : '', 'translation' => isset($values[$filters['tag']]) ? $values[$filters['tag']] : ''); } } $param = array('id' => 'language-key-list', 'action' => App::router()->getUri('language-keys-list'), 'data' => $data, 'controls' => array(array('type' => 'submit', 'icon' => 'save', 'label' => Lang::get('main.valid-button'), 'class' => 'btn-primary'), array('icon' => 'plus', 'label' => Lang::get('language.new-lang'), 'href' => App::router()->getUri('edit-language', array('tag' => 'new')), 'target' => 'dialog', 'class' => 'btn-success'), array('href' => App::router()->getUri('import-language-keys'), 'target' => 'dialog', 'icon' => 'download', 'label' => Lang::get('language.import-btn'), 'class' => 'btn-info')), 'fields' => array('langKey' => array('label' => Lang::get('language.key-list-key-label')), 'origin' => array('label' => Lang::get('language.key-list-default-translation-label', array('tag' => Lang::DEFAULT_LANGUAGE))), 'translation' => array('label' => Lang::get('language.key-list-default-translation-label', array('tag' => $filters['tag'])), 'display' => function ($value, $field, $line) use($filters) { $key = str_replace(array('[', ']'), array('{', '}'), $line->langKey); return "<textarea name='translation[{$filters['tag']}][{$key}]' cols='40' rows='5'>{$value}</textarea>"; }), 'clean' => array('search' => false, 'sort' => false, 'display' => function ($value, $field, $line) { return Icon::make(array('icon' => 'undo', 'class' => 'text-danger delete-translation', 'title' => Lang::get('language.delete-translation-btn'), 'data-key' => $line->langKey)); }))); $list = new ItemList($param); return $list->__toString(); }