Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache core and plugin updates #856

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 15 additions & 18 deletions qa-content/qa-admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@

var qa_recalc_running = 0;

window.onbeforeunload = function(event)
{
window.onbeforeunload = function (event) {
if (qa_recalc_running > 0) {
event = event || window.event;
var message = qa_warning_recalc;
Expand All @@ -43,8 +42,9 @@ function qa_recalc_click(state, elem, value, noteid)

document.getElementById(noteid).innerHTML = '';
elem.qa_original_value = elem.value;
if (value)
if (value) {
elem.value = value;
}

qa_recalc_update(elem, state, noteid);
}
Expand Down Expand Up @@ -147,36 +147,33 @@ function qa_admin_click(target)
return false;
}

function qa_version_check(uri, version, elem, isCore)
function qa_version_check(uri, version, elem, componentId)
{
qa_ajax_post(
'version',
{uri: uri, version: version, isCore: isCore},
function (response) {
if (response.result === 'error') {
alert(response.error.message);
var params = {uri: uri, version: version, componentId: componentId};
qa_ajax_post('version', params, function (response) {
if (response.result === 'error') {
alert(response.error.message);

return;
}
return;
}

document.getElementById(elem).innerHTML = response.html;
}, 1
);
document.getElementById(elem).innerHTML = response.html;
}, 1);
}

function qa_version_check_array(versionChecks)
{
for (var i = 0; i < versionChecks.length; i++) {
qa_version_check(versionChecks[i].uri, versionChecks[i].version, versionChecks[i].elem, false)
qa_version_check(versionChecks[i].uri, versionChecks[i].version, versionChecks[i].elem, versionChecks[i].componentId);
}
}

function qa_get_enabled_plugins_hashes()
{
var hashes = [];
$('[id^=plugin_enabled]:checked').each(
function(idx, elem) {
hashes.push(elem.id.replace("plugin_enabled_", ""));
function (idx, elem) {
hashes.push(elem.id.replace('plugin_enabled_', ''));
}
);

Expand Down
15 changes: 10 additions & 5 deletions qa-include/ajax/version.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,26 +36,27 @@

$uri = qa_post_text('uri');
$currentVersion = qa_post_text('version');
$isCore = qa_post_text('isCore') === "true";
$componentId = qa_post_text('componentId');

if ($isCore) {
if ($componentId === 'core') {
$contents = qa_retrieve_url($uri);

if (strlen($contents) > 0) {
if (qa_qa_version_below($contents)) {
if (version_compare($currentVersion, $contents) < 0) {
$versionResponse =
'<a href="https://github.com/q2a/question2answer/releases" style="color:#d00;">' .
qa_lang_html_sub('admin/version_get_x', qa_html('v' . $contents)) .
'</a>';
} else {
$versionResponse = qa_html($contents); // Output the current version number
}

(new \Q2A\Update\CoreUpdateManager())->setCachedVersion($contents);
} else {
$versionResponse = qa_lang_html('admin/version_latest_unknown');
}
} else {
$metadataUtil = new \Q2A\Util\Metadata();
$metadata = $metadataUtil->fetchFromUrl($uri);
$metadata = (new \Q2A\Util\Metadata())->fetchFromUrl($uri);

if (strlen(@$metadata['version']) > 0) {
if (version_compare($currentVersion, $metadata['version']) < 0) {
Expand All @@ -72,6 +73,10 @@
} else {
$versionResponse = qa_lang_html_sub('admin/version_get_x', qa_html('v' . $metadata['version']));

if ($componentId !== null) {
(new \Q2A\Plugin\PluginManager())->addCachedUpdate($componentId, $metadata['version']);
}

if (strlen(@$metadata['uri'])) {
$versionResponse = '<a href="' . qa_html($metadata['uri']) . '" style="color:#d00;">' . $versionResponse . '</a>';
}
Expand Down
27 changes: 27 additions & 0 deletions qa-include/app/options.php
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,33 @@ function qa_load_options_results($results)
}


/**
* Get option $name from the database
* @param string $name
* @return string
*/
function qa_db_get_option($name)
{
global $qa_options_cache, $qa_options_loaded;

$selectSpec = [
'columns' => array('content'),
'source' => '^options WHERE title = #',
'arrayvalue' => 'content',
'single' => true,
'arguments' => [$name],
];

$value = qa_db_single_select($selectSpec);

if (isset($qa_options_loaded)) {
$qa_options_cache[$name] = $value;
}

return $value;
}


/**
* Set an option $name to $value (application level) in both cache and database, unless
* $todatabase=false, in which case set it in the cache only
Expand Down
2 changes: 1 addition & 1 deletion qa-include/pages/admin/admin-default.php
Original file line number Diff line number Diff line change
Expand Up @@ -1076,7 +1076,7 @@ function qa_optionfield_make_select(&$optionfield, $options, $value, $default)
$updatehtml = '(<span id="' . $elementid . '">...</span>)';

$qa_content['script_onloads'][] = array(
"qa_version_check(" . qa_js($metadata['update_uri']) . ", " . qa_js($metadata['version'], true) . ", " . qa_js($elementid) . ", false);"
"qa_version_check(" . qa_js($metadata['update_uri']) . ", " . qa_js($metadata['version'], true) . ", " . qa_js($elementid) . ", null);"
);

}
Expand Down
20 changes: 15 additions & 5 deletions qa-src/Controllers/Admin/Plugins.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public function index()

$pluginManager = new \Q2A\Plugin\PluginManager();
$pluginManager->cleanRemovedPlugins();
$cachedUpdates = $pluginManager->getCachedUpdates(true);

$enabledPlugins = $pluginManager->getEnabledPlugins();
$fileSystemPlugins = $pluginManager->getFilesystemPlugins();
Expand Down Expand Up @@ -178,18 +179,27 @@ public function index()
$authorhtml = '';
}

$pluginId = md5($pluginDirectory);
$elementId = 'version_check_' . $pluginId;
if ($shouldCheckForUpdate && $metaver && isset($metadata['update_uri']) && strlen($metadata['update_uri'])) {
$elementid = 'version_check_' . md5($pluginDirectory);

$versionChecks[] = array(
'uri' => $metadata['update_uri'],
'version' => $metadata['version'],
'elem' => $elementid,
'elem' => $elementId,
'componentId' => $pluginId,
);

$updatehtml = '(<span id="' . $elementid . '">...</span>)';
$updatehtml = sprintf('(<span id="%s">...</span>)', $elementId);
} else {
$updatehtml = '';
if (isset($cachedUpdates[$pluginId]) && isset($metadata['uri']) && $metadata['version'] !== $cachedUpdates[$pluginId]) {
$updatehtml = sprintf(
'(<a href="%s" style="color:#d00;">%s</a>)',
qa_html($metadata['uri']),
qa_lang_html_sub('admin/version_get_x', qa_html('v' . $cachedUpdates[$pluginId]))
);
} else {
$updatehtml = '';
}
}

if (isset($metadata['description']))
Expand Down
38 changes: 33 additions & 5 deletions qa-src/Controllers/Admin/Stats.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,16 @@
use Q2A\Controllers\BaseController;
use Q2A\Database\DbConnection;
use Q2A\Middleware\Auth\MinimumUserLevel;
use Q2A\Update\CoreUpdateManager;

/**
* Controller for admin page showing usage statistics and clean-up buttons
*/
class Stats extends BaseController
{
/** @var CoreUpdateManager */
private $coreUpdateManager;

public function __construct(DbConnection $db)
{
require_once QA_INCLUDE_DIR . 'db/recalc.php';
Expand All @@ -37,6 +41,8 @@ public function __construct(DbConnection $db)
parent::__construct($db);

$this->addMiddleware(new MinimumUserLevel(QA_USER_LEVEL_ADMIN));

$this->coreUpdateManager = new CoreUpdateManager();
}

public function index()
Expand Down Expand Up @@ -79,7 +85,7 @@ public function index()
'q2a_latest' => array(
'label' => qa_lang_html('admin/q2a_latest_version'),
'type' => 'custom',
'html' => '<span id="q2a-version">...</span>',
'html' => $this->getUpdateVersionText(),
),

'break0' => array(
Expand Down Expand Up @@ -282,17 +288,39 @@ public function index()
}
}


$qa_content['script_rel'][] = 'qa-content/qa-admin.js?' . QA_VERSION;
$qa_content['script_var']['qa_warning_recalc'] = qa_lang('admin/stop_recalc_warning');

$qa_content['script_onloads'][] = array(
"qa_version_check('https://raw.githubusercontent.com/q2a/question2answer/master/VERSION.txt', " . qa_js(qa_html(QA_VERSION), true) . ", 'q2a-version', true);"
);
if ($this->coreUpdateManager->shouldCheckForUpdate()) {
$qa_content['script_onloads'][] = array(
sprintf("qa_version_check('https://raw.githubusercontent.com/q2a/question2answer/master/VERSION.txt', '%s', 'q2a-version', 'core');", QA_VERSION),
);
}

$qa_content['navigation']['sub'] = qa_admin_sub_navigation();


return $qa_content;
}

/**
* @return string
*/
private function getUpdateVersionText()
{
if ($this->coreUpdateManager->shouldCheckForUpdate()) {
return '<span id="q2a-version">...</span>';
}

$version = $this->coreUpdateManager->getCachedVersion();

if (!isset($version) || $version === QA_VERSION) {
return QA_VERSION;
}

return
'<a href="https://github.com/q2a/question2answer/releases" style="color:#d00;">' .
qa_lang_html_sub('admin/version_get_x', qa_html('v' . $version)) .
'</a>';
}
}
38 changes: 36 additions & 2 deletions qa-src/Plugin/PluginManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ class PluginManager
{
const PLUGIN_DELIMITER = ';';
const OPT_ENABLED_PLUGINS = 'enabled_plugins';
const OPT_LAST_UPDATE_CHECK = 'last_plugin_update_check';
const OPT_LAST_UPDATE_CHECK = 'plugin_update_last_check';
const OPT_PLUGIN_UPDATES_CACHE = 'plugin_update_cache';
const NUMBER_OF_DAYS_TO_CHECK_FOR_UPDATE = 14;

private $loadBeforeDbInit = array();
Expand Down Expand Up @@ -200,9 +201,42 @@ public function shouldCheckForUpdate()
public function performUpdateCheck($time = null)
{
if ($time === null) {
$time = time();
$time = (int)qa_opt('db_time');
}

qa_opt(self::OPT_LAST_UPDATE_CHECK, $time);
$this->setCachedUpdates([]);
}

/**
* @param bool $fromDatabase
* @return array
*/
public function getCachedUpdates($fromDatabase = false)
{
$option = $fromDatabase
? qa_db_get_option(self::OPT_PLUGIN_UPDATES_CACHE)
: qa_opt(self::OPT_PLUGIN_UPDATES_CACHE);

return json_decode($option, true);
}

/**
* @param array $pluginUpdates Key-value array relating MD5 plugin IDs and versions
*/
public function setCachedUpdates($pluginUpdates)
{
qa_opt(self::OPT_PLUGIN_UPDATES_CACHE, json_encode($pluginUpdates));
}

/**
* @param string $componentId
* @param string $version
*/
public function addCachedUpdate($componentId, $version)
{
$pluginUpdates = $this->getCachedUpdates(true);
$pluginUpdates[$componentId] = $version;
$this->setCachedUpdates($pluginUpdates);
}
}
Loading