362 lines
9.3 KiB
PHP
362 lines
9.3 KiB
PHP
<?php
|
|
/**
|
|
* @package solo
|
|
* @copyright Copyright (c)2014-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
|
|
* @license GNU General Public License version 3, or later
|
|
*/
|
|
|
|
namespace Solo\View\Main;
|
|
|
|
use Akeeba\Engine\Factory;
|
|
use Akeeba\Engine\Platform;
|
|
use Awf\Mvc\Model;
|
|
use Awf\Mvc\View;
|
|
use Awf\Utils\Template;
|
|
use RuntimeException;
|
|
use Solo\Helper\Status;
|
|
use Solo\Model\Main;
|
|
use Solo\Model\Stats;
|
|
|
|
class Html extends View
|
|
{
|
|
/**
|
|
* Active backup profile ID
|
|
*
|
|
* @var int
|
|
*/
|
|
public $profile;
|
|
|
|
/**
|
|
* A list of Akeeba Engine backup profiles in a format suitable for use with Html\Select::genericList
|
|
*
|
|
* @var array
|
|
*/
|
|
public $profileList;
|
|
|
|
/**
|
|
* List of profiles to display as Quick Icons in the control panel page
|
|
*
|
|
* @var array Array of stdClass objects
|
|
*/
|
|
public $quickIconProfiles;
|
|
|
|
/**
|
|
* Do I have to ask the user to provide a Download ID?
|
|
*
|
|
* @var bool
|
|
*/
|
|
public $needsDownloadId;
|
|
|
|
/**
|
|
* Did a Core edition user provide a Download ID instead of installing Akeeba Backup Professional?
|
|
*
|
|
* @var bool
|
|
*/
|
|
public $warnCoreDownloadId;
|
|
|
|
/**
|
|
* If front-end backup is enabled and the secret word has an issue (too insecure) we populate this variable
|
|
*
|
|
* @var string
|
|
*/
|
|
public $frontEndSecretWordIssue;
|
|
|
|
/**
|
|
* In case the existing Secret Word is insecure we generate a new one. This variable contains the new Secret Word.
|
|
*
|
|
* @var string
|
|
*/
|
|
public $newSecretWord;
|
|
|
|
/**
|
|
* Should I have the browser ask for desktop notification permissions?
|
|
*
|
|
* @var bool
|
|
*/
|
|
public $desktop_notifications;
|
|
|
|
/**
|
|
* If anonymous statistics collection is enabled and we have to collect statistics this will include the HTML for
|
|
* the IFRAME that performs the anonymous stats collection.
|
|
*
|
|
* @var string
|
|
*/
|
|
public $statsIframe;
|
|
|
|
/**
|
|
* Is the mbstring extension installed and enabled? This is required by Joomla and Akeeba Backup to correctly work
|
|
*
|
|
* @var bool
|
|
*/
|
|
public $checkMbstring = true;
|
|
|
|
/**
|
|
* ACL checks. This is set to the View by the Controller.
|
|
*
|
|
* @see \Solo\Controller\Main::onBeforeDefault()
|
|
*
|
|
* @var array
|
|
*/
|
|
public $aclChecks = [];
|
|
|
|
/**
|
|
* The HTML for the backup status cell
|
|
*
|
|
* @var string
|
|
*/
|
|
public $statusCell = '';
|
|
|
|
/**
|
|
* HTML for the warnings (status details)
|
|
*
|
|
* @var string
|
|
*/
|
|
public $detailsCell = '';
|
|
|
|
/**
|
|
* Details of the latest backup as HTML
|
|
*
|
|
* @var string
|
|
*/
|
|
public $latestBackupCell = '';
|
|
|
|
/**
|
|
* Do I have stuck updates pending?
|
|
*
|
|
* @var bool
|
|
*/
|
|
public $stuckUpdates = false;
|
|
|
|
/**
|
|
* Should I prompt the user ot run the configuration wizard?
|
|
*
|
|
* @var bool
|
|
*/
|
|
public $promptForConfigurationWizard = false;
|
|
|
|
/**
|
|
* How many warnings do I have to display?
|
|
*
|
|
* @var int
|
|
*/
|
|
public $countWarnings = 0;
|
|
|
|
/**
|
|
* The fancy formatted changelog of the component
|
|
*
|
|
* @var string
|
|
*/
|
|
public $formattedChangelog = '';
|
|
|
|
/**
|
|
* Timestamp when the Core user last dismissed the upsell to Pro
|
|
*
|
|
* @var int
|
|
* @since 7.0.0
|
|
*/
|
|
public $lastUpsellDismiss = 0;
|
|
|
|
/**
|
|
* Is the output directory under the site's root?
|
|
*
|
|
* @var bool
|
|
* @since 7.0.3
|
|
*/
|
|
public $isOutputDirectoryUnderSiteRoot = false;
|
|
|
|
/**
|
|
* Does the output directory have the expected security files?
|
|
*
|
|
* @var bool
|
|
* @since 7.0.3
|
|
*/
|
|
public $hasOutputDirectorySecurityFiles = false;
|
|
|
|
public function onBeforeMain()
|
|
{
|
|
/** @var Main $model */
|
|
$model = $this->getModel();
|
|
$statusHelper = Status::getInstance();
|
|
$session = $this->container->segment;
|
|
|
|
$this->profile = Platform::getInstance()->get_active_profile();
|
|
$this->profileList = $model->getProfileList();
|
|
$this->quickIconProfiles = $model->getQuickIconProfiles();
|
|
$this->statusCell = $statusHelper->getStatusCell();
|
|
$this->detailsCell = $statusHelper->getQuirksCell();
|
|
$this->latestBackupCell = $statusHelper->getLatestBackupDetails();
|
|
$this->needsDownloadId = $model->needsDownloadID();
|
|
$this->warnCoreDownloadId = $model->mustWarnAboutDownloadIdInCore();
|
|
$this->checkMbstring = $model->checkMbstring();
|
|
$this->frontEndSecretWordIssue = $model->getFrontendSecretWordError();
|
|
$this->newSecretWord = $session->get('newSecretWord', null);
|
|
$this->stuckUpdates = ($this->container->appConfig->get('updatedb', 0) == 1);
|
|
$this->promptForConfigurationWizard = Factory::getConfiguration()->get('akeeba.flag.confwiz', 0) == 0;
|
|
$this->countWarnings = count(Factory::getConfigurationChecks()->getDetailedStatus());
|
|
$this->desktop_notifications = Platform::getInstance()->get_platform_configuration_option('desktop_notifications', '0') ? 1 : 0;
|
|
$this->formattedChangelog = $this->formatChangelog();
|
|
$this->lastUpsellDismiss = $this->container->appConfig->get('lastUpsellDismiss', 0);
|
|
$this->hasOutputDirectorySecurityFiles = $model->hasOutputDirectorySecurityFiles();
|
|
$this->isOutputDirectoryUnderSiteRoot = $model->isOutputDirectoryUnderSiteRoot();
|
|
|
|
// Solo: the output directory may be under Solo's root, not the site's root. It's equally important to me.
|
|
if (!$this->container->segment->get('insideCMS', false))
|
|
{
|
|
$this->isOutputDirectoryUnderSiteRoot |= $model->isOutputDirectoryUnderSiteRoot(null, true);
|
|
}
|
|
|
|
/** @var Stats $statsModel */
|
|
$statsModel = Model::getTmpInstance($this->container->application_name, 'Stats', $this->container);
|
|
$this->statsIframe = $statsModel->collectStatistics(true);
|
|
|
|
// Load the Javascript for this page
|
|
Template::addJs('media://js/solo/main.js', $this->container->application);
|
|
|
|
|
|
$router = $this->container->router;
|
|
$document = $this->container->application->getDocument();
|
|
|
|
$document->addScriptOptions('akeeba.System.notification.hasDesktopNotification', $this->desktop_notifications);
|
|
$document->addScriptOptions('akeeba.ControlPanel.checkOutDirUrl', $router->route('index.php?view=main&format=raw&task=checkOutputDirectory'));
|
|
$document->addScriptOptions('akeeba.ControlPanel.outputDirUnderSiteRoot', (bool) $this->isOutputDirectoryUnderSiteRoot);
|
|
$document->addScriptOptions('akeeba.ControlPanel.hasSecurityFiles', (bool) $this->hasOutputDirectorySecurityFiles);
|
|
$document->addScriptOptions('akeeba.ControlPanel.cloudFlareURN', 'CLOUDFLARE::' . Template::parsePath('media://js/solo/system.js', false, $this->getContainer()->application));
|
|
$document->addScriptOptions('akeeba.ControlPanel.updateInfoURL', $router->route('index.php?view=main&format=raw&task=getUpdateInformation&' . $this->getContainer()->session->getCsrfToken()->getValue() . '=1'));
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Performs automatic access control checks
|
|
*
|
|
* @param string $view The view being considered
|
|
* @param string $task The task being considered
|
|
*
|
|
* @return bool True if access is allowed
|
|
*
|
|
* @throws RuntimeException
|
|
*/
|
|
public function canAccess($view, $task)
|
|
{
|
|
$view = strtolower($view);
|
|
$task = strtolower($task);
|
|
|
|
if (!isset($this->aclChecks[$view]))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (!isset($this->aclChecks[$view][$task]))
|
|
{
|
|
if (!isset($this->aclChecks[$view]['*']))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
$requiredPrivileges = $this->aclChecks[$view]['*'];
|
|
}
|
|
else
|
|
{
|
|
$requiredPrivileges = $this->aclChecks[$view][$task];
|
|
}
|
|
|
|
$user = $this->container->userManager->getUser();
|
|
|
|
foreach ($requiredPrivileges as $privilege)
|
|
{
|
|
if (!$user->getPrivilege('akeeba.' . $privilege))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
protected function formatChangelog($onlyLast = false)
|
|
{
|
|
$container = $this->getContainer();
|
|
$filePath = isset($container['changelogPath']) ? $container['changelogPath'] : null;
|
|
|
|
if (empty($filePath))
|
|
{
|
|
$filePath = APATH_BASE . '/CHANGELOG.php';
|
|
}
|
|
|
|
$ret = '';
|
|
$file = $filePath;
|
|
$lines = @file($file);
|
|
|
|
if (empty($lines))
|
|
{
|
|
return $ret;
|
|
}
|
|
|
|
array_shift($lines);
|
|
|
|
foreach ($lines as $line)
|
|
{
|
|
$line = trim($line);
|
|
|
|
if (empty($line))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
$type = substr($line, 0, 1);
|
|
|
|
switch ($type)
|
|
{
|
|
case '=':
|
|
continue 2;
|
|
break;
|
|
|
|
case '+':
|
|
$ret .= "\t" . '<li><span class="akeeba-label--green">Added</span> ' . htmlentities(trim(substr($line, 2))) . "</li>\n";
|
|
break;
|
|
|
|
case '-':
|
|
$ret .= "\t" . '<li><span class="akeeba-label--grey">Removed</span> ' . htmlentities(trim(substr($line, 2))) . "</li>\n";
|
|
break;
|
|
|
|
case '~':
|
|
case '^':
|
|
$ret .= "\t" . '<li><span class="akeeba-label--grey">Changed</span> ' . htmlentities(trim(substr($line, 2))) . "</li>\n";
|
|
break;
|
|
|
|
case '*':
|
|
$ret .= "\t" . '<li><span class="akeeba-label--red">Security</span> ' . htmlentities(trim(substr($line, 2))) . "</li>\n";
|
|
break;
|
|
|
|
case '!':
|
|
$ret .= "\t" . '<li><span class="akeeba-label--orange">Important</span> ' . htmlentities(trim(substr($line, 2))) . "</li>\n";
|
|
break;
|
|
|
|
case '#':
|
|
$ret .= "\t" . '<li><span class="akeeba-label--teal">Fixed</span> ' . htmlentities(trim(substr($line, 2))) . "</li>\n";
|
|
break;
|
|
|
|
default:
|
|
if (!empty($ret))
|
|
{
|
|
$ret .= "</ul>";
|
|
if ($onlyLast)
|
|
{
|
|
return $ret;
|
|
}
|
|
}
|
|
|
|
if (!$onlyLast)
|
|
{
|
|
$ret .= "<h4>$line</h4>\n";
|
|
}
|
|
$ret .= "<ul class=\"akeeba-changelog\">\n";
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
return $ret;
|
|
}
|
|
}
|