/** * @route ajax/clear_cache{_string} * @param string $key */ public function clearCache(string $key) { $secret = $this->config('cache-secret'); if ($secret === null) { \Airship\json_response(['status' => 'ERROR', 'message' => 'Cache-clearing secret value not set']); } if (!\hash_equals($secret, $key)) { \Airship\json_response(['status' => 'ERROR', 'message' => 'Invalid cache-clearing secret value']); } \Airship\clear_cache(); \Airship\json_response(['status' => 'OK', 'message' => 'Cache cleared!']); }
/** * @route gadgets/universal */ public function manageUniversal() { $cabins = $this->getCabinNamespaces(); $gadgets = \Airship\loadJSON(ROOT . '/config/gadgets.json'); if (!$this->can('update')) { \Airship\redirect($this->airship_cabin_prefix . '/gadgets'); } $post = $this->post(GadgetsFilter::fromConfig(\array_keys($gadgets))); if ($post) { if ($this->updateUniversalGadgets($gadgets, $post)) { \Airship\clear_cache(); \Airship\redirect($this->airship_cabin_prefix . '/gadgets/universal'); } } $this->lens('gadget_manage', ['cabins' => $cabins, 'gadgets' => $gadgets, 'title' => \__('Manage Universal Gadgets')]); }
/** * Update a blog post * * @param array $post * @param array $old * @param bool $publish * @return bool */ public function updatePost(array $post, array $old, bool $publish = false) : bool { $this->db->beginTransaction(); $postUpdates = []; // First, update the hull_blog_posts entry if (!empty($post['author'])) { if ($post['author'] !== $old['author']) { $postUpdates['author'] = (int) $post['author']; } } if ($post['description'] !== $old['description']) { $postUpdates['description'] = (string) $post['description']; } if ($post['format'] !== $old['format']) { $postUpdates['format'] = (string) $post['format']; } if ($post['slug'] !== $old['slug']) { $bm = (string) $old['blogmonth'] < 10 ? '0' . $old['blogmonth'] : $old['blogmonth']; $exists = $this->db->cell('SELECT count(*) FROM view_hull_blog_list WHERE blogmonth = ? AND blogyear = ? AND slug = ?', $old['blogyear'], $bm, $post['slug']); if ($exists > 0) { // Slug collision return false; } $postUpdates['slug'] = (string) $post['slug']; if (!empty($post['redirect_slug'])) { $oldUrl = \implode('/', ['blog', $old['blogyear'], $bm, $old['slug']]); $newUrl = \implode('/', ['blog', $old['blogyear'], $bm, $post['slug']]); $this->db->insert('airship_custom_redirect', ['oldpath' => $oldUrl, 'newpath' => $newUrl, 'cabin' => $this->cabin, 'same_cabin' => true]); } } $now = new \DateTime(); if (!empty($post['published'])) { try { $now = new \DateTime($post['published']); } catch (\Throwable $ex) { } } if (!\array_key_exists('category', $post)) { $post['category'] = 0; } if ($post['category'] !== $old['category']) { $postUpdates['category'] = (int) $post['category']; } if ($publish) { $postUpdates['status'] = true; $postUpdates['cache'] = !empty($post['cache']); // Let's set the publishing time. $postUpdates['published'] = $now->format(\AIRSHIP_DATE_FORMAT); } if ($post['title'] !== $old['title']) { $postUpdates['title'] = (string) $post['title']; } if (!empty($postUpdates)) { $this->db->update('hull_blog_posts', $postUpdates, ['postid' => $old['postid']]); } do { $unique = \Airship\uniqueId(); $exists = $this->db->exists('SELECT COUNT(*) FROM hull_blog_post_versions WHERE uniqueid = ?', $unique); } while ($exists); // Second, create a new entry in hull_blog_post_versions $this->db->insert('hull_blog_post_versions', ['post' => $old['postid'], 'body' => $post['blog_post_body'], 'format' => $post['format'], 'live' => $publish, 'metadata' => \json_encode($post['metadata'] ?? []), 'published_by' => $publish ? $this->getActiveUserId() : null, 'uniqueid' => $unique]); if (empty($old['tags'])) { $old['tags'] = []; } if (empty($post['tags'])) { $post['tags'] = []; } // Now let's update the tag relationships $tag_ins = \array_diff($post['tags'], $old['tags']); $tag_del = \array_diff($old['tags'], $post['tags']); foreach ($tag_del as $del) { $this->db->delete('hull_blog_post_tags', ['postid' => $old['postid'], 'tagid' => $del]); } foreach ($tag_ins as $ins) { $this->db->insert('hull_blog_post_tags', ['postid' => $old['postid'], 'tagid' => $ins]); } if ($publish) { \Airship\clear_cache(); } return $this->db->commit(); }
/** * @param string $motifName * @param array $config * @return bool */ protected function saveMotifConfig(string $motifName, array $config = []) : bool { $res = \Airship\saveJSON(ROOT . '/config/motifs/' . $motifName . '.json', $config); \Airship\clear_cache(); return $res; }
/** * Create a new page (and initial page version) * * @param int $pageId * @param array $post * @param bool $publish (This is set to FALSE by the Landing if the permission check fails) * @param bool|null $raw * @param bool $cache * @return bool */ public function updatePage(int $pageId, array $post = [], bool $publish = false, $raw = null, bool $cache = false) : bool { $this->db->beginTransaction(); if ($publish) { $this->db->update('airship_custom_page', ['active' => true, 'cache' => $cache], ['pageid' => $pageId]); } if ($raw === null) { $raw = $this->db->cell('SELECT raw FROM airship_custom_page_version WHERE page = ? ORDER BY versionid DESC LIMIT 1', $pageId); } $last_copy = $this->db->row('SELECT * FROM airship_custom_page_version WHERE page = ? ORDER BY versionid DESC LIMIT 1', $pageId); // Short circuit the needless inserts if ($last_copy['raw'] === (bool) $raw && $last_copy['formatting'] === (string) $post['format'] && \json_decode($last_copy['metadata'], true) === $post['metadata'] && $last_copy['body'] === (string) $post['page_body']) { // Are we publishing a previously unpublished edition? if ($publish && !$last_copy['publish']) { $this->db->update('airship_custom_page_version', ['published' => $publish], ['page' => $pageId]); } \Airship\clear_cache(); return $this->db->commit(); } $meta = !empty($post['metadata']) ? \json_encode($post['metadata']) : '[]'; // Create the next version of the new page $this->db->insert('airship_custom_page_version', ['page' => (int) $pageId, 'published' => (bool) $publish, 'uniqueid' => $this->uniqueId('airship_custom_page_version'), 'raw' => (bool) $raw, 'formatting' => (string) $post['format'] ?? 'HTML', 'bridge_user' => (int) $this->getActiveUserId(), 'metadata' => (string) $meta, 'body' => (string) ($post['page_body'] ?? '')]); if ($publish) { // Nuke the page cache \Airship\clear_cache(); } return $this->db->commit(); }
/** * We just need to clear the template caches and the cabin data. * * @return bool */ public function clearCache() : bool { \Airship\clear_cache(); $dirs = ['csp_hash', 'csp_static', 'html_purifier', 'markdown', 'rst', 'static', 'twig']; foreach ($dirs as $dir) { if (!\is_dir(ROOT . '/tmp/cache/' . $dir)) { continue; } foreach (\Airship\list_all_files(ROOT . '/tmp/cache/' . $dir) as $file) { if ($file === ROOT . '/tmp/cache/' . $dir . '/.gitignore') { continue; } \unlink($file); } } if (\file_exists(ROOT . '/tmp/cache/cabin_data.json')) { \unlink(ROOT . '/tmp/cache/cabin_data.json'); } \clearstatcache(); return true; }
/** * @route admin/settings */ public function manageSettings() { $state = State::instance(); $settings = ['universal' => $state->universal]; $post = $this->post(new SettingsFilter()); if (!empty($post)) { if ($this->saveSettings($post)) { \Airship\clear_cache(); \Airship\redirect($this->airship_cabin_prefix . '/admin/settings', ['msg' => 'saved']); } else { $this->log('Could not save new settings', LogLevel::ALERT); } } // Load individual files... $settings['cabins'] = $this->loadJSONConfigFile('cabins.json'); $settings['content_security_policy'] = $this->loadJSONConfigFile('content_security_policy.json'); $settings['keyring'] = $this->loadJSONConfigFile('keyring.json'); foreach (\Airship\list_all_files(ROOT . '/config/supplier_keys/', 'json') as $supplier) { $name = \Airship\path_to_filename($supplier, true); $settings['suppliers'][$name] = \Airship\loadJSON($supplier); } $this->lens('admin_settings', ['active_link' => 'bridge-link-admin-settings', 'config' => $settings, 'groups' => $this->acct->getGroupTree()]); }
<?php declare (strict_types=1); use Airship\Engine\{Gears, Hail, State}; /** * @global State $state * @global Hail $hail */ // Always check for changes to channel keys before initiating update require_once __DIR__ . '/channel.php'; /** * Initialize the automatic updater service * @var \Airship\Engine\Continuum */ $autoUpdater = Gears::get('AutoUpdater', $hail); if (IDE_HACKS) { // Just for the sake of auto-completion: $autoUpdater = new \Airship\Engine\Continuum($hail); } $state->logger->info('Automatic update started'); try { $autoUpdater->doUpdateCheck(); } catch (\Throwable $ex) { $state->logger->critical('Tree update failed: ' . \get_class($ex), \Airship\throwableToArray($ex)); exit(255); } $state->logger->info('Automatic update concluded'); \Airship\clear_cache(); exit(0);