/** * Tests File::isWritable */ public function testIsWritable() { $spl = $this->getDeletableFileInfo(); $file = new File($spl); $writable = $file->isWritable(); unlink($spl->getPathname()); $this->assertEquals(true, $writable); }
public function systemConfig() { $sc = new SystemConfig(); $workRoot = trim(Input::get('workRoot')); // if (File::isWritable($workRoot)) { // $sc->set(SystemConfig::WORK_ROOT_FIELD, $workRoot); // } else { // return Response::json(array( // 'res' => 1, // 'errMsg' => 'Work Root目录不可写!', // )); // } $sc->set(SystemConfig::WORK_ROOT_FIELD, $workRoot); return Response::json(array('res' => 0, 'write' => File::isWritable($workRoot))); }
function action() { $FileManager =& $this->_Parent->ExtensionManager->create('filemanager'); $file = new File(DOCROOT . $FileManager->getStartLocation() . $_GET['file']); if (isset($_POST['action']['save'])) { $fields = $_POST['fields']; $file->setName($fields['name']); if (isset($fields['contents'])) { $file->setContents($fields['contents']); } $file->setPermissions($fields['permissions']); $relpath = str_replace(DOCROOT . $FileManager->getStartLocation(), NULL, dirname($_GET['file'])); if ($file->isWritable()) { redirect($FileManager->baseURL() . 'properties/?file=' . rtrim(dirname($_GET['file']), '/') . '/' . $file->name() . '&result=saved'); } else { redirect($FileManager->baseURL() . 'browse/' . $relpath); } } elseif (isset($_POST['action']['delete'])) { General::deleteFile($file->path() . '/' . $file->name()); $relpath = str_replace(DOCROOT . $FileManager->getStartLocation(), NULL, dirname($_GET['file'])); redirect($FileManager->baseURL() . 'browse/' . $relpath); } }
$tpl->set_filenames(array('show' => 'tpl/install/check_directories.tpl')); $tpl->assign_vars(array('LANGUAGE' => $config['language'], 'SESSION_ID' => session_id())); $checkDirs = array('work/', 'work/config/', 'work/log/', 'work/backup/'); $isWritable = array(); if (1 == $config['safe_mode']) { $tpl->assign_block_vars('SAFE_MODE_ON', array()); } $i = 0; foreach ($checkDirs as $dir) { clearstatcache(); if (!is_dir($dir)) { @mkdir($dir); } clearstatcache(); $check = file_exists($dir); $isWritable[$i] = File::isWritable($dir, 0777); $tpl->assign_vars(array('LANGUAGE' => $config['language'], 'ICON_OK' => $icon['ok'])); $tpl->assign_block_vars('DIR', array('NAME' => $config['paths']['root'] . $dir, 'CHMOD' => File::getChmod($dir), 'ICON_EXISTS' => $check === true ? $icon['ok'] : $icon['not_ok'] . ' ' . $check, 'ICON_IS_WRITABLE' => $isWritable[$i] ? $icon['ok'] : $icon['not_ok'])); $i++; } if (in_array(false, $isWritable)) { $tpl->pparse('show'); // something is wrong with the dirs -> show info } else { $phase = 2; // everything ok -> continue with db-param-input } } // Step 3: database parameters if ($phase == 2) { $tpl = new MSDTemplate();
function perform() { // fetch the data needed from the request $this->_dbServer = $this->_request->getValue("dbServer"); $this->_dbUser = $this->_request->getValue("dbUser"); $this->_dbPassword = $this->_request->getValue("dbPassword"); $this->_dbName = $this->_request->getValue("dbName"); $this->_skipThis = $this->_request->getValue("skipDbInfo"); $this->_dbPrefix = $this->_request->getValue("dbPrefix", DEFAULT_DB_PREFIX); // we should now save the data to the configuration file, just before // we read it $configFile = new ConfigFileStorage(); // we expect everything to be fine $errors = false; // before doing anything, we should check of the configuration file is // writable by this script, or else, throw an error and bail out gracefully $configFileName = $configFile->getConfigFileName(); if (!File::exists($configFileName)) { if (!File::touch($configFileName)) { $this->_view = new WizardView("intro"); $message = "Could not create the pLog configuration file {$configFileName}. Please make sure\n that the file can be created by the user running the webserver. It is needed to\n store the database configuration settings."; $this->_view->setErrorMessage($message); $this->setCommonData(true); return false; } else { ConfigFileStorage::createConfigFile($configFileName); } } if (File::exists($configFileName) && !File::isWritable($configFileName)) { $this->_view = new WizardView("intro"); $message = "Please make sure that the file {$configFileName} can be written by this script during\n the installation process. It is needed to store the database configuration settings. Once the\n installation is complete, please revert the permissions to no writing possible."; $this->_view->setErrorMessage($message); $this->setCommonData(true); return false; } // continue if everything went fine if (!$configFile->saveValue("db_username", $this->_dbUser) || !$configFile->saveValue("db_password", $this->_dbPassword) || !$configFile->saveValue("db_host", $this->_dbServer) || !$configFile->saveValue("db_database", $this->_dbName) || !$configFile->saveValue("db_prefix", $this->_dbPrefix)) { $errors = true; } if ($errors) { $message = "Could not save values to the configuration file. Please make sure it is available and\n that has write permissions for the user under your web server is running."; $this->_view = new WizardView("intro"); $this->_view->setErrorMessage($message); return false; } else { $this->_view = new WizardView("step1"); // now we better read the information from the config file to make sure that // it has been correctly saved $this->setCommonData(true); return true; } }
/** * Removes a locale from the system. First the file containing it is deleted * and then we also remove its entry from the configuration. * * @param localeCode The code of the locale that we would like to delete. * @return Returns true if the locale was removed succesfully or false otherwise. */ function removeLocale($localeCode) { $config =& Config::getConfig(); // if we don't have permissions on the folder where the locale files // are stored, we don't even have to bother about it... if (!File::isWritable(Locale::getLocaleFolder())) { return false; } // does the locale really exist? if (!$this->isValidLocale($localeCode)) { return false; } $fileName = $this->getLocaleFilename($localeCode); if (File::exists($fileName)) { if (!unlink($fileName)) { return false; } } $availableLocales = $config->getValue("locales"); $newLocaleList = array(); foreach ($availableLocales as $locale) { if ($locale != $localeCode) { array_push($newLocaleList, $locale); } } $config->saveValue("locales", $newLocaleList); return true; }
/** * Execute the console command. * * @return mixed */ public function fire() { // Certain stages of this installer will require variables // to be opulated, which will eventually be used to // write the resultant configuration file. Some // stages require testing too, so lets // prepare some defaults that will // be used. $configuration = array('mysql_hostname' => '127.0.0.1', 'mysql_database' => 'seat', 'mysql_username' => 'root', 'mysql_password' => '', 'redis_host' => '127.0.0.1', 'redis_port' => 6379, 'mail_driver' => 'mail', 'mail_from' => 'seatadmin@localhost', 'mail_from_name' => 'SeAT Administrator', 'smtp_hostname' => '127.0.0.1', 'smtp_username' => null, 'smtp_password' => null, 'smtp_port' => 25, 'smtp_encryption' => null); $this->info('[+] Welcome to the SeAT v' . \Config::get('seat.version') . ' installer!'); $this->line(''); // The very first thing we will be checking is the existence of // the .env.php file which contains the configuration of a // installed system. If this file exists, we will assume // that SeAT is already installed and exit. if (\File::exists(base_path() . '/.installed.lck')) { $this->error('[!] It appears as if SeAT is already installed. Exiting.'); return; } // Next, we will check that we will eventually be able to write // to the .env.php in base_path() /.env.php. if (!\File::isWritable(base_path() . '/.env.php')) { $this->error('[!] The installer needs to be able to write a configuration file to ' . base_path() . '/.env.php, but it appears as though it can not write there.'); return; } // Knowing that we can write the configuration file, we move on to // getting the details for the database. We will try with the // defaults, and if that fails, continue to ask for details // until we can connect $this->info('[+] Database setup...'); $this->info('[+] Please enter the details for the MySQL database to use (enter to use default):'); $error_count = 0; while (true) { // Ask for the MySQL credentials. $configuration['mysql_username'] = $this->ask('[?] Username (' . $configuration['mysql_username'] . '):') ?: $configuration['mysql_username']; $configuration['mysql_password'] = $this->secret('[?] Password:'******'mysql_password']; $configuration['mysql_hostname'] = $this->ask('[?] Hostname (' . $configuration['mysql_hostname'] . '):') ?: $configuration['mysql_hostname']; $configuration['mysql_database'] = $this->ask('[?] Database (' . $configuration['mysql_database'] . '):') ?: $configuration['mysql_database']; // Set the runtime configuration that we have \Config::set('database.connections.mysql.host', $configuration['mysql_hostname']); \Config::set('database.connections.mysql.database', $configuration['mysql_database']); \Config::set('database.connections.mysql.username', $configuration['mysql_username']); \Config::set('database.connections.mysql.password', $configuration['mysql_password']); // Test the database connection try { \DB::reconnect(); \DB::connection()->getDatabaseName(); $this->info('[+] Successfully connected to the MySQL database.'); $this->line(''); // If the connection worked, we don't have to ask for anything // and just move on to the next section break; } catch (\Exception $e) { $error_count++; // Check if we have had more than 3 errors now. if ($error_count >= 3) { $this->error('[!] 3 attempts to connect to the database failed.'); $this->error('[!] Please ensure that you have a MySQL server with a database ready for SeAT to use before installation.'); return; } $this->error('[!] Unable to connect to the database with mysql://' . $configuration['mysql_username'] . '@' . $configuration['mysql_hostname'] . '/' . $configuration['mysql_database']); $this->error('[!] Please re-enter the configuration to try again.'); $this->error('[!] MySQL said: ' . $e->getMessage()); $this->line(''); $this->info('[+] Please re-enter the MySQL details below:'); } } // Now that we have a working database connection, move // on to the Redis configuration. We will follow a // similar path of a infinite loop until it works $this->info('[+] Redis cache setup...'); $this->info('[+] Please enter the details for the Redis cache to use (enter to use default):'); $error_count = 0; while (true) { // Ask for the Redis details. $configuration['redis_host'] = $this->ask('[?] Host (' . $configuration['redis_host'] . '):') ?: $configuration['redis_host']; $configuration['redis_port'] = $this->ask('[?] Port (' . $configuration['redis_port'] . '):') ?: $configuration['redis_port']; // Set the \Config for this one runtime to test the connection \Config::set('database.redis.default.host', $configuration['redis_host']); \Config::set('database.redis.default.port', $configuration['redis_port']); // Test that we can add and remove keys from the cache try { \Cache::put('installer_test', true, 60 * 24); \Cache::forget('installer_test'); $this->info('[+] Successfully connected to the Redis cache.'); $this->line(''); // If the connection worked and we were able to place // and delete a key, move on to the next section break; } catch (\Exception $e) { $error_count++; // Check if we have had more than 3 errors now. if ($error_count >= 3) { $this->error('[!] 3 attempts to connect to redis failed.'); $this->error('[!] Please ensure that you have a Redis server ready for SeAT to use before installation.'); return; } $this->error('[!] Unable to connect to the redis cache at tcp://' . $configuration['redis_host'] . ':' . $configuration['redis_port']); $this->error('[!] Please re-enter the configuration to try again.'); $this->error('[!] Redis said: ' . $e->getMessage()); $this->line(''); $this->info('[+] Please re-enter the Redis details below:'); } } // We now have MySQL + Redis setup and ready. Lets move on the // the email configurations. If we have mail/sendmail as // the config, its easy. However, if we use SMTP, we // need to ask the user for credentials too, incase // those are needed. We will also start another // infinite loop to allow the user to confirm // that the details they entered is correct. $this->info('[+] Mail setup...'); $this->info('[+] Please enter the details for the email configuration to use (enter to use default):'); while (true) { // Ask for the email details $configuration['mail_driver'] = $this->ask('[?] How are emails going to be sent? [mail/sendmail/smtp] (' . $configuration['mail_driver'] . '):') ?: $configuration['mail_driver']; // Check the option we got. If it is not in the array of // known configuration, we return to the question if (!in_array($configuration['mail_driver'], array('mail', 'sendmail', 'smtp'))) { $this->error('[!] The driver you have chosen is not recognized, please try again.'); continue; } // Get the details about where emails will be coming from $configuration['mail_from'] = $this->ask('[?] Where will emails be coming from? (' . $configuration['mail_from'] . '):') ?: $configuration['mail_from']; $configuration['mail_from_name'] = $this->ask('[?] Who will emails be coming from? (' . $configuration['mail_from_name'] . '):') ?: $configuration['mail_from_name']; // If the configuration option is set as smtp, we need to // give the option to set the username and password if ($configuration['mail_driver'] == 'smtp') { $configuration['smtp_hostname'] = $this->ask('[?] SMTP Hostname (' . $configuration['smtp_hostname'] . '):') ?: $configuration['smtp_hostname']; $configuration['smtp_username'] = $this->ask('[?] SMTP Username (' . $configuration['smtp_username'] . '):') ?: $configuration['smtp_username']; $configuration['smtp_password'] = $this->secret('[?] SMTP Password:'******'smtp_password']; $configuration['smtp_port'] = $this->ask('[?] SMTP Port (' . $configuration['smtp_port'] . '):') ?: $configuration['smtp_port']; $configuration['smtp_encryption'] = $this->ask('[?] SMTP Encryption (' . $configuration['smtp_encryption'] . '):') ?: $configuration['smtp_encryption']; } // Print the values and get confirmation that they are correct $this->line(''); $this->line('[+] Mail configuration summary:'); $this->line('[+] Mail Driver: ' . $configuration['mail_driver']); // If we are going to be using the SMTP driver, show the // values for the host/user/pass if ($configuration['mail_driver'] == 'smtp') { $this->line('[+] SMTP Host: ' . $configuration['smtp_hostname']); $this->line('[+] SMTP Username: '******'smtp_username']); $this->line('[+] SMTP Password: '******'*', strlen($configuration['smtp_password']))); $this->line('[+] SMTP Port: ' . $configuration['smtp_port']); $this->line('[+] SMTP Encryption: ' . $configuration['smtp_encryption']); } $this->line(''); if ($this->confirm('[?] Are the above mail settings correct? [yes/no]', true)) { break; } else { continue; } } // With the configuration done, lets attempt to write this to // to disk if (!$this->writeConfig($configuration)) { $this->error('[!] Writing the configuration file failed!'); return; } $this->info('[+] Successfully wrote the configuration file'); // With configuration in place, lets move on to preparing SeAT // for use. We have to do a few things for which most // already have commands. So, lets re-use those // meaning that if they change the intaller // is already up to date. // Run the database migrations $this->info('[+] Running the database migrations...'); $this->call('migrate'); // Run the database seeds $this->info('[+] Running the database seeds...'); $this->call('db:seed'); // Update the SDEs $this->info('[+] Updating to the latest EVE SDE\'s...'); $this->call('seat:update-sde', array('--confirm' => null)); // Configure the admin user $this->info('[+] Configuring the \'admin\' user...'); $this->call('seat:reset'); // Sync the access groups $this->info('[+] Syncing the access groups...'); $this->call('seat:groupsync'); $this->line(''); // Regenerate the Application Encryption key $this->info('[+] Regenerating the Encryption Key'); $this->call('key:generate'); $this->line(''); // Finally, write the installer lock file! $lock_file_write = \File::put(base_path() . '/.installed.lck', 'Installed ' . date('Y-m-d H:i:s')); // Check that we wrote the lock file successfully if (!$lock_file_write) { $this->error('[!] Was not able to write the installation lock file! Please touch \'installed.lck\'.'); } $this->info('[+] Done!'); }
/** * Sets the folder where sessions should be saved, in case we'd like to save * them somewhere else. This class will check the config parameter <b>session_save_path</b>: if * it's not empty, it will use its value as the name of the folder where sessions should be saved, and it * will also take care of creating the folder if it does not exist. If the folder exists but it cannot * be read, it will throw an exception and quit (because this is a big issue) * If the value of this parameter is empty, it will not do anything and use PHP's default settings for this. * * @static */ function setSessionSavePath() { $config =& Config::getConfig(); $sessionFolder = $config->getValue("session_save_path"); // do we need to do anything if we are using the default // session path? PHP defaults to /tmp/, so there isn't // anything to do if (isset($sessionFolder)) { if (!File::exists($sessionFolder)) { // create folder with only user permissions // since we want to protect the session data if (!File::createDir($sessionFolder, 0700)) { throw new Exception("Sessions should be " . "saved in {$sessionFolder} but it " . "doesn't exist and I can't create it!"); die; } } // check if the folder is accessible if (!File::isReadable($sessionFolder) || !File::isWritable($sessionFolder)) { if (!File::chMod($sessionFolder, 0700)) { throw new Exception("Sessions should be " . "saved in {$sessionFolder} but it is " . "not accessible!"); die; } } // if everything ok, we can continue... session_save_path($sessionFolder); } return true; }
$fieldset_data = $fs->get_data(); $data['fields'] = $fieldset_data['fields']; } else { # not set. $data['fields'] = array(); } /* |-------------------------------------------------------------------------- | Check if file is writable |-------------------------------------------------------------------------- | | We now have a file name. Let's check if we can write to this thing. | If not, throw an error page | */ if (!Statamic::is_content_writable() || File::exists($file) && !File::isWritable($file)) { $url = $admin_app->urlFor('error') . "?code=content_not_writable"; $admin_app->redirect($url); } /* |-------------------------------------------------------------------------- | Fieldset defaults |-------------------------------------------------------------------------- | | We need to bring in the fieldset so we know what we're working with | */ $fieldset = null; $field_settings = array(); if (count($data['fields']) < 1 && File::exists("{$content_root}/{$folder}/fields.yaml")) { $fields_raw = File::get("{$content_root}/{$folder}/fields.yaml");
/** * Updates the internal content cache * * @return boolean */ public static function update() { // track if any files have changed $files_changed = false; // grab length of content type extension $content_type = Config::getContentType(); $full_content_root = rtrim(Path::tidy(BASE_PATH . "/" . Config::getContentRoot()), "/"); $content_type_length = strlen($content_type) + 1; // the cache file we'll use $cache_file = BASE_PATH . "/_cache/_app/content/content.php"; $time_file = BASE_PATH . "/_cache/_app/content/last.php"; $now = time(); // grab the existing cache $cache = unserialize(File::get($cache_file)); if (!is_array($cache)) { $cache = array("urls" => array(), "content" => array(), "taxonomies" => array()); } $last = File::get($time_file); // grab a list of all files $finder = new Finder(); $files = $finder->files()->name("*." . Config::getContentType())->in(Config::getContentRoot()); // grab a separate list of files that have changed since last check $updated_files = clone $files; $updated = array(); if ($last) { $updated_files->date(">= " . Date::format("Y-m-d H:i:s", $last)); foreach ($updated_files as $file) { // we don't want directories, they may show up as being modified // if a file inside them has changed or been renamed if (is_dir($file)) { continue; } // this isn't a directory, add it to the list $updated[] = Path::trimFilesystem(Path::standardize($file->getRealPath())); } } // loop over current files $current_files = array(); foreach ($files as $file) { $current_files[] = Path::trimFilesystem(Path::standardize($file->getRealPath())); } // get a diff of files we know about and files currently existing $new_files = array_diff($current_files, $cache['urls']); // create a master list of files that need updating $changed_files = array_unique(array_merge($new_files, $updated)); // add to the cache if files have been updated if (count($changed_files)) { $files_changed = true; // build content cache foreach ($changed_files as $file) { $file = $full_content_root . $file; $local_path = Path::trimFilesystem($file); $local_filename = Path::clean($local_path); // file parsing $content = substr(File::get($file), 3); $divide = strpos($content, "\n---"); $front_matter = trim(substr($content, 0, $divide)); // parse data $data = YAML::parse($front_matter); // set additional information $data['_file'] = $file; $data['_local_path'] = $local_path; $data['_order_key'] = null; $data['datetimestamp'] = null; // legacy $data['datestamp'] = null; $data['date'] = null; $data['time'] = null; $data['numeric'] = null; $data['last_modified'] = filemtime($file); $data['_is_hidden'] = false; $data['_is_draft'] = false; // folder $data['_folder'] = preg_replace(Pattern::ORDER_KEY, "", str_replace($full_content_root, "", $data['_file'])); $slash = strrpos($data['_folder'], "/"); $data['_folder'] = $slash === 0 ? "" : substr($data['_folder'], 1, $slash - 1); // fix hidden/draft files $slug = basename($file, "." . $content_type); if (substr($slug, 0, 2) === "__") { $data['_is_hidden'] = true; $data['slug'] = substr($slug, 2); } elseif (substr($slug, 0, 1) === "_") { $data['_is_draft'] = true; $data['slug'] = substr($slug, 1); } else { $data['slug'] = $slug; } $data['_basename'] = $data['slug'] . "." . $content_type; $data['_filename'] = $data['slug']; $data['_is_entry'] = preg_match(Pattern::ENTRY_FILEPATH, $data['_basename']); $data['_is_page'] = preg_match(Pattern::PAGE_FILEPATH, $data['_basename']); // 404 is special if ($data['_local_path'] === "/404.{$content_type}") { $local_filename = $local_path; // order key } elseif (preg_match(Pattern::DATE_OR_DATETIME, $data['_basename'], $matches)) { $date = $matches[1] . '-' . $matches[2] . '-' . $matches[3]; $time = NULL; if (isset($matches[4])) { $time = substr($matches[4], 0, 2) . ":" . substr($matches[4], 2); $date = $date . " " . $time; $data['slug'] = substr($data['slug'], 16); $data['datetimestamp'] = $data['_order_key']; } else { $data['slug'] = substr($data['slug'], 11); } $data['_order_key'] = strtotime($date); $data['datestamp'] = $data['_order_key']; $data['date'] = Date::format(Config::getDateFormat(), $data['_order_key']); $data['time'] = $time ? Date::format(Config::getTimeFormat(), $data['_order_key']) : NULL; } elseif (preg_match(Pattern::NUMERIC, $data['_basename'], $matches)) { $data['_order_key'] = $matches[1]; $data['numeric'] = $data['_order_key']; $data['slug'] = substr($data['slug'], strlen($matches[1]) + 1); } else { $data['_order_key'] = $data['_basename']; } // determine url $data['url'] = preg_replace("/\\/__?/", "/", $local_filename); // remove any content type extensions from the end of filename if (substr($data['url'], -$content_type_length) === "." . $content_type) { $data['url'] = substr($data['url'], 0, strlen($data['url']) - $content_type_length); } // remove any base pages from filename if (substr($data['url'], -5) == "/page") { $data['url'] = substr($data['url'], 0, strlen($data['url']) - 5); } // add the site root $data['url'] = Path::tidy(Config::getSiteRoot() . $data['url']); // add the site URL to get the permalink $data['permalink'] = Path::tidy(Config::getSiteURL() . $data['url']); // add to cache file $cache['content'][$local_path] = $data; $cache['urls'][$data['url']] = $local_path; } } // loop through all cached content for deleted files // this isn't as expensive as you'd think in real-world situations foreach ($cache['content'] as $local_path => $data) { if (File::exists($full_content_root . $local_path)) { continue; } $files_changed = TRUE; // remove from content cache unset($cache['content'][$local_path]); // remove from url cache $url = array_search($local_path, $cache['urls']); if ($url !== FALSE) { unset($cache['urls'][$url]); } } // build taxonomy cache // only happens if files were added, updated, or deleted above if ($files_changed) { $taxonomies = Config::getTaxonomies(); $force_lowercase = Config::getTaxonomyForceLowercase(); $case_sensitive = Config::getTaxonomyCaseSensitive(); $cache['taxonomies'] = array(); if (count($taxonomies)) { // set up taxonomy array foreach ($taxonomies as $taxonomy) { $cache['taxonomies'][$taxonomy] = array(); } // loop through content to build cached array foreach ($cache['content'] as $file => $data) { // do not grab anything not public if (array_get($data, '_is_hidden', FALSE) || array_get($data, '_is_draft', FALSE)) { continue; } // loop through the types of taxonomies foreach ($taxonomies as $taxonomy) { // if this file contains this type of taxonomy if (isset($data[$taxonomy])) { $values = Helper::ensureArray($data[$taxonomy]); // add the file name to the list of found files for a given taxonomy value foreach ($values as $value) { if (!$value) { continue; } $key = !$case_sensitive ? strtolower($value) : $value; if (!isset($cache['taxonomies'][$taxonomy][$key])) { $cache['taxonomies'][$taxonomy][$key] = array("name" => $force_lowercase ? strtolower($value) : $value, "files" => array()); } array_push($cache['taxonomies'][$taxonomy][$key]['files'], $data['url']); } } } } } if (File::put($cache_file, serialize($cache)) === false) { if (!File::isWritable($cache_file)) { Log::fatal("Cache folder is not writable.", "core", "content-cache"); } Log::fatal("Could not write to the cache.", "core", "content-cache"); return false; } } File::put($time_file, $now); return true; }
/** * Execute the console command. * * @return mixed */ public function fire() { // Start by warning the user about the command that will be run $this->comment('Warning! This Laravel command uses exec() to execute a mysql shell command to import a extracted dump.'); $this->comment('Due to the way the command is constructed, should someone view the current running processes of your server, they will be able to see your SeAT database users password.'); $this->line(''); $this->line('Ensure that you understand this before continuing.'); // Test that we have valid Database details. An exception // will be thrown if this fails. \DB::connection()->getDatabaseName(); if ($this->option('confirm') || $this->confirm('Are you sure you want to update to the latest EVE SDE? [yes|no]', true)) { $this->info('Checking for SDE updates at https://raw.githubusercontent.com/eve-seat/seat/resources/sde_version.json ...'); // Check the current SDE version from Github in the eve-seat/seat/resources // repository. First though, we setup some default headers and options // that will be used in Requests in this script $headers = array('Accept' => 'application/json'); $options = array('timeout' => 120, 'useragent' => 'SeAT-Updater/' . \Config::get('seat.version')); // Now, attempt the actual request. $request = \Requests::get('https://raw.githubusercontent.com/eve-seat/seat/resources/sde_version.json', $headers, $options); // If the request failed, return as there is nothing we can do about that if (!$request->success) { $this->error('Warning: Failed to retreive the latest SDE information from the eve-seat/resources branch.'); return; } // Read the response JSON $sde_data = json_decode($request->body); // If it was not possible to parse the JSON, return as there is nothing // we can go any further if (is_null($sde_data)) { $this->error('Warning: Failed to parse the response JSON.'); return; } // Show some debugging information about what we got from the resources branch $this->line('The current SDE version is ' . $sde_data->version); $this->line(count($sde_data->tables) . ' dumps will be downloaded from ' . $sde_data->url . ' in ' . $sde_data->format . ' format and imported into mysql://' . \Config::get('database.connections.mysql.host') . '/' . \Config::get('database.connections.mysql.database')); // Prepare a final confirmation before work comences for the update if ($this->option('confirm') || $this->confirm('Does the above look OK? [yes|no]', true)) { // Prepare the filesystem for the dumps $storage = storage_path() . '/sde/' . $sde_data->version . '/'; $this->line('Preparing ' . $storage . ' to store the dumps.'); // Check that we are able to write to the storage_path() if (\File::isWritable(storage_path())) { // Check that the path exists if (!\File::exists($storage)) { \File::makeDirectory($storage, 0755, true); } // With the disk storage ok, we continue to download the // archives. To try and save some badnwidth, we will // check that the archive does not already exist. $this->line('Downloading SDE data...'); // Loop over the tables as defined in the JSON foreach ($sde_data->tables as $table) { $full_path = $storage . $table . $sde_data->format; $full_url = $sde_data->url . $table . $sde_data->format; // Check if we don't already have this file. If it does // exist, check that it is larger than 0 bytes. if (\File::exists($full_path)) { if (\File::size($full_path) > 0) { continue; } } // Attempt to download the file $file = \Requests::get($full_url, $options, $options); if ($file->success) { // Save the dump to disk \File::put($full_path, $file->body); $this->info('[OK] ' . $full_url); } else { $this->error('Failed to download ' . $full_url . '. The HTTP error was ' . $file->status_code); } } // Next, we will read the bz2 archives, and attempt to run the // SQL queries in them. // Unfortunately, at least until I learn a better way, I seems like // running the imports with a exec() is the only way I can get // this to work, for now. =( $this->line('Importing the SQL...'); foreach ($sde_data->tables as $table) { // Prepare the full path and check its validity $full_path = $storage . $table . $sde_data->format; if (!\File::exists($full_path) || !\File::size($full_path) > 0) { $this->error('Warning: ' . $full_path . ' does not appear to be valid. Maybe the download failed? Skipping import for this file.'); continue; } // Now that we know that the source .bz2 exists, check if // the archive is possibly already extracted. Of so, // skip the extraction process completely. $full_extracted_path = $storage . $table . '.sql'; if (!\File::exists($full_extracted_path) || !\File::size($full_extracted_path) > 0) { // Get 2 handles ready for both the in and out files $input_file = bzopen($full_path, 'r'); $output_file = fopen($full_extracted_path, 'w'); // Write the $output_file in chunks while ($chunk = bzread($input_file, 4096)) { fwrite($output_file, $chunk, 4096); } // Close the input file bzclose($input_file); fclose($output_file); } // With the output file ready, prepare the scary exec() command // that should be run. A sample $import_command is: // mysql -u root -h 127.0.0.1 seat < /tmp/sample.sql $import_command = 'mysql -u ' . \Config::get('database.connections.mysql.username') . (strlen(\Config::get('database.connections.mysql.password')) ? ' -p' : '') . \Config::get('database.connections.mysql.password') . ' -h ' . \Config::get('database.connections.mysql.host') . ' ' . \Config::get('database.connections.mysql.database') . ' < ' . $full_extracted_path; // Run the command... (*scared_face*) exec($import_command, $output, $exit_code); // If the command failed, we should have a $exit_code of // not 0. If thats the case, read $output and print // that as debugging information if ($exit_code !== 0) { $this->error('Warning: Import failed with exit code ' . $exit_code . ' and command outut: ' . implode('\\n', $output)); } // Write the OK $this->info('[OK] ' . $table . $sde_data->format . ' [' . number_format(\File::size($full_path) / 1048576, 2) . 'MB]'); } $this->line('SDE update to ' . $sde_data->version . ' completed successfully.'); } else { $this->error('Warning: Unable to write to the storage path ' . storage_path() . ' to store the dumps.'); } } else { $this->comment('Warning: SDE Update aborted'); } } }
/** * Execute the console command. * * @return mixed */ public function fire() { // Prepare some welcome information $this->info('[+] Welcome to the SeAT v' . \Config::get('seat.version') . ' updater!'); $this->line(''); $this->comment('[+] Warning: Please ensure that you read any potential upgrade specifics prior to upgrading your installation.'); $this->comment('[+] Upgrade guides can be found here: https://github.com/eve-seat/seat/tree/master/docs/upgrade_specifics'); $this->line(''); $this->comment('[+] Note: Any local changes to SeAT will be overriden with this upgrade. Ensure you have the required backups first.'); $this->line(''); $this->line('[+] Checking if we have everything required to attempt an update...'); // Lets check if we have everything that we need to update, //and that we are infact out of date // Start with the git command $git_command = exec('which git'); if (strlen($git_command) <= 0 || !\File::exists($git_command)) { $this->error('[!] Error: `git` command not found. Please ensure that you have Git installed and in your $PATH'); return; } $this->info('[+] `git` found at `' . $git_command . '`'); // Move on to composer. If we did not get the path // to where composer is installed, attempt to // find it. We will first check $PATH, then // the ./ and finally error out $composer_command = $this->option('composer'); if (!is_null($composer_command)) { if (!\File::exists($composer_command)) { $this->error('[!] Error: Composer was not found at `' . $composer_command . '`. Please specify a valid path to `composer.phar`.'); return; } } else { // So we did not get the path to composer.phar, lets // try and find it. $composer_command = exec('which composer'); if (strlen($composer_command) <= 0 || !\File::exists($composer_command)) { $composer_command = exec('which composer.phar'); if (strlen($composer_command) <= 0 || !\File::exists($composer_command)) { $composer_command = base_path() . '/composer'; if (strlen($composer_command) <= 0 || !\File::exists($composer_command)) { $composer_command = base_path() . '/composer.phar'; if (strlen($composer_command) <= 0 || !\File::exists($composer_command)) { $this->error('[!] Error: Unable to find `composer.phar`. Please specify a valid path to `composer.phar` as a command argument.'); return; } } } } } $this->info('[+] `composer.phar` found at `' . $composer_command . '`'); // Next ensure that the path where SeAT is installed is // writable to us now if (!\File::isWritable(base_path())) { $this->error('[!] Error: ' . base_path() . ' is not writable to the current user that is running this command.'); return; } $this->info('[+] ' . base_path() . ' is writable for the upgrade.'); $this->line('[+] Checking version information against the Github repository...'); // Check the version information $version_information = $this->checkVersion(); // If we didnt get the flag to skip the version // check, check it. if (!$this->option('no-version')) { // If we are on the latest, simply exit if ($version_information['versions_behind'] == 0) { $this->comment('[+] You are running SeAT v' . \Config::get('seat.version') . ' which is the latest.'); return; } } // Ask the user if they want to upgrade. if (!$this->confirm('[?] Are you sure you want to upgrade from SeAT v' . \Config::get('seat.version') . ' to ' . $version_information['release_data'][0]->tag_name . '?', true)) { $this->error('[+] Error: User cancelled upgrade.'); return; } // We have everything we need to continue the // upgrade. Bring the application down so // that we can continue. $this->call('down'); if (!\App::isDownForMaintenance()) { $this->error('[!] Error: Dropping SeAT into maintenance mode failed.'); return; } // Move on to calling git to pull down the latest // code from eve-seat/seat. // git fetch -f $this->line('[+] Running: `' . $git_command . ' fetch -f`'); system($git_command . ' fetch -f', $exit_code); // If the command failed, we should have a $exit_code of // not 0. If thats the case, read $output and print // that as debugging information if ($exit_code !== 0) { $this->error('[!] Error: git fetch failed with exit code ' . $exit_code); return; } // git pull -f $this->line('[+] Running: `' . $git_command . ' pull -f`'); system($git_command . ' pull -f', $exit_code); // If the command failed, we should have a $exit_code of // not 0. If thats the case, read $output and print // that as debugging information if ($exit_code !== 0) { $this->error('[!] Error: git pull failed with exit code ' . $exit_code); return; } // git checkout -f master if we did not get the --dev option if (!$this->option('dev')) { $this->line('[+] Running: `' . $git_command . ' checkout -f master`'); system($git_command . ' checkout -f master', $exit_code); // If the command failed, we should have a $exit_code of // not 0. If thats the case, read $output and print // that as debugging information if ($exit_code !== 0) { $this->error('[!] Error: git checkout -f master failed with exit code ' . $exit_code); return; } } // composer self-update $this->line('[+] Running: `' . $composer_command . ' self-update`'); system($composer_command . ' self-update', $exit_code); // If the command failed, we should have a $exit_code of // not 0. If thats the case, read $output and print // that as debugging information if ($exit_code !== 0) { $this->error('[!] Error: composer self-update failed with exit code ' . $exit_code); return; } // composer update $this->line('[+] Running: `' . $composer_command . ' update`'); system($composer_command . ' update', $exit_code); // If the command failed, we should have a $exit_code of // not 0. If thats the case, read $output and print // that as debugging information if ($exit_code !== 0) { $this->error('[!] Error: composer update failed with exit code ' . $exit_code); return; } // composer dump-autoload $this->line('[+] Running: `' . $composer_command . ' dump-autoload`'); system($composer_command . ' dump-autoload', $exit_code); // If the command failed, we should have a $exit_code of // not 0. If thats the case, read $output and print // that as debugging information if ($exit_code !== 0) { $this->error('[!] Error: composer dump-autoload failed with exit code ' . $exit_code); return; } // Database migrations $this->line('[+] Running database migrations.'); $this->call('migrate'); // SDE Updates if (!$this->option('no-sde')) { $this->line('[+] Running EVE SDE Updates'); $this->call('seat:update-sde', array('--confirm' => null)); } // With everything done, bring the application back up $this->call('up'); $this->line(''); $this->info('[+] Upgrade done! It is recommended that you have a look at the `laravel.log` file for any potential errors.'); $this->info('[+] You can view the log file with `php artisan tail`, or responding with [y] to the next question.'); // Ask the user if they want to upgrade. if ($this->confirm('[?] Do you want to tail the log file now?', true)) { $this->call('tail'); } }
/** * Updates the internal content cache * * @return boolean */ public static function update() { // start measuring $content_hash = Debug::markStart('caching', 'content'); // track if any files have changed $files_changed = false; $settings_changed = false; $members_changed = false; // grab length of content type extension $content_type = Config::getContentType(); $full_content_root = rtrim(Path::tidy(BASE_PATH . "/" . Config::getContentRoot()), "/"); $content_type_length = strlen($content_type) + 1; // the cache files we'll use $cache_file = BASE_PATH . '/_cache/_app/content/content.php'; $settings_file = BASE_PATH . '/_cache/_app/content/settings.php'; $structure_file = BASE_PATH . '/_cache/_app/content/structure.php'; $time_file = BASE_PATH . '/_cache/_app/content/last.php'; $members_file = BASE_PATH . '/_cache/_app/members/members.php'; $now = time(); // start measuring settings hash $settings_hash = Debug::markStart('caching', 'settings'); // check for current and new settings $settings = unserialize(File::get($settings_file)); if (!is_array($settings)) { $settings = array('site_root' => '', 'site_url' => '', 'timezone' => '', 'date_format' => '', 'time_format' => '', 'content_type' => '', 'taxonomy' => '', 'taxonomy_case_sensitive' => '', 'taxonomy_force_lowercase' => '', 'entry_timestamps' => '', 'base_path' => '', 'app_version' => ''); } // look up current settings $current_settings = array('site_root' => Config::getSiteRoot(), 'site_url' => Config::getSiteURL(), 'timezone' => Config::get('timezone'), 'date_format' => Config::get('date_format'), 'time_format' => Config::get('time_format'), 'content_type' => Config::get('content_type'), 'taxonomy' => Config::getTaxonomies(), 'taxonomy_case_sensitive' => Config::getTaxonomyCaseSensitive(), 'taxonomy_force_lowercase' => Config::getTaxonomyForceLowercase(), 'entry_timestamps' => Config::getEntryTimestamps(), 'base_path' => BASE_PATH, 'app_version' => STATAMIC_VERSION); // have cache-altering settings changed? if ($settings !== $current_settings) { // settings have changed $settings_changed = true; // clear the cache and set current settings $cache = self::getCleanCacheArray(); $settings = $current_settings; $last = null; } else { // grab the existing cache $cache = unserialize(File::get($cache_file)); if (!is_array($cache)) { $cache = self::getCleanCacheArray(); } $last = File::get($time_file); } // mark end of settings hash measuring Debug::markEnd($settings_hash); // grab a list of all content files $files = File::globRecursively(Path::tidy(BASE_PATH . '/' . Config::getContentRoot() . '/*'), Config::getContentType()); // grab a separate list of files that have changed since last check $updated = array(); $current_files = array(); // loop through files, getting local paths and checking for updated files foreach ($files as $file) { $local_file = Path::trimFilesystemFromContent(Path::standardize($file)); // add to current files $current_files[] = $local_file; // is this updated? if ($last && File::getLastModified($file) >= $last) { $updated[] = $local_file; } } // get a diff of files we know about and files currently existing $known_files = array(); foreach ($cache['urls'] as $url_data) { array_push($known_files, $url_data['path']); } $new_files = array_diff($current_files, $known_files); // create a master list of files that need updating $changed_files = array_unique(array_merge($new_files, $updated)); // store a list of changed URLs $changed_urls = array(); // add to the cache if files have been updated if (count($changed_files)) { $files_changed = true; // build content cache foreach ($changed_files as $file) { $file = $full_content_root . $file; $local_path = Path::trimFilesystemFromContent($file); // before cleaning anything, check for hidden or draft content $is_hidden = Path::isHidden($local_path); $is_draft = Path::isDraft($local_path); // now clean up the path $local_filename = Path::clean($local_path); // file parsing $content = substr(File::get($file), 3); $divide = strpos($content, "\n---"); $front_matter = trim(substr($content, 0, $divide)); $content_raw = trim(substr($content, $divide + 4)); // parse data $data = YAML::parse($front_matter); if ($content_raw) { $data['content'] = 'true'; $data['content_raw'] = 'true'; } // set additional information $data['_file'] = $file; $data['_local_path'] = $local_path; $data['_order_key'] = null; $data['datetimestamp'] = null; // legacy $data['datestamp'] = null; $data['date'] = null; $data['time'] = null; $data['numeric'] = null; $data['last_modified'] = filemtime($file); $data['_is_hidden'] = $is_hidden; $data['_is_draft'] = $is_draft; // get initial slug (may be changed below) $data['slug'] = ltrim(basename($file, "." . $content_type), "_"); // folder $instance = $data['slug'] == 'page' ? 1 : 0; $data['_folder'] = Path::clean($data['_local_path']); $slash = Helper::strrpos_count($data['_folder'], '/', $instance); $data['_folder'] = !$slash ? '' : substr($data['_folder'], 1, $slash - 1); $data['_folder'] = !strlen($data['_folder']) ? "/" : $data['_folder']; $data['_basename'] = $data['slug'] . '.' . $content_type; $data['_filename'] = $data['slug']; $data['_is_entry'] = preg_match(Pattern::ENTRY_FILEPATH, $data['_basename']); $data['_is_page'] = preg_match(Pattern::PAGE_FILEPATH, $data['_basename']); // 404 is special if ($data['_local_path'] === "/404.{$content_type}") { $local_filename = $local_path; // order key: date or datetime } elseif (preg_match(Pattern::DATE_OR_DATETIME, $data['_basename'], $matches)) { // order key: date or datetime $date = $matches[1] . '-' . $matches[2] . '-' . $matches[3]; $time = null; if (Config::getEntryTimestamps() && isset($matches[4])) { $time = substr($matches[4], 0, 2) . ":" . substr($matches[4], 2); $date = $date . " " . $time; $data['slug'] = substr($data['slug'], 16); $data['datetimestamp'] = $data['_order_key']; } else { $data['slug'] = substr($data['slug'], 11); } $data['_order_key'] = strtotime($date); $data['datestamp'] = $data['_order_key']; $data['date'] = Date::format(Config::getDateFormat(), $data['_order_key']); $data['time'] = $time ? Date::format(Config::getTimeFormat(), $data['_order_key']) : null; // order key: slug is page, back up a level } elseif ($data['slug'] == 'page' && preg_match(Pattern::NUMERIC, substr($data['_local_path'], Helper::strrpos_count($data['_local_path'], '/', 1)), $matches)) { // order key: slug is page, back up a level $data['_order_key'] = $matches[1]; $data['numeric'] = $data['_order_key']; // order key: numeric } elseif (preg_match(Pattern::NUMERIC, $data['_basename'], $matches)) { // order key: numeric $data['_order_key'] = $matches[1]; $data['numeric'] = $data['_order_key']; $data['slug'] = substr($data['slug'], strlen($matches[1]) + 1); // order key: other } else { // order key: other $data['_order_key'] = $data['_basename']; } // determine url $data['url'] = preg_replace('#/__?#', '/', $local_filename); // remove any content type extensions from the end of filename if (substr($data['url'], -$content_type_length) === '.' . $content_type) { $data['url'] = substr($data['url'], 0, strlen($data['url']) - $content_type_length); } // remove any base pages from filename if (substr($data['url'], -5) == '/page') { $data['url'] = substr($data['url'], 0, strlen($data['url']) - 5); } // add the site root $data['url'] = Path::tidy(Config::getSiteRoot() . $data['url']); // add the site URL to get the permalink $data['permalink'] = Path::tidy(Config::getSiteURL() . $data['url']); // new content if (!isset($cache['content'][$data['_folder']]) || !is_array($cache['content'][$data['_folder']])) { $cache['content'][$data['_folder']] = array(); } $slug_with_extension = $data['_filename'] == 'page' ? substr($data['url'], strrpos($data['url'], '/') + 1) . '/' . $data['_filename'] . "." . $content_type : $data['_filename'] . "." . $content_type; $cache['content'][$data['_folder']][$slug_with_extension] = array('folder' => $data['_folder'], 'path' => $local_path, 'file' => $slug_with_extension, 'url' => $data['url'], 'data' => $data); $cache['urls'][$data['url']] = array('folder' => $data['_folder'], 'path' => $local_path, 'file' => $slug_with_extension); $changed_urls[$data['url']] = true; } } // loop through all cached content for deleted files // this isn't as expensive as you'd think in real-world situations foreach ($cache['content'] as $folder => $folder_contents) { foreach ($folder_contents as $path => $data) { if (File::exists($full_content_root . $data['path'])) { // still here, keep it continue; } $files_changed = true; // get URL $url = isset($cache['content'][$folder][$path]['url']) ? $cache['content'][$folder][$path]['url'] : null; // only remove from URLs list if not in changed URLs list if (!isset($changed_urls[$url]) && !is_null($url)) { // remove from url cache unset($cache['urls'][$url]); } // remove from content cache unset($cache['content'][$folder][$path]); } } // build taxonomy cache // only happens if files were added, updated, or deleted above if ($files_changed) { $taxonomies = Config::getTaxonomies(); $force_lowercase = Config::getTaxonomyForceLowercase(); $case_sensitive = Config::getTaxonomyCaseSensitive(); $cache['taxonomies'] = array(); // rebuild taxonomies if (count($taxonomies)) { // set up taxonomy array foreach ($taxonomies as $taxonomy) { $cache['taxonomies'][$taxonomy] = array(); } // loop through content to build cached array foreach ($cache['content'] as $pages) { foreach ($pages as $item) { $data = $item['data']; // loop through the types of taxonomies foreach ($taxonomies as $taxonomy) { // if this file contains this type of taxonomy if (isset($data[$taxonomy])) { $values = Helper::ensureArray($data[$taxonomy]); // add the file name to the list of found files for a given taxonomy value foreach ($values as $value) { if (!$value) { continue; } $key = !$case_sensitive ? strtolower($value) : $value; if (!isset($cache['taxonomies'][$taxonomy][$key])) { $cache['taxonomies'][$taxonomy][$key] = array('name' => $force_lowercase ? strtolower($value) : $value, 'files' => array()); } array_push($cache['taxonomies'][$taxonomy][$key]['files'], $data['url']); } } } } } } // build structure cache $structure = array(); $home = Path::tidy('/' . Config::getSiteRoot() . '/'); foreach ($cache['content'] as $pages) { foreach ($pages as $item) { // set up base variables $parent = null; // Trim off home and any /page.md ending so that all URLs are treated // equally regardless of page type. $order_key = str_replace('/page.md', '', str_replace($home, '', $item['path'])); $sub_order_key = $item['data']['_order_key']; // does this have a parent (and if so, what is it?) if ($item['url'] !== $home) { $parent = $home; $depth = substr_count(str_replace($home, '/', $item['url']), '/'); $last_slash = strrpos($item['url'], '/', 1); $last_order_slash = strrpos($order_key, '/', 0); if ($last_slash !== false) { $parent = substr($item['url'], 0, $last_slash); } if ($last_order_slash !== false) { $order_key = substr($order_key, 0, $last_order_slash); } if ($item['data']['_is_page']) { $type = $item['data']['slug'] == 'page' ? 'folder' : 'page'; } else { $type = 'entry'; } } else { $depth = 0; $type = 'folder'; $order_key = $home; } $structure[$item['url']] = array('parent' => $parent, 'is_entry' => $item['data']['_is_entry'], 'is_page' => $item['data']['_is_page'], 'is_hidden' => $item['data']['_is_hidden'], 'is_draft' => $item['data']['_is_draft'], 'depth' => $depth, 'order_key' => $order_key ? $order_key : $sub_order_key, 'sub_order_key' => $sub_order_key, 'type' => $type); } } } // mark ending of content cache measuring Debug::markEnd($content_hash); if (!Config::get('disable_member_cache')) { // build member cache // ---------------------------------------------------------------- // start measuring $member_hash = Debug::markStart('caching', 'member'); // grab a list of existing members $users = File::globRecursively(Path::tidy(Config::getConfigPath() . '/users/*'), 'yaml'); // clone for reuse, set up our list of updated users $updated = array(); $current_users = array(); foreach ($users as $user) { $local_file = Path::trimFilesystemFromContent(Path::standardize($user)); // add to current users $current_users[] = $local_file; // is this updated? if ($last && File::getLastModified($user) >= $last) { $updated[] = $local_file; } } // get users from the file $members = unserialize(File::get($members_file)); // get a diff of users we know about and files currently existing $known_users = array(); if (!empty($members)) { foreach ($members as $username => $member_data) { $known_users[$username] = $member_data['_path']; } } // create a master list of users that need updating $changed_users = array_unique(array_merge(array_diff($current_users, $known_users), $updated)); $removed_users = array_diff($known_users, $current_users); if (count($changed_users)) { $members_changed = true; foreach ($changed_users as $user_file) { // file parsing $last_slash = strrpos($user_file, '/') + 1; $last_dot = strrpos($user_file, '.'); $username = substr($user_file, $last_slash, $last_dot - $last_slash); $content = substr(File::get($user_file), 3); $divide = strpos($content, "\n---"); $data = YAML::parse(trim(substr($content, 0, $divide))); $bio_raw = trim(substr($content, $divide + 4)); $data['_path'] = $user_file; if ($bio_raw) { $data['biography'] = 'true'; $data['biography_raw'] = 'true'; } $members[$username] = $data; } } // loop through all cached content for deleted files // this isn't as expensive as you'd think in real-world situations if (!empty($removed_users)) { $members_changed = true; $members = array_diff_key($members, $removed_users); } // mark ending of member cache measuring Debug::markEnd($member_hash); } // write to caches // -------------------------------------------------------------------- // add file-writing to content-cache actions $content_hash = Debug::markStart('caching', 'content'); if ($files_changed) { // store the content cache if (File::put($cache_file, serialize($cache)) === false) { if (!File::isWritable($cache_file)) { Log::fatal('Cache folder is not writable.', 'core', 'content-cache'); } Log::fatal('Could not write to the cache.', 'core', 'content-cache'); return false; } // store the structure cache if (File::put($structure_file, serialize($structure)) === false) { if (!File::isWritable($structure_file)) { Log::fatal('Structure cache file is not writable.', 'core', 'structure-cache'); } Log::fatal('Could not write to the structure cache.', 'core', 'structure-cache'); return false; } } // mark ending of content cache file write measuring Debug::markEnd($content_hash); // add file-writing to settings-cache actions $settings_hash = Debug::markStart('caching', 'settings'); // store the settings cache if ($settings_changed) { if (File::put($settings_file, serialize($settings)) === false) { if (!File::isWritable($settings_file)) { Log::fatal('Settings cache file is not writable.', 'core', 'settings-cache'); } Log::fatal('Could not write to the settings cache file.', 'core', 'settings-cache'); return false; } } // mark ending of settings cache file write measuring Debug::markEnd($settings_hash); if (!Config::get('disable_member_cache')) { // add file-writing to settings-cache actions $member_hash = Debug::markStart('caching', 'member'); // store the members cache if ($members_changed) { if (File::put($members_file, serialize($members)) === false) { if (!File::isWritable($members_file)) { Log::fatal('Member cache file is not writable.', 'core', 'member-cache'); } Log::fatal('Could not write to the member cache file.', 'core', 'member-cache'); return false; } } // mark ending of member cache file write measuring Debug::markEnd($member_hash); } File::put($time_file, $now - 1); return true; }
$call = '?a=get_language_file&v=' . $version . '&l=' . $languageToLoad; $call .= '&f=' . $file; $fileData = getFileDataFromURL($updateUrl . $call); if (false === $fileData || $fileData == '') { $msg = 'Fatal error: error downloading file \'' . $file . '\'!'; $msg .= ' Please try again.'; $message[] = Html::getErrorMsg($msg); } else { // save file to disk $file = $path . '/' . $file . '.php'; $fp = @fopen($file, 'wb'); if ($fp) { fwrite($fp, $fileData); fclose($fp); if (!File::isWritable($file, 0644)) { File::isWritable($file, 0777); } $msg = ' File \'' . $file . '\' saved succesfully.'; $message[] = Html::getOkMsg($msg); // remove file from todo list $fileIndex = count($_SESSION['get_language']) - 1; unset($_SESSION['get_language'][$fileIndex]); } else { $msg = 'Fatal error: couldn\'t write file \'' . $file; $msg .= '\' to \'' . $path . '\''; $message[] = Html::getErrorMsg($msg); } } } else { $inProgress = 0; $msg = 'Finished installing language \'' . $languageToLoad;