Commit fd1210bc by lmf

项目初始化版本

后台地址:http://xxxx/admin  默认账户:admin  密码 admin123
记得composer update 初始化vendor
parents

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

/app/etc/config.php
/.gitignore
cache
composer_home
log
page_cache
view_preprocessed
static
errors
media
opt
code
vendor
RewriteEngine on
RewriteCond %{REQUEST_URI} !^/pub/
RewriteCond %{REQUEST_URI} !^/setup/
RewriteCond %{REQUEST_URI} !^/update/
RewriteCond %{REQUEST_URI} !^/dev/
RewriteRule .* /pub/$0 [L]
DirectoryIndex index.php
{"php":"7.4.3","version":"2.18.7:v2.18.7#b3281bbe07e8d45759e9e3e8032b4c5fa3463b21","indent":" ","lineEnding":"\n","rules":{"blank_line_after_namespace":true,"braces":true,"class_definition":true,"constant_case":true,"elseif":true,"function_declaration":true,"indentation_type":true,"line_ending":true,"lowercase_keywords":true,"method_argument_space":{"on_multiline":"ensure_fully_multiline"},"no_break_comment":true,"no_closing_tag":true,"no_spaces_after_function_name":true,"no_spaces_inside_parenthesis":true,"no_trailing_whitespace":true,"no_trailing_whitespace_in_comment":true,"single_blank_line_at_eof":true,"single_class_element_per_statement":{"elements":["property"]},"single_import_per_statement":true,"single_line_after_imports":true,"switch_case_semicolon_to_colon":true,"switch_case_space":true,"visibility_required":true,"encoding":true,"full_opening_tag":true,"array_syntax":{"syntax":"short"},"concat_space":{"spacing":"one"},"include":true,"new_with_braces":true,"no_empty_statement":true,"no_extra_consecutive_blank_lines":true,"no_leading_import_slash":true,"no_leading_namespace_whitespace":true,"no_multiline_whitespace_around_double_arrow":true,"no_multiline_whitespace_before_semicolons":true,"no_singleline_whitespace_before_semicolons":true,"no_trailing_comma_in_singleline_array":true,"no_unused_imports":true,"no_whitespace_in_blank_line":true,"object_operator_without_whitespace":true,"ordered_imports":true,"standardize_not_equals":true,"ternary_operator_spaces":true},"hashes":{"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp6331\\app\\etc\\env.php":4258235100,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp1189\\app\\etc\\env.php":4258235100,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp2048\\app\\etc\\env.php":4258235100,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp2799\\app\\etc\\env.php":3686923414,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp4722\\app\\etc\\env.php":3686923414,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp1\\app\\etc\\env.php":3686923414,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp2\\app\\etc\\env.php":3686923414,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp566\\app\\code\\Magento\\Backend\\view\\adminhtml\\templates\\admin\\login.phtml":1612615526,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp2540\\app\\code\\Magento\\Backend\\view\\adminhtml\\templates\\admin\\login_buttons.phtml":1401038611,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp1516\\app\\code\\Magento\\Backend\\view\\adminhtml\\templates\\admin\\overlay_popup.phtml":2665078040,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp2339\\app\\code\\Magento\\Backend\\view\\adminhtml\\templates\\admin\\page.phtml":4136835805,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp1694\\app\\code\\Magento\\Backend\\view\\adminhtml\\templates\\page\\header.phtml":1812012403,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp385\\app\\code\\Magento\\Backend\\view\\adminhtml\\templates\\page\\header.phtml":1812012403,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp2468\\app\\code\\Magento\\Backend\\view\\adminhtml\\templates\\admin\\login.phtml":1612615526,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp4473\\app\\code\\Magento\\Backend\\view\\adminhtml\\templates\\admin\\login_buttons.phtml":1401038611,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp3538\\app\\code\\Magento\\Backend\\view\\adminhtml\\templates\\admin\\overlay_popup.phtml":2665078040,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp3837\\app\\code\\Magento\\Backend\\view\\adminhtml\\templates\\admin\\access_denied.phtml":3622208428,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp2985\\app\\code\\Magento\\Backend\\view\\adminhtml\\templates\\admin\\formkey.phtml":327288504,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp2852\\app\\code\\Magento\\Backend\\view\\adminhtml\\templates\\admin\\delete_confirm.phtml":421277462,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp150\\app\\code\\Magento\\Backend\\Block\\Page\\Header.php":1659583925,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp2198\\app\\code\\Magento\\Backend\\view\\adminhtml\\templates\\page\\header.phtml":2932881176,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp439\\app\\code\\Magento\\Backend\\view\\adminhtml\\templates\\page\\header.phtml":2932881176,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp1343\\app\\code\\Magento\\Backend\\view\\adminhtml\\templates\\page\\header.phtml":1812012403,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp3677\\app\\code\\Magento\\Backend\\view\\adminhtml\\templates\\page\\footer.phtml":702807491,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp971\\app\\code\\Magento\\AdminAnalytics\\ViewModel\\Metadata.php":2784624062,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp945\\app\\code\\Magento\\AdminAnalytics\\view\\adminhtml\\templates\\tracking.phtml":3226784892,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp739\\app\\code\\Magento\\Backend\\Block\\Page\\Footer.php":1140121689,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp3030\\var\\view_preprocessed\\pub\\static\\app\\code\\Magento\\AdminAnalytics\\view\\adminhtml\\templates\\tracking.phtml":3074453550,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp2309\\var\\view_preprocessed\\pub\\static\\app\\code\\Magento\\Backend\\view\\adminhtml\\templates\\page\\footer.phtml":3703258226,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp4522\\lib\\internal\\Magento\\Framework\\App\\ProductMetadataInterface.php":1340186670,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp1011\\app\\code\\Magento\\AdminAnalytics\\view\\adminhtml\\templates\\tracking.phtml":3226784892,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp306\\app\\code\\Magento\\AdminAnalytics\\ViewModel\\Metadata.php":2784624062,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp4184\\app\\etc\\config.php":134853695,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp1621\\app\\etc\\env.php":3686923414,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp2066\\app\\etc\\NonComposerComponentRegistration.php":4078136569,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp4158\\app\\etc\\registration_globlist.php":744714674,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp1196\\app\\etc\\vendor_path.php":3235679491,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp3510\\app\\etc\\vendor_path.php":3235679491,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp1659\\lib\\internal\\Magento\\Framework\\App\\ProductMetadataInterface.php":1340186670,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp1132\\app\\code\\Magento\\Backend\\view\\adminhtml\\templates\\page\\footer.phtml":702807491,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp3600\\app\\code\\Magento\\AdminAnalytics\\ViewModel\\Metadata.php":2784624062,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp4500\\app\\code\\Magento\\AdminAnalytics\\view\\adminhtml\\templates\\tracking.phtml":3226784892,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp3454\\app\\etc\\config.php":134853695,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp4588\\app\\code\\Magento\\Backend\\Block\\Page\\Footer.php":1140121689,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp1654\\var\\view_preprocessed\\pub\\static\\app\\code\\Magento\\AdminAnalytics\\view\\adminhtml\\templates\\tracking.phtml":3074453550,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp2402\\var\\view_preprocessed\\pub\\static\\app\\code\\Magento\\Backend\\view\\adminhtml\\templates\\page\\footer.phtml":3703258226,"C:\\Users\\EDY\\AppData\\Local\\Temp\\phpcsfixer_temp.tmp4917\\app\\code\\Magento\\Backend\\view\\adminhtml\\templates\\page\\footer.phtml":702807491}}
\ No newline at end of file
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
/**
* PHP Coding Standards fixer configuration
*/
$finder = PhpCsFixer\Finder::create()
->name('*.phtml')
->exclude('dev/tests/integration/tmp')
->exclude('dev/tests/integration/var')
->exclude('lib/internal/Cm')
->exclude('lib/internal/Credis')
->exclude('lib/internal/Less')
->exclude('lib/internal/LinLibertineFont')
->exclude('pub/media')
->exclude('pub/static')
->exclude('setup/vendor')
->exclude('var');
return PhpCsFixer\Config::create()
->setFinder($finder)
->setRules([
'@PSR2' => true,
'array_syntax' => ['syntax' => 'short'],
'concat_space' => ['spacing' => 'one'],
'include' => true,
'new_with_braces' => true,
'no_empty_statement' => true,
'no_extra_consecutive_blank_lines' => true,
'no_leading_import_slash' => true,
'no_leading_namespace_whitespace' => true,
'no_multiline_whitespace_around_double_arrow' => true,
'no_multiline_whitespace_before_semicolons' => true,
'no_singleline_whitespace_before_semicolons' => true,
'no_trailing_comma_in_singleline_array' => true,
'no_unused_imports' => true,
'no_whitespace_in_blank_line' => true,
'object_operator_without_whitespace' => true,
'ordered_imports' => true,
'standardize_not_equals' => true,
'ternary_operator_spaces' => true,
]);
memory_limit = 756M
max_execution_time = 18000
session.auto_start = off
suhosin.session.cryptua = off
\ No newline at end of file
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
// For performance use one level down: 'name/{,*/}*.js'
// If you want to recursively match all subfolders, use: 'name/**/*.js'
module.exports = function (grunt) {
'use strict';
var _ = require('underscore'),
path = require('path'),
filesRouter = require('./dev/tools/grunt/tools/files-router'),
configDir = './dev/tools/grunt/configs',
tasks = grunt.file.expand('./dev/tools/grunt/tasks/*'),
themes;
filesRouter.set('themes', 'dev/tools/grunt/configs/themes');
themes = filesRouter.get('themes');
tasks = _.map(tasks, function(task){ return task.replace('.js', '') });
tasks.push('time-grunt');
tasks.forEach(function (task) {
require(task)(grunt);
});
require('load-grunt-config')(grunt, {
configPath: path.join(__dirname, configDir),
init: true,
jitGrunt: {
staticMappings: {
usebanner: 'grunt-banner'
}
}
});
_.each({
/**
* Assembling tasks.
* ToDo: define default tasks.
*/
default: function () {
grunt.log.subhead('I\'m default task and at the moment I\'m empty, sorry :/');
},
/**
* Production preparation task.
*/
prod: function (component) {
var tasks = [
'less',
'autoprefixer',
'cssmin',
'usebanner'
].map(function(task){
return task + ':' + component;
});
if (typeof component === 'undefined') {
grunt.log.subhead('Tip: Please make sure that u specify prod subtask. By default prod task do nothing');
} else {
grunt.task.run(tasks);
}
},
/**
* Refresh themes.
*/
refresh: function () {
var tasks = [
'clean',
'exec:all'
];
_.each(themes, function(theme, name) {
tasks.push('less:' + name);
});
grunt.task.run(tasks);
},
/**
* Documentation
*/
documentation: [
'replace:documentation',
'less:documentation',
'styledocco:documentation',
'usebanner:documentationCss',
'usebanner:documentationLess',
'usebanner:documentationHtml',
'clean:var',
'clean:pub'
],
'legacy-build': [
'mage-minify:legacy'
],
spec: function (theme) {
var runner = require('./dev/tests/js/jasmine/spec_runner');
runner.init(grunt, { theme: theme });
grunt.task.run(runner.getTasks());
}
}, function (task, name) {
grunt.registerTask(name, task);
});
};
<IfVersion < 2.4>
order allow,deny
deny from all
</IfVersion>
<IfVersion >= 2.4>
Require all denied
</IfVersion>
<?php
/**
* Register basic autoloader that uses include path
*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);
use Magento\Framework\Autoload\AutoloaderRegistry;
use Magento\Framework\Autoload\ClassLoaderWrapper;
/**
* Shortcut constant for the root directory
*/
\define('BP', \dirname(__DIR__));
\define('VENDOR_PATH', BP . '/app/etc/vendor_path.php');
if (!\is_readable(VENDOR_PATH)) {
throw new \Exception(
'We can\'t read some files that are required to run the Magento application. '
. 'This usually means file permissions are set incorrectly.'
);
}
$vendorAutoload = (
static function (): ?string {
$vendorDir = require VENDOR_PATH;
$vendorAutoload = BP . "/{$vendorDir}/autoload.php";
if (\is_readable($vendorAutoload)) {
return $vendorAutoload;
}
$vendorAutoload = "{$vendorDir}/autoload.php";
if (\is_readable($vendorAutoload)) {
return $vendorAutoload;
}
return null;
}
)();
if ($vendorAutoload === null) {
throw new \Exception(
'Vendor autoload is not found. Please run \'composer install\' under application root directory.'
);
}
$composerAutoloader = include $vendorAutoload;
AutoloaderRegistry::registerAutoloader(new ClassLoaderWrapper($composerAutoloader));
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
/**
* Environment initialization
*/
error_reporting(E_ALL);
if (in_array('phar', \stream_get_wrappers())) {
stream_wrapper_unregister('phar');
}
#ini_set('display_errors', 1);
/* PHP version validation */
if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 70300) {
if (PHP_SAPI == 'cli') {
echo 'Magento supports PHP 7.3.0 or later. ' .
'Please read https://devdocs.magento.com/guides/v2.4/install-gde/system-requirements-tech.html';
} else {
echo <<<HTML
<div style="font:12px/1.35em arial, helvetica, sans-serif;">
<p>Magento supports PHP 7.3.0 or later. Please read
<a target="_blank" href="https://devdocs.magento.com/guides/v2.4/install-gde/system-requirements-tech.html">
Magento System Requirements</a>.
</div>
HTML;
}
exit(1);
}
require_once __DIR__ . '/autoload.php';
// Sets default autoload mappings, may be overridden in Bootstrap::create
\Magento\Framework\App\Bootstrap::populateAutoloader(BP, []);
/* Custom umask value may be provided in optional mage_umask file in root */
$umaskFile = BP . '/magento_umask';
$mask = file_exists($umaskFile) ? octdec(file_get_contents($umaskFile)) : 002;
umask($mask);
if (empty($_SERVER['ENABLE_IIS_REWRITES']) || ($_SERVER['ENABLE_IIS_REWRITES'] != 1)) {
/*
* Unset headers used by IIS URL rewrites.
*/
unset($_SERVER['HTTP_X_REWRITE_URL']);
unset($_SERVER['HTTP_X_ORIGINAL_URL']);
unset($_SERVER['IIS_WasUrlRewritten']);
unset($_SERVER['UNENCODED_URL']);
unset($_SERVER['ORIG_PATH_INFO']);
}
if (
(!empty($_SERVER['MAGE_PROFILER']) || file_exists(BP . '/var/profiler.flag'))
&& isset($_SERVER['HTTP_ACCEPT'])
&& strpos($_SERVER['HTTP_ACCEPT'], 'text/html') !== false
) {
$profilerConfig = isset($_SERVER['MAGE_PROFILER']) && strlen($_SERVER['MAGE_PROFILER'])
? $_SERVER['MAGE_PROFILER']
: trim(file_get_contents(BP . '/var/profiler.flag'));
if ($profilerConfig) {
$profilerConfig = json_decode($profilerConfig, true) ?: $profilerConfig;
}
Magento\Framework\Profiler::applyConfig(
$profilerConfig,
BP,
!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest'
);
}
date_default_timezone_set('UTC');
/* For data consistency between displaying (printing) and serialization a float number */
ini_set('precision', 14);
ini_set('serialize_precision', 14);
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);
namespace Magento\AdminAnalytics\Controller\Adminhtml\Config;
use Magento\Backend\App\Action;
use Magento\Framework\App\Action\HttpPostActionInterface;
use Magento\Framework\Controller\ResultFactory;
use Magento\AdminAnalytics\Model\ResourceModel\Viewer\Logger as NotificationLogger;
use Magento\Framework\App\ProductMetadataInterface;
use Magento\Framework\Controller\ResultInterface;
use Magento\Config\Model\Config\Factory;
/**
* Controller to record Admin analytics usage log
*/
class DisableAdminUsage extends Action implements HttpPostActionInterface
{
/**
* @var Factory
*/
private $configFactory;
/**
* @var ProductMetadataInterface
*/
private $productMetadata;
/**
* @var NotificationLogger
*/
private $notificationLogger;
/**
* DisableAdminUsage constructor.
*
* @param Action\Context $context
* @param ProductMetadataInterface $productMetadata
* @param NotificationLogger $notificationLogger
* @param Factory $configFactory
*/
public function __construct(
Action\Context $context,
ProductMetadataInterface $productMetadata,
NotificationLogger $notificationLogger,
Factory $configFactory
) {
parent::__construct($context);
$this->configFactory = $configFactory;
$this->productMetadata = $productMetadata;
$this->notificationLogger = $notificationLogger;
}
/**
* Change the value of config/admin/usage/enabled
*/
private function disableAdminUsage()
{
$configModel = $this->configFactory->create();
$configModel->setDataByPath('admin/usage/enabled', 0);
$configModel->save();
}
/**
* Log information about the last admin usage selection
*
* @return ResultInterface
*/
private function markUserNotified(): ResultInterface
{
$responseContent = [
'success' => $this->notificationLogger->log(
$this->productMetadata->getVersion()
),
'error_message' => ''
];
$resultJson = $this->resultFactory->create(ResultFactory::TYPE_JSON);
return $resultJson->setData($responseContent);
}
/**
* Log information about the last shown advertisement
*
* @return ResultInterface
*/
public function execute()
{
$this->disableAdminUsage();
$this->markUserNotified();
}
/**
* @inheritDoc
*/
protected function _isAllowed()
{
return $this->_authorization->isAllowed(static::ADMIN_RESOURCE);
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);
namespace Magento\AdminAnalytics\Controller\Adminhtml\Config;
use Magento\Backend\App\Action;
use Magento\Framework\App\Action\HttpPostActionInterface;
use Magento\Framework\Controller\ResultFactory;
use Magento\AdminAnalytics\Model\ResourceModel\Viewer\Logger as NotificationLogger;
use Magento\Framework\App\ProductMetadataInterface;
use Magento\Framework\Controller\ResultInterface;
use Magento\Config\Model\Config\Factory;
/**
* Controller to record that the current admin user has responded to Admin Analytics notice
*/
class EnableAdminUsage extends Action implements HttpPostActionInterface
{
/**
* @var Factory
*/
private $configFactory;
/**
* @var ProductMetadataInterface
*/
private $productMetadata;
/**
* @var NotificationLogger
*/
private $notificationLogger;
/**
* @param Action\Context $context
* @param ProductMetadataInterface $productMetadata
* @param NotificationLogger $notificationLogger
* @param Factory $configFactory
*/
public function __construct(
Action\Context $context,
ProductMetadataInterface $productMetadata,
NotificationLogger $notificationLogger,
Factory $configFactory
) {
parent::__construct($context);
$this->configFactory = $configFactory;
$this->productMetadata = $productMetadata;
$this->notificationLogger = $notificationLogger;
}
/**
* Change the value of config/admin/usage/enabled
*/
private function enableAdminUsage()
{
$configModel = $this->configFactory->create();
$configModel->setDataByPath('admin/usage/enabled', 1);
$configModel->save();
}
/**
* Log information about the last user response
*
* @return ResultInterface
*/
private function markUserNotified(): ResultInterface
{
$responseContent = [
'success' => $this->notificationLogger->log(
$this->productMetadata->getVersion()
),
'error_message' => ''
];
$resultJson = $this->resultFactory->create(ResultFactory::TYPE_JSON);
return $resultJson->setData($responseContent);
}
/**
* Log information about the last shown advertisement
*
* @return \Magento\Framework\Controller\ResultInterface
*/
public function execute()
{
$this->enableAdminUsage();
$this->markUserNotified();
}
/**
* @inheritDoc
*/
protected function _isAllowed()
{
return $this->_authorization->isAllowed(static::ADMIN_RESOURCE);
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);
namespace Magento\AdminAnalytics\Model\Condition;
use Magento\AdminAnalytics\Model\ResourceModel\Viewer\Logger;
use Magento\Framework\View\Layout\Condition\VisibilityConditionInterface;
use Magento\Framework\App\CacheInterface;
/**
* Dynamic validator for UI admin analytics notification, control UI component visibility.
*/
class CanViewNotification implements VisibilityConditionInterface
{
/**
* Unique condition name.
*
* @var string
*/
private static $conditionName = 'can_view_admin_usage_notification';
/**
* Prefix for cache
*
* @var string
*/
private static $cachePrefix = 'admin-usage-notification-popup';
/**
* @var Logger
*/
private $viewerLogger;
/**
* @var CacheInterface
*/
private $cacheStorage;
/**
* @param Logger $viewerLogger
* @param CacheInterface $cacheStorage
*/
public function __construct(
Logger $viewerLogger,
CacheInterface $cacheStorage
) {
$this->viewerLogger = $viewerLogger;
$this->cacheStorage = $cacheStorage;
}
/**
* Validate if notification popup can be shown and set the notification flag
*
* @param array $arguments Attributes from element node.
* @inheritdoc
*/
public function isVisible(array $arguments): bool
{
$cacheKey = self::$cachePrefix;
$value = $this->cacheStorage->load($cacheKey);
if ($value !== 'log-exists') {
$logExists = $this->viewerLogger->checkLogExists();
if ($logExists) {
$this->cacheStorage->save('log-exists', $cacheKey);
}
return !$logExists;
}
return false;
}
/**
* Get condition name
*
* @return string
*/
public function getName(): string
{
return self::$conditionName;
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);
namespace Magento\AdminAnalytics\Model\ResourceModel\Viewer;
use Magento\AdminAnalytics\Model\Viewer\Log;
use Magento\AdminAnalytics\Model\Viewer\LogFactory;
use Magento\Framework\App\ResourceConnection;
/**
* Admin Analytics log data logger.
*
* Saves and retrieves release notification viewer log data.
*/
class Logger
{
/**
* Admin Analytics usage version log table name
*/
const LOG_TABLE_NAME = 'admin_analytics_usage_version_log';
/**
* @var Resource
*/
private $resource;
/**
* @var LogFactory
*/
private $logFactory;
/**
* @param ResourceConnection $resource
* @param LogFactory $logFactory
*/
public function __construct(
ResourceConnection $resource,
LogFactory $logFactory
) {
$this->resource = $resource;
$this->logFactory = $logFactory;
}
/**
* Save (insert new or update existing) log.
*
* @param string $lastViewVersion
* @return bool
*/
public function log(string $lastViewVersion): bool
{
/** @var \Magento\Framework\DB\Adapter\AdapterInterface $connection */
$connection = $this->resource->getConnection(ResourceConnection::DEFAULT_CONNECTION);
$connection->insertOnDuplicate(
$this->resource->getTableName(self::LOG_TABLE_NAME),
[
'last_viewed_in_version' => $lastViewVersion,
],
[
'last_viewed_in_version',
]
);
return true;
}
/**
* Get log by the last view version.
*
* @return Log
*/
public function get(): Log
{
return $this->logFactory->create(['data' => $this->loadLatestLogData()]);
}
/**
* Checks is log already exists.
*
* @return boolean
*/
public function checkLogExists(): bool
{
$data = $this->logFactory->create(['data' => $this->loadLatestLogData()]);
$lastViewedVersion = $data->getLastViewVersion();
return isset($lastViewedVersion);
}
/**
* Load release notification viewer log data by last view version
*
* @return array
*/
private function loadLatestLogData(): array
{
$connection = $this->resource->getConnection();
$select = $connection->select()
->from(['log_table' => $this->resource->getTableName(self::LOG_TABLE_NAME)])
->order('log_table.id desc')
->limit(['count' => 1]);
$data = $connection->fetchRow($select);
if (!$data) {
$data = [];
}
return $data;
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);
namespace Magento\AdminAnalytics\Model\Viewer;
use Magento\Framework\DataObject;
/**
* Admin Analytics log resource
*/
class Log extends DataObject
{
/**
* Get log id
*
* @return int
*/
public function getId() : ?int
{
return $this->getData('id');
}
/**
* Get last viewed product version
*
* @return string
*/
public function getLastViewVersion() : ?string
{
return $this->getData('last_viewed_in_version');
}
}
The Magento\AdminAnalytics module gathers information about the features Magento administrators use. This information will be used to help improve the user experience on the Magento Admin.
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
<actionGroup name="AdminLoginActionGroup">
<conditionalClick selector="{{AdminUsageNotificationSection.adminUsageDontAllowButton}}" dependentSelector="{{AdminUsageNotificationSection.adminUsageDontAllowButton}}" visible="true" stepKey="clickDontAllowButtonIfVisible" before="closeAdminNotification"/>
</actionGroup>
</actionGroups>
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
<actionGroup name="CloseAllDialogBoxes">
<conditionalClick selector="{{AdminUsageNotificationSection.releaseNotificationCloseButton1}}" dependentSelector="{{AdminUsageNotificationSection.releaseNotificationCloseButton1}}" visible="true" stepKey="clickCloseButtonIfVisible1"/>
<conditionalClick selector="{{AdminUsageNotificationSection.releaseNotificationCloseButton2}}" dependentSelector="{{AdminUsageNotificationSection.releaseNotificationCloseButton2}}" visible="true" stepKey="clickCloseButtonIfVisible2"/>
<conditionalClick selector="{{AdminUsageNotificationSection.releaseNotificationCloseButton3}}" dependentSelector="{{AdminUsageNotificationSection.releaseNotificationCloseButton3}}" visible="true" stepKey="clickCloseButtonIfVisible3"/>
<conditionalClick selector="{{AdminUsageNotificationSection.releaseNotificationCloseButton4}}" dependentSelector="{{AdminUsageNotificationSection.releaseNotificationCloseButton4}}" visible="true" stepKey="clickCloseButtonIfVisible4"/>
<conditionalClick selector="{{AdminUsageNotificationSection.releaseNotificationCloseButton5}}" dependentSelector="{{AdminUsageNotificationSection.releaseNotificationCloseButton5}}" visible="true" stepKey="clickCloseButtonIfVisible5"/>
<conditionalClick selector="{{AdminUsageNotificationSection.releaseNotificationCloseButton6}}" dependentSelector="{{AdminUsageNotificationSection.releaseNotificationCloseButton6}}" visible="true" stepKey="clickCloseButtonIfVisible6"/>
<conditionalClick selector="{{AdminUsageNotificationSection.adminUsageAllowButton}}" dependentSelector="{{AdminUsageNotificationSection.adminUsageAllowButton}}" visible="true" stepKey="clickAllowButtonIfVisible"/>
</actionGroup>
</actionGroups>
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
<actionGroup name="SelectAdminUsageSetting">
<arguments>
<argument name="adminUsageValue" type="string" defaultValue="0"/>
</arguments>
<conditionalClick selector="{{AdminUsageConfigSection.adminUsageHeader}}" dependentSelector="{{AdminUsageConfigSection.adminUsageOptions}}" visible="false" stepKey="clickOnAdminUsageHeader"/>
<selectOption selector="{{AdminUsageConfigSection.adminUsageOptions}}" userInput="{{adminUsageValue}}" stepKey="selectOption"/>
<click selector="{{AdminNewStoreGroupActionsSection.saveButton}}" stepKey="clickSaveButton"/>
</actionGroup>
</actionGroups>
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd">
<section name="AdminHeaderSection">
<element name="adminTrackingScript" type="text" selector="script[src*='//assets.adobedtm.com/launch']"/>
<element name="adminTrackingMetaData" type="text" selector="//*script[contains('adminAnalyticsMetadata')]"/>
</section>
</sections>
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd">
<section name="AdminUsageConfigSection">
<element name="adminUsageHeader" type="text" selector="#admin_usage-head"/>
<element name="adminUsageOptions" type="select" selector="#admin_usage_enabled"/>
</section>
</sections>
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd">
<section name="AdminUsageNotificationSection">
<element name="adminUsageDialogBox" type="text" selector="//*[@class='modal-inner-wrap'][last()]"/>
<element name="adminUsageDontAllowButton" type="text" selector=".modal-popup .action-secondary"/>
</section>
</sections>
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
<test name="AdminCheckAnalyticsTrackingTest">
<annotations>
<stories value="AdminAnalytics Check Tracking."/>
<title value="AdminAnalytics Check Tracking."/>
<description value="AdminAnalytics Check Tracking."/>
<severity value="MINOR"/>
<testCaseId value="MC-36869"/>
</annotations>
<before>
<actionGroup ref="AdminLoginActionGroup" stepKey="LoginAsAdmin"/>
<magentoCLI command="config:set admin/usage/enabled 1" stepKey="enableAdminUsageTracking"/>
<actionGroup ref="CliCacheCleanActionGroup" stepKey="cleanInvalidatedCaches">
<argument name="tags" value="config full_page"/>
</actionGroup>
<reloadPage stepKey="pageReload"/>
</before>
<after>
<magentoCLI command="config:set admin/usage/enabled 0" stepKey="disableAdminUsageTracking"/>
<actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/>
</after>
<waitForPageLoad stepKey="waitForPageReloaded"/>
<seeInPageSource html="var adminAnalyticsMetadata =" stepKey="seeInPageSource"/>
<grabPageSource stepKey="pageSource"/>
<assertRegExp message="adminAnalyticsMetadata object is invalid" stepKey="validateadminAnalyticsMetadata">
<expectedResult type="string">#var\s+adminAnalyticsMetadata\s+=\s+{\s+("[\w_]+":\s+"[^"]*?",\s+)*?("[\w_]+":\s+"[^"]*?"\s+)};#s</expectedResult>
<actualResult type="variable">$pageSource</actualResult>
</assertRegExp>
<assertRegExp message="adminAnalyticsMetadata object contains incorrect user ID" stepKey="validateUserId">
<expectedResult type="string">#var\s+adminAnalyticsMetadata\s+=\s+{\s+("[\w_]+":\s+"[^"]*?",\s+)*?"user":\s+"[\w\d]{64}"#s</expectedResult>
<actualResult type="variable">$pageSource</actualResult>
</assertRegExp>
<assertRegExp message="adminAnalyticsMetadata object contains incorrect secure base URL" stepKey="validateSecureBaseURL">
<expectedResult type="string">#var\s+adminAnalyticsMetadata\s+=\s+{\s+("[\w_]+":\s+"[^"]*?",\s+)*?"secure_base_url":\s+"http(s)?\\\\u003A\\\\u002F\\\\u002F.+?\\\\u002F"#s</expectedResult>
<actualResult type="variable">$pageSource</actualResult>
</assertRegExp>
<assertRegExp message="adminAnalyticsMetadata object contains incorrect product version" stepKey="validateProductVersion">
<expectedResult type="string">#var\s+adminAnalyticsMetadata\s+=\s+{\s+("[\w_]+":\s+"[^"]*?",\s+)*?"version":\s+"[^\s]+"#s</expectedResult>
<actualResult type="variable">$pageSource</actualResult>
</assertRegExp>
<assertRegExp message="adminAnalyticsMetadata object contains incorrect product edition" stepKey="validateProductEdition">
<expectedResult type="string">#var\s+adminAnalyticsMetadata\s+=\s+{\s+("[\w_]+":\s+"[^"]*?",\s+)*?"product_edition":\s+"(Community|Enterprise|B2B)"#s</expectedResult>
<actualResult type="variable">$pageSource</actualResult>
</assertRegExp>
<assertRegExp message="adminAnalyticsMetadata object contains incorrect application mode" stepKey="validateApplicationMode">
<expectedResult type="string">#var\s+adminAnalyticsMetadata\s+=\s+{\s+("[\w_]+":\s+"[^"]*?",\s+)*?"mode":\s+"default|developer|production"#s</expectedResult>
<actualResult type="variable">$pageSource</actualResult>
</assertRegExp>
<assertRegExp message="adminAnalyticsMetadata object contains incorrect store name" stepKey="validateStoreName">
<expectedResult type="string">#var\s+adminAnalyticsMetadata\s+=\s+{\s+("[\w_]+":\s+"[^"]*?",\s+)*?"store_name_default":\s+".*?"#s</expectedResult>
<actualResult type="variable">$pageSource</actualResult>
</assertRegExp>
<assertRegExp message="adminAnalyticsMetadata object contains incorrect admin user created date" stepKey="validateAdminUserCreatedDate">
<expectedResult type="string">#var\s+adminAnalyticsMetadata\s+=\s+{\s+("[\w_]+":\s+"[^"]*?",\s+)*?"admin_user_created":\s+".+?"#s</expectedResult>
<actualResult type="variable">$pageSource</actualResult>
</assertRegExp>
<assertRegExp message="adminAnalyticsMetadata object contains incorrect admin user log date" stepKey="validateAdminUserLogDate">
<expectedResult type="string">#var\s+adminAnalyticsMetadata\s+=\s+{\s+("[\w_]+":\s+"[^"]*?",\s+)*?"admin_user_logdate":\s+".+?"#s</expectedResult>
<actualResult type="variable">$pageSource</actualResult>
</assertRegExp>
<assertRegExp message="adminAnalyticsMetadata object contains incorrect admin user role name" stepKey="validateAdminUserRoleName">
<expectedResult type="string">#var\s+adminAnalyticsMetadata\s+=\s+{\s+("[\w_]+":\s+"[^"]*?",\s+)*?"admin_user_role_name":\s+".+?"#s</expectedResult>
<actualResult type="variable">$pageSource</actualResult>
</assertRegExp>
</test>
</tests>
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);
namespace Magento\AdminAnalytics\Test\Unit\Condition;
use Magento\AdminAnalytics\Model\Condition\CanViewNotification;
use Magento\AdminAnalytics\Model\ResourceModel\Viewer\Logger;
use Magento\AdminAnalytics\Model\Viewer\Log;
use Magento\Framework\App\CacheInterface;
use Magento\Framework\App\ProductMetadataInterface;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
class CanViewNotificationTest extends TestCase
{
/** @var CanViewNotification */
private $canViewNotification;
/** @var Logger|MockObject */
private $viewerLoggerMock;
/** @var ProductMetadataInterface|MockObject */
private $productMetadataMock;
/** @var Log|MockObject */
private $logMock;
/** @var MockObject|CacheInterface $cacheStorageMock */
private $cacheStorageMock;
protected function setUp(): void
{
$this->cacheStorageMock = $this->getMockBuilder(CacheInterface::class)
->getMockForAbstractClass();
$this->logMock = $this->createMock(Log::class);
$this->viewerLoggerMock = $this->createMock(Logger::class);
$this->productMetadataMock = $this->getMockForAbstractClass(ProductMetadataInterface::class);
$objectManager = new ObjectManager($this);
$this->canViewNotification = $objectManager->getObject(
CanViewNotification::class,
[
'viewerLogger' => $this->viewerLoggerMock,
'productMetadata' => $this->productMetadataMock,
'cacheStorage' => $this->cacheStorageMock,
]
);
}
/**
* @param $expected
* @param $cacheResponse
* @param $logExists
* @dataProvider isVisibleProvider
*/
public function testIsVisibleLoadDataFromLog($expected, $cacheResponse, $logExists)
{
$this->cacheStorageMock->expects($this->once())
->method('load')
->with('admin-usage-notification-popup')
->willReturn($cacheResponse);
$this->viewerLoggerMock
->method('checkLogExists')
->willReturn($logExists);
$this->cacheStorageMock
->method('save')
->with('log-exists', 'admin-usage-notification-popup');
$this->assertEquals($expected, $this->canViewNotification->isVisible([]));
}
/**
* @return array
*/
public function isVisibleProvider()
{
return [
[true, false, false],
[false, 'log-exists', true],
[false, false, true],
];
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminAnalytics\Ui\DataProvider;
use Magento\Ui\DataProvider\AbstractDataProvider;
use Magento\Framework\Api\Filter;
/**
* Data Provider for the Admin usage UI component.
*/
class AdminUsageNotificationDataProvider extends AbstractDataProvider
{
/**
* @inheritdoc
*/
public function getData()
{
return $this->data;
}
/**
* @inheritdoc
*/
public function addFilter(Filter $filter)
{
return null;
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);
namespace Magento\AdminAnalytics\ViewModel;
use Magento\Config\Model\Config\Backend\Admin\Custom;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\ProductMetadataInterface;
use Magento\Backend\Model\Auth\Session;
use Magento\Framework\App\State;
use Magento\Framework\View\Element\Block\ArgumentInterface;
use Magento\Store\Model\Information;
/**
* Gets user version and mode
*/
class Metadata implements ArgumentInterface
{
/**
* @var State
*/
private $appState;
/**
* @var Session
*/
private $authSession;
/**
* @var ProductMetadataInterface
*/
private $productMetadata;
/**
* @var ScopeConfigInterface
*/
private $config;
/**
* @param ProductMetadataInterface $productMetadata
* @param Session $authSession
* @param State $appState
* @param ScopeConfigInterface $config
*/
public function __construct(
ProductMetadataInterface $productMetadata,
Session $authSession,
State $appState,
ScopeConfigInterface $config
) {
$this->productMetadata = $productMetadata;
$this->authSession = $authSession;
$this->appState = $appState;
$this->config = $config;
}
/**
* Get product version
*
* @return string
*/
public function getMagentoVersion() :string
{
return $this->productMetadata->getVersion();
}
/**
* Get product edition
*
* @return string
*/
public function getProductEdition(): string
{
return $this->productMetadata->getEdition();
}
/**
* Get current user id (hash generated from email)
*
* @return string
*/
public function getCurrentUser() :string
{
return hash('sha256', 'ADMIN_USER' . $this->authSession->getUser()->getEmail());
}
/**
* Get Magento mode that the user is using
*
* @return string
*/
public function getMode() :string
{
return $this->appState->getMode();
}
/**
* Get created date for current user
*
* @return string
*/
public function getCurrentUserCreatedDate(): string
{
return $this->authSession->getUser()->getCreated();
}
/**
* Get log date for current user
*
* @return string|null
*/
public function getCurrentUserLogDate(): ?string
{
return $this->authSession->getUser()->getLogdate();
}
/**
* Get secure base URL
*
* @param string $scope
* @param string|null $scopeCode
* @return string|null
*/
public function getSecureBaseUrlForScope(
string $scope = ScopeConfigInterface::SCOPE_TYPE_DEFAULT,
?string $scopeCode = null
): ?string {
return $this->config->getValue(Custom::XML_PATH_SECURE_BASE_URL, $scope, $scopeCode);
}
/**
* Get store name
*
* @param string $scope
* @param string|null $scopeCode
* @return string|null
*/
public function getStoreNameForScope(
string $scope = ScopeConfigInterface::SCOPE_TYPE_DEFAULT,
?string $scopeCode = null
): ?string {
return $this->config->getValue(Information::XML_PATH_STORE_INFO_NAME, $scope, $scopeCode);
}
/**
* Get current user role name
*
* @return string
*/
public function getCurrentUserRoleName(): string
{
return $this->authSession->getUser()->getRole()->getRoleName();
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);
namespace Magento\AdminAnalytics\ViewModel;
use Magento\Framework\View\Element\Block\ArgumentInterface;
use Magento\AdminAnalytics\Model\Condition\CanViewNotification as AdminAnalyticsNotification;
use Magento\ReleaseNotification\Model\Condition\CanViewNotification as ReleaseNotification;
/**
* Control display of admin analytics and release notification modals
*/
class Notification implements ArgumentInterface
{
/**
* @var AdminAnalyticsNotification
*/
private $canViewNotificationAnalytics;
/**
* @var ReleaseNotification
*/
private $canViewNotificationRelease;
/**
* @param AdminAnalyticsNotification $canViewNotificationAnalytics
* @param ReleaseNotification $canViewNotificationRelease
*/
public function __construct(
AdminAnalyticsNotification $canViewNotificationAnalytics,
ReleaseNotification $canViewNotificationRelease
) {
$this->canViewNotificationAnalytics = $canViewNotificationAnalytics;
$this->canViewNotificationRelease = $canViewNotificationRelease;
}
/**
* Determine if the analytics popup is visible
*
* @return bool
*/
public function isAnalyticsVisible(): bool
{
return $this->canViewNotificationAnalytics->isVisible([]);
}
/**
* Determine if the release popup is visible
*
* @return bool
*/
public function isReleaseVisible(): bool
{
return $this->canViewNotificationRelease->isVisible([]);
}
}
{
"name": "magento/module-admin-analytics",
"description": "N/A",
"config": {
"sort-packages": true
},
"require": {
"php": "~7.3.0||~7.4.0",
"magento/framework": "*",
"magento/module-backend": "*",
"magento/module-config": "*",
"magento/module-store": "*",
"magento/module-ui": "*",
"magento/module-release-notification": "*"
},
"type": "magento2-module",
"license": [
"OSL-3.0",
"AFL-3.0"
],
"autoload": {
"files": [
"registration.php"
],
"psr-4": {
"Magento\\AdminAnalytics\\": ""
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<csp_whitelist xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Csp:etc/csp_whitelist.xsd">
<policies>
<policy id="script-src">
<values>
<value id="aptrinsic" type="host">*.aptrinsic.com</value>
</values>
</policy>
<policy id="style-src">
<values>
<value id="aptrinsic" type="host">*.aptrinsic.com</value>
<value id="fonts_googleapis" type="host">fonts.googleapis.com</value>
</values>
</policy>
<policy id="img-src">
<values>
<value id="aptrinsic" type="host">*.aptrinsic.com</value>
<value id="storage_googleapis" type="host">storage.googleapis.com</value>
</values>
</policy>
<policy id="connect-src">
<values>
<value id="aptrinsic" type="host">*.aptrinsic.com</value>
</values>
</policy>
<policy id="font-src">
<values>
<value id="fonts_gstatic" type="host">fonts.gstatic.com</value>
</values>
</policy>
</policies>
</csp_whitelist>
<?xml version="1.0"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
<router id="admin">
<route id="adminAnalytics" frontName="adminAnalytics">
<module name="Magento_AdminAnalytics" />
</route>
</router>
</config>
<?xml version="1.0"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
<system>
<section id="admin">
<group id="usage" translate="label" type="text" sortOrder="2000" showInDefault="1">
<label>Admin Usage</label>
<field id="enabled" translate="label comment" type="select" sortOrder="1" showInDefault="1">
<label>Enable Admin Usage Tracking</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<comment>Allow Magento to track admin usage in order to improve the quality and user experience.</comment>
</field>
</group>
</section>
</system>
</config>
<?xml version="1.0"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
<default>
<admin>
<usage>
<enabled>
1
</enabled>
</usage>
</admin>
</default>
</config>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<csp_whitelist xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Csp:etc/csp_whitelist.xsd">
<policies>
<policy id="script-src">
<values>
<value id="adobedtm" type="host">assets.adobedtm.com</value>
<value id="adobe" type="host">*.adobe.com</value>
</values>
</policy>
<policy id="style-src">
<values>
<value id="adobe" type="host">*.adobe.com</value>
</values>
</policy>
<policy id="img-src">
<values>
<value id="adobedtm" type="host">assets.adobedtm.com</value>
<value id="omtrdc" type="host">amcglobal.sc.omtrdc.net</value>
<value id="dpmdemdex" type="host">dpm.demdex.net</value>
<value id="everesttech" type="host">cm.everesttech.net</value>
<value id="adobe" type="host">*.adobe.com</value>
</values>
</policy>
<policy id="connect-src">
<values>
<value id="dpmdemdex" type="host">dpm.demdex.net</value>
<value id="omtrdc" type="host">amcglobal.sc.omtrdc.net</value>
</values>
</policy>
<policy id="media-src">
<values>
<value id="adobe" type="host">*.adobe.com</value>
</values>
</policy>
<policy id="frame-src">
<values>
<value id="amcdemdex" type="host">fast.amc.demdex.net</value>
<value id="adobe" type="host">*.adobe.com</value>
</values>
</policy>
</policies>
</csp_whitelist>
<?xml version="1.0"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
<table name="admin_analytics_usage_version_log" resource="default" engine="innodb"
comment="Admin Notification Viewer Log Table">
<column xsi:type="int" name="id" unsigned="true" nullable="false" identity="true"
comment="Log ID"/>
<column xsi:type="varchar" name="last_viewed_in_version" nullable="false" length="50"
comment="Viewer last viewed on product version"/>
<constraint xsi:type="primary" referenceId="PRIMARY">
<column name="id"/>
</constraint>
<constraint xsi:type="unique" referenceId="ADMIN_ANALYTICS_USAGE_VERSION_LOG_LAST_VIEWED_IN_VERSION">
<column name="last_viewed_in_version"/>
</constraint>
</table>
</schema>
{
"admin_analytics_usage_version_log": {
"column": {
"id": true,
"last_viewed_in_version": true
},
"constraint": {
"PRIMARY": true,
"ADMIN_ANALYTICS_USAGE_VERSION_LOG_LAST_VIEWED_IN_VERSION": true
}
}
}
\ No newline at end of file
<?xml version="1.0"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Magento_AdminAnalytics"/>
</config>
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
use Magento\Framework\Component\ComponentRegistrar;
ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Magento_AdminAnalytics', __DIR__);
<?xml version="1.0"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="content">
<uiComponent name="admin_usage_notification">
<visibilityCondition name="can_view_admin_usage_notification" className="Magento\AdminAnalytics\Model\Condition\CanViewNotification"/>
</uiComponent>
<block name="tracking_notification" as="tracking_notification" template="Magento_AdminAnalytics::notification.phtml">
<arguments>
<argument name="notification" xsi:type="object">Magento\AdminAnalytics\ViewModel\Notification</argument>
</arguments>
</block>
</referenceContainer>
</body>
</page>
\ No newline at end of file
<?xml version="1.0"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd" >
<body>
<referenceContainer name="header">
<block name="tracking" as="tracking" template="Magento_AdminAnalytics::tracking.phtml" ifconfig="admin/usage/enabled">
<arguments>
<argument name="tracking_url" xsi:type="string">//assets.adobedtm.com/a7d65461e54e/37baabec1b6e/launch-177bc126c8e6.min.js</argument>
<argument name="metadata" xsi:type="object">Magento\AdminAnalytics\ViewModel\Metadata</argument>
</arguments>
</block>
</referenceContainer>
</body>
</page>
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
var config = {
config: {
mixins: {
'Magento_ReleaseNotification/js/modal/component': {
'Magento_AdminAnalytics/js/release-notification/modal/component-mixin': true
}
}
}
};
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
/** @var \Magento\Framework\View\Helper\SecureHtmlRenderer $secureRenderer */
?>
<?php
$isAnaliticsVisible = $block->getNotification()->isAnalyticsVisible() ? 1 : 0;
$isReleaseVisible = $block->getNotification()->isReleaseVisible() ? 1 : 0;
$scriptString = <<<script
define('analyticsPopupConfig', function () {
return {
analyticsVisible: {$isAnaliticsVisible},
releaseVisible: {$isReleaseVisible},
}
});
script;
?>
<?= /* @noEscape */ $secureRenderer->renderTag('script', [], $scriptString, false); ?>
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
/**
* @var \Magento\Framework\View\Helper\SecureHtmlRenderer $secureRenderer
*/
?>
<?= /* @noEscape */ $secureRenderer->renderTag(
'script',
[
'src' => $block->getTrackingUrl(),
'async' => true,
],
'&nbsp;',
false
) ?>
<?php
/** @var \Magento\AdminAnalytics\ViewModel\Metadata $metadata */
$metadata = $block->getMetadata();
$scriptString = '
var adminAnalyticsMetadata = {
"secure_base_url": "' . $block->escapeJs($metadata->getSecureBaseUrlForScope()) . '",
"version": "' . $block->escapeJs($metadata->getMagentoVersion()) . '",
"product_edition": "' . $block->escapeJs($metadata->getProductEdition()) . '",
"user": "' . $block->escapeJs($metadata->getCurrentUser()) . '",
"mode": "' . $block->escapeJs($metadata->getMode()) . '",
"store_name_default": "' . $block->escapeJs($metadata->getStoreNameForScope()) . '",
"admin_user_created": "' . $block->escapeJs($metadata->getCurrentUserCreatedDate()) . '",
"admin_user_logdate": "' . $block->escapeJs($metadata->getCurrentUserLogDate()) . '",
"admin_user_role_name": "' . $block->escapeJs($metadata->getCurrentUserRoleName()) . '"
};
';
?>
<?= /* @noEscape */ $secureRenderer->renderTag('script', [], $scriptString, false); ?>
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="provider" xsi:type="string">admin_usage_notification.admin_usage_notification_data_source</item>
</item>
<item name="label" xsi:type="string" translate="true">Admin Usage Notification</item>
<item name="template" xsi:type="string">templates/form/collapsible</item>
</argument>
<settings>
<namespace>admin_usage_notification</namespace>
<dataScope>data</dataScope>
<deps>
<dep>admin_usage_notification.admin_usage_notification_data_source</dep>
</deps>
</settings>
<dataSource name="admin_usage_notification_data_source">
<argument name="dataProvider" xsi:type="configurableObject">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="data" xsi:type="array">
<item name="enableLogAction" xsi:type="url" path="adminAnalytics/config/enableAdminUsage"/>
<item name="disableLogAction" xsi:type="url" path="adminAnalytics/config/disableAdminUsage"/>
</item>
</item>
</argument>
</argument>
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/form/provider</item>
</item>
</argument>
<dataProvider class="Magento\AdminAnalytics\Ui\DataProvider\AdminUsageNotificationDataProvider" name="admin_usage_notification_data_source">
<settings>
<requestFieldName>id</requestFieldName>
<primaryFieldName>entity_id</primaryFieldName>
</settings>
</dataProvider>
</dataSource>
<modal name="notification_modal_1" component="Magento_AdminAnalytics/js/modal/component">
<settings>
<state>true</state>
<options>
<option name="modalClass" xsi:type="string">admin-usage-notification</option>
<option name="title" xsi:type="string" translate="true">Allow admin usage data collection</option>
<option name="autoOpen" xsi:type="boolean">true</option>
<option name="type" xsi:type="string">popup</option>
<option name="clickableOverlay" xsi:type="boolean">false</option>
<option name="responsive" xsi:type="boolean">true</option>
<option name="innerScroll" xsi:type="boolean">false</option>
<option name="buttons" xsi:type="array">
<item name="0" xsi:type="array">
<item name="text" xsi:type="string" translate="true">Don't Allow</item>
<item name="class" xsi:type="string">action-secondary</item>
<item name="actions" xsi:type="array">
<item name="0" xsi:type="string">disableAdminUsage</item>
</item>
</item>
<item name="1" xsi:type="array">
<item name="text" xsi:type="string" translate="true">Allow</item>
<item name="class" xsi:type="string">action-primary</item>
<item name="actions" xsi:type="array">
<item name="0" xsi:type="string">enableAdminUsage</item>
</item>
</item>
</option>
</options>
</settings>
<fieldset name="notification_fieldset">
<settings>
<label/>
</settings>
<container name="notification_text" template="ui/form/components/complex">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="label" xsi:type="string"/>
<item name="additionalClasses" xsi:type="string">release-notification-text</item>
<item name="text" xsi:type="string" translate="true"><![CDATA[
<p>Help us improve Magento Admin by allowing us to collect usage data.</p>
<p>All usage data that we collect for this purpose cannot be used to individually identify you and is used only to improve the Magento Admin and related products and services.</p>
<p>You can learn more and opt out at any time by following the instructions in <a href="https://docs.magento.com/user-guide/stores/admin.html" target="_blank" tabindex="0">merchant documentation</a>.</p>
]]></item>
</item>
</argument>
</container>
</fieldset>
</modal>
</form>
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
define([
'underscore',
'jquery',
'Magento_Ui/js/modal/modal-component',
'uiRegistry',
'analyticsPopupConfig'
],
function (_, $, Modal, registry, analyticsPopupConfig) {
'use strict';
return Modal.extend(
{
defaults: {
imports: {
enableLogAction: '${ $.provider }:data.enableLogAction',
disableLogAction: '${ $.provider }:data.disableLogAction'
},
options: {},
notificationWindow: null
},
/**
* Initializes modal on opened function
*/
initModal: function () {
this.options.opened = this.onOpened.bind(this);
this._super();
},
/**
* Configure ESC and TAB so user can't leave modal
* without selecting an option
*
* @returns {Object} Chainable.
*/
initModalEvents: function () {
this._super();
//Don't allow ESC key to close modal
this.options.keyEventHandlers.escapeKey = this.handleEscKey.bind(this);
//Restrict tab action to the modal
this.options.keyEventHandlers.tabKey = this.handleTabKey.bind(this);
return this;
},
/**
* Once the modal is opened it hides the X
*/
onOpened: function () {
$('.modal-header button.action-close').attr('disabled', true).hide();
this.focusableElements = $(this.rootSelector).find('a[href], button:enabled');
this.firstFocusableElement = this.focusableElements[0];
this.lastFocusableElement = this.focusableElements[this.focusableElements.length - 1];
this.firstFocusableElement.focus();
},
/**
* Changes admin usage setting to yes
*/
enableAdminUsage: function () {
var data = {
'form_key': window.FORM_KEY
};
$.ajax(
{
type: 'POST',
url: this.enableLogAction,
data: data,
showLoader: true
}
).done(
function (xhr) {
if (xhr.error) {
self.onError(xhr);
}
}
).fail(this.onError);
this.openReleasePopup();
this.closeModal();
},
/**
* Changes admin usage setting to no
*/
disableAdminUsage: function () {
var data = {
'form_key': window.FORM_KEY
};
$.ajax(
{
type: 'POST',
url: this.disableLogAction,
data: data,
showLoader: true
}
).done(
function (xhr) {
if (xhr.error) {
self.onError(xhr);
}
}
).fail(this.onError);
this.openReleasePopup();
this.closeModal();
},
/**
* Allows admin usage popup to be shown first and then new release notification
*/
openReleasePopup: function () {
var notificationModalSelector = 'release_notification.release_notification.notification_modal_1';
if (analyticsPopupConfig.releaseVisible) {
registry.get(notificationModalSelector).initializeContentAfterAnalytics();
}
},
/**
* Handle Tab and Shift+Tab key event
*
* Keep the tab actions restricted to the popup modal
* so the user must select an option to dismiss the modal
*/
handleTabKey: function (event) {
var modal = this,
KEY_TAB = 9;
/**
* Handle Shift+Tab to tab backwards
*/
function handleBackwardTab() {
if (document.activeElement === modal.firstFocusableElement ||
document.activeElement === $(modal.rootSelector)[0]
) {
event.preventDefault();
modal.lastFocusableElement.focus();
}
}
/**
* Handle Tab forward
*/
function handleForwardTab() {
if (document.activeElement === modal.lastFocusableElement) {
event.preventDefault();
modal.firstFocusableElement.focus();
}
}
switch (event.keyCode) {
case KEY_TAB:
if (modal.focusableElements.length === 1) {
event.preventDefault();
break;
}
if (event.shiftKey) {
handleBackwardTab();
break;
}
handleForwardTab();
break;
default:
break;
}
},
/**
* Handle Esc key
*
* Esc key should not close modal
*/
handleEscKey: function (event) {
event.preventDefault();
}
}
);
}
);
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
define(['jquery', 'analyticsPopupConfig'], function ($, analyticsPopupConfig) {
'use strict';
var deferred = $.Deferred(),
mixin = {
/**
* Initializes content only if its visible
*/
initializeContent: function () {
var initializeContent = this._super.bind(this);
if (!analyticsPopupConfig.analyticsVisible) {
initializeContent();
} else {
deferred.then(function () {
initializeContent();
});
}
},
/**
* Initializes release notification content after admin analytics
*/
initializeContentAfterAnalytics: function () {
deferred.resolve();
}
};
return function (target) {
return target.extend(mixin);
};
});
<?php
declare(strict_types=1);
/**
* Adminhtml AdminNotification Severity Renderer
*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Block\Grid\Renderer;
use Magento\Backend\Block\Context;
use Magento\Backend\Block\Widget\Grid\Column\Renderer\AbstractRenderer;
use Magento\Framework\App\ActionInterface;
use Magento\Framework\DataObject;
use Magento\Framework\Url\Helper\Data;
/**
* Renderer class for action in the admin notifications grid
*/
class Actions extends AbstractRenderer
{
/**
* @var \Magento\Framework\Url\Helper\Data
*/
protected $_urlHelper;
/**
* @param \Magento\Backend\Block\Context $context
* @param \Magento\Framework\Url\Helper\Data $urlHelper
* @param array $data
*/
public function __construct(Context $context, Data $urlHelper, array $data = [])
{
$this->_urlHelper = $urlHelper;
parent::__construct($context, $data);
}
/**
* Renders grid column
*
* @param \Magento\Framework\DataObject $row
* @return string
*/
public function render(DataObject $row)
{
$readDetailsHtml = $row->getUrl() ? '<a class="action-details" target="_blank" href="' .
$this->escapeUrl($row->getUrl())
. '">' .
__('Read Details') . '</a>' : '';
$markAsReadHtml = !$row->getIsRead() ? '<a class="action-mark" href="' . $this->getUrl(
'*/*/markAsRead/',
['_current' => true, 'id' => $row->getNotificationId()]
) . '">' . __(
'Mark as Read'
) . '</a>' : '';
$encodedUrl = $this->_urlHelper->getEncodedUrl();
return sprintf(
'%s%s<a class="action-delete" href="%s" onClick="deleteConfirm(\'%s\', this.href); return false;">%s</a>',
$readDetailsHtml,
$markAsReadHtml,
$this->getUrl(
'*/*/remove/',
[
'_current' => true,
'id' => $row->getNotificationId(),
ActionInterface::PARAM_NAME_URL_ENCODED => $encodedUrl
]
),
__('Are you sure?'),
__('Remove')
);
}
}
<?php
declare(strict_types=1);
/**
* Adminhtml AdminNotification Severity Renderer
*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Block\Grid\Renderer;
use Magento\Backend\Block\Widget\Grid\Column\Renderer\AbstractRenderer;
use Magento\Framework\DataObject;
/**
* Renderer class for notice in the admin notifications grid
*/
class Notice extends AbstractRenderer
{
/**
* Renders grid column
*
* @param \Magento\Framework\DataObject $row
* @return string
*/
public function render(DataObject $row)
{
return '<span class="grid-row-title">' .
$this->escapeHtml($row->getTitle()) .
'</span>' .
($row->getDescription() ? '<br />' . $this->escapeHtml($row->getDescription()) : '');
}
}
<?php
declare(strict_types=1);
/**
* Adminhtml AdminNotification Severity Renderer
*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Block\Grid\Renderer;
use Magento\AdminNotification\Model\Inbox;
use Magento\Backend\Block\Context;
use Magento\Backend\Block\Widget\Grid\Column\Renderer\AbstractRenderer;
use Magento\Framework\DataObject;
use Magento\Framework\Notification\MessageInterface;
/**
* Renderer class for severity in the admin notifications grid
*/
class Severity extends AbstractRenderer
{
/**
* @var \Magento\AdminNotification\Model\Inbox
*/
protected $_notice;
/**
* @param \Magento\Backend\Block\Context $context
* @param \Magento\AdminNotification\Model\Inbox $notice
* @param array $data
*/
public function __construct(Context $context, Inbox $notice, array $data = [])
{
parent::__construct($context, $data);
$this->_notice = $notice;
}
/**
* Renders grid column
*
* @param \Magento\Framework\DataObject $row
* @return string
*/
public function render(DataObject $row)
{
$class = '';
$value = '';
$column = $this->getColumn();
$index = $column->getIndex();
switch ($row->getData($index)) {
case MessageInterface::SEVERITY_CRITICAL:
$class = 'critical';
$value = $this->_notice->getSeverities(MessageInterface::SEVERITY_CRITICAL);
break;
case MessageInterface::SEVERITY_MAJOR:
$class = 'major';
$value = $this->_notice->getSeverities(MessageInterface::SEVERITY_MAJOR);
break;
case MessageInterface::SEVERITY_MINOR:
$class = 'minor';
$value = $this->_notice->getSeverities(MessageInterface::SEVERITY_MINOR);
break;
case MessageInterface::SEVERITY_NOTICE:
$class = 'notice';
$value = $this->_notice->getSeverities(MessageInterface::SEVERITY_NOTICE);
break;
}
return '<span class="grid-severity-' . $class . '"><span>' . $value . '</span></span>';
}
}
<?php
/**
* Adminhtml AdminNotification inbox grid
*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Block;
/**
* @api
* @since 100.0.2
*/
class Inbox extends \Magento\Backend\Block\Widget\Grid\Container
{
/**
* @return void
*/
protected function _construct()
{
$this->_controller = 'adminhtml';
$this->_blockGroup = 'Magento_AdminNotification';
$this->_headerText = __('Messages Inbox');
parent::_construct();
$this->buttonList->remove('add');
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Block\System;
use Magento\AdminNotification\Model\ResourceModel\System\Message\Collection\Synchronized;
use Magento\Backend\Block\Template;
use Magento\Backend\Block\Template\Context as TemplateContext;
use Magento\Framework\Json\Helper\Data as JsonDataHelper;
use Magento\Framework\Notification\MessageInterface;
use Magento\Framework\Serialize\Serializer\Json as JsonSerializer;
/**
* AdminNotification Messages class
*/
class Messages extends Template
{
/**
* Synchronized Message collection
*
* @var Synchronized
*/
protected $_messages;
/**
* @var JsonDataHelper
* @deprecated 100.3.0
*/
protected $jsonHelper;
/**
* @var JsonSerializer
*/
private $serializer;
/**
* @param TemplateContext $context
* @param Synchronized $messages
* @param JsonDataHelper $jsonHelper
* @param JsonSerializer $serializer
* @param array $data
*/
public function __construct(
TemplateContext $context,
Synchronized $messages,
JsonDataHelper $jsonHelper,
JsonSerializer $serializer,
array $data = []
) {
$this->jsonHelper = $jsonHelper;
parent::__construct($context, $data);
$this->_messages = $messages;
$this->serializer = $serializer;
}
/**
* Prepare html output
*
* @return string
*/
protected function _toHtml()
{
if (count($this->_messages->getItems())) {
return parent::_toHtml();
}
return '';
}
/**
* Retrieve message list
*
* @return MessageInterface[]|null
*/
public function getLastCritical()
{
$items = array_values($this->_messages->getItems());
if (!empty($items) && current($items)->getSeverity() === MessageInterface::SEVERITY_CRITICAL) {
return current($items);
}
return null;
}
/**
* Retrieve number of critical messages
*
* @return int
*/
public function getCriticalCount()
{
return $this->_messages->getCountBySeverity(MessageInterface::SEVERITY_CRITICAL);
}
/**
* Retrieve number of major messages
*
* @return int
*/
public function getMajorCount()
{
return $this->_messages->getCountBySeverity(MessageInterface::SEVERITY_MAJOR);
}
/**
* Check whether system messages are present
*
* @return bool
*/
public function hasMessages()
{
return (bool)count($this->_messages->getItems());
}
/**
* Retrieve message list url
*
* @return string
*/
protected function _getMessagesUrl()
{
return $this->getUrl('adminhtml/system_message/list');
}
/**
* Initialize system message dialog widget
*
* @return string
*/
public function getSystemMessageDialogJson()
{
return $this->serializer->serialize(
[
'systemMessageDialog' => [
'buttons' => [],
'modalClass' => 'ui-dialog-active ui-popup-message modal-system-messages',
'ajaxUrl' => $this->_getMessagesUrl()
],
]
);
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Block\System\Messages;
use Magento\Framework\Notification\MessageInterface;
/**
* @api
* @since 100.0.2
*/
class UnreadMessagePopup extends \Magento\Backend\Block\Template
{
/**
* List of item classes per severity
*
* @var array
*/
protected $_itemClasses = [
MessageInterface::SEVERITY_CRITICAL => 'error',
MessageInterface::SEVERITY_MAJOR => 'warning',
];
/**
* System Message list
*
* @var \Magento\AdminNotification\Model\ResourceModel\System\Message\Collection
*/
protected $_messages;
/**
* @param \Magento\Backend\Block\Template\Context $context
* @param \Magento\AdminNotification\Model\ResourceModel\System\Message\Collection\Synchronized $messages
* @param array $data
*/
public function __construct(
\Magento\Backend\Block\Template\Context $context,
\Magento\AdminNotification\Model\ResourceModel\System\Message\Collection\Synchronized $messages,
array $data = []
) {
parent::__construct($context, $data);
$this->_messages = $messages;
}
/**
* Render block
*
* @return string
*/
protected function _toHtml()
{
if (count($this->_messages->getUnread())) {
return parent::_toHtml();
}
return '';
}
/**
* Retrieve list of unread messages
*
* @return MessageInterface[]
*/
public function getUnreadMessages()
{
return $this->_messages->getUnread();
}
/**
* Retrieve popup title
*
* @return \Magento\Framework\Phrase
*/
public function getPopupTitle()
{
$messageCount = count($this->_messages->getUnread());
if ($messageCount > 1) {
return __('You have %1 new system messages', $messageCount);
}
return __('You have %1 new system message', $messageCount);
}
/**
* Retrieve item class by severity
*
* @param MessageInterface $message
* @return string
*/
public function getItemClass(MessageInterface $message)
{
return $this->_itemClasses[$message->getSeverity()];
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Block;
/**
* Toolbar entry that shows latest notifications
*
* @api
* @since 100.0.2
*/
class ToolbarEntry extends \Magento\Backend\Block\Template
{
/**
* Number of notifications showed on expandable window
*/
const NOTIFICATIONS_NUMBER = 3;
/**
* Number of notifications showed on icon
*/
const NOTIFICATIONS_COUNTER_MAX = 99;
/**
* Length of notification description showed by default
*/
const NOTIFICATION_DESCRIPTION_LENGTH = 150;
/**
* Collection of latest unread notifications
*
* @var \Magento\AdminNotification\Model\ResourceModel\Inbox\Collection
*/
protected $_notificationList;
/**
* @param \Magento\Backend\Block\Template\Context $context
* @param \Magento\AdminNotification\Model\ResourceModel\Inbox\Collection\Unread $notificationList
* @param array $data
*/
public function __construct(
\Magento\Backend\Block\Template\Context $context,
\Magento\AdminNotification\Model\ResourceModel\Inbox\Collection\Unread $notificationList,
array $data = []
) {
parent::__construct($context, $data);
$this->_notificationList = $notificationList;
}
/**
* Retrieve notification description start length
*
* @return int
*/
public function getNotificationDescriptionLength()
{
return self::NOTIFICATION_DESCRIPTION_LENGTH;
}
/**
* Retrieve notification counter max value
*
* @return int
*/
public function getNotificationCounterMax()
{
return self::NOTIFICATIONS_COUNTER_MAX;
}
/**
* Retrieve number of unread notifications
*
* @return int
*/
public function getUnreadNotificationCount()
{
return $this->_notificationList->getSize();
}
/**
* Retrieve the list of latest unread notifications
*
* @return \Magento\AdminNotification\Model\ResourceModel\Inbox\Collection
*/
public function getLatestUnreadNotifications()
{
return $this->_notificationList->setPageSize(self::NOTIFICATIONS_NUMBER);
}
/**
* Format notification date (show only time if notification has been added today)
*
* @param string $dateString
* @return string
*/
public function formatNotificationDate($dateString)
{
$date = new \DateTime($dateString);
if ($date == new \DateTime('today')) {
return $this->_localeDate->formatDateTime(
$date,
\IntlDateFormatter::NONE,
\IntlDateFormatter::SHORT
);
}
return $this->_localeDate->formatDateTime(
$date,
\IntlDateFormatter::MEDIUM,
\IntlDateFormatter::MEDIUM
);
}
}
<?php
/**
* Critical notification window
*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Block;
/**
* Admin notification window block
*
* @api
* @since 100.0.2
*/
class Window extends \Magento\Backend\Block\Template
{
/**
* XML path of Severity icons url
*/
const XML_SEVERITY_ICONS_URL_PATH = 'system/adminnotification/severity_icons_url';
/**
* Severity icons url
*
* @var string
*/
protected $_severityIconsUrl;
/**
* Authentication
*
* @var \Magento\Backend\Model\Auth\Session
*/
protected $_authSession;
/**
* Critical messages collection
*
* @var \Magento\AdminNotification\Model\ResourceModel\Inbox\Collection
*/
protected $_criticalCollection;
/**
* @var \Magento\AdminNotification\Model\Inbox
*/
protected $_latestItem;
/**
* The property is used to define content-scope of block. Can be private or public.
* If it isn't defined then application considers it as false.
*
* @var bool
*/
protected $_isScopePrivate;
/**
* @param \Magento\Backend\Block\Template\Context $context
* @param \Magento\Backend\Model\Auth\Session $authSession
* @param \Magento\AdminNotification\Model\ResourceModel\Inbox\Collection\Critical $criticalCollection
* @param array $data
*/
public function __construct(
\Magento\Backend\Block\Template\Context $context,
\Magento\Backend\Model\Auth\Session $authSession,
\Magento\AdminNotification\Model\ResourceModel\Inbox\Collection\Critical $criticalCollection,
array $data = []
) {
parent::__construct($context, $data);
$this->_authSession = $authSession;
$this->_criticalCollection = $criticalCollection;
$this->_isScopePrivate = true;
}
/**
* Render block
*
* @return string
*/
protected function _toHtml()
{
if ($this->canShow()) {
$this->setHeaderText($this->escapeHtml(__('Incoming Message')));
$this->setCloseText($this->escapeHtml(__('close')));
$this->setReadDetailsText($this->escapeHtml(__('Read Details')));
$this->setNoticeMessageText($this->escapeHtml($this->_getLatestItem()->getTitle()));
$this->setNoticeMessageUrl($this->escapeUrl($this->_getLatestItem()->getUrl()));
$this->setSeverityText('critical');
return parent::_toHtml();
}
return '';
}
/**
* Retrieve latest critical item
*
* @return bool|\Magento\AdminNotification\Model\Inbox
*/
protected function _getLatestItem()
{
if ($this->_latestItem == null) {
$items = array_values($this->_criticalCollection->getItems());
$this->_latestItem = false;
if (count($items)) {
$this->_latestItem = $items[0];
}
}
return $this->_latestItem;
}
/**
* Check whether block should be displayed
*
* @return bool
*/
public function canShow()
{
return $this->_authSession->isFirstPageAfterLogin() && $this->_getLatestItem();
}
}
<?php
/**
* Adminhtml AdminNotification controller
*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Controller\Adminhtml;
/**
* @api
* @since 100.0.2
*/
abstract class Notification extends \Magento\Backend\App\AbstractAction
{
/**
* Authorization level of a basic admin session
*/
const ADMIN_RESOURCE = 'Magento_AdminNotification::show_list';
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Controller\Adminhtml\Notification;
use Magento\AdminNotification\Controller\Adminhtml\Notification;
use Magento\AdminNotification\Model\NotificationService;
use Magento\Backend\App\Action;
use Magento\Framework\App\Action\HttpPostActionInterface;
use Magento\Framework\Controller\ResultFactory;
/**
* AdminNotification AjaxMarkAsRead controller
*/
class AjaxMarkAsRead extends Notification implements HttpPostActionInterface
{
/**
* @var NotificationService
*/
private $notificationService;
/**
* @param Action\Context $context
* @param NotificationService $notificationService
*/
public function __construct(Action\Context $context, NotificationService $notificationService)
{
parent::__construct($context);
$this->notificationService = $notificationService;
}
/**
* Mark notification as read (AJAX action)
*
* @return \Magento\Framework\Controller\Result\Json|void
* @throws \InvalidArgumentException
*/
public function execute()
{
if (!$this->getRequest()->getPostValue()) {
return;
}
$notificationId = (int)$this->getRequest()->getPost('id');
$responseData = [];
try {
$this->notificationService->markAsRead($notificationId);
$responseData['success'] = true;
} catch (\Exception $e) {
$responseData['success'] = false;
}
/** @var \Magento\Framework\Controller\Result\Json $resultJson */
$resultJson = $this->resultFactory->create(ResultFactory::TYPE_JSON);
$resultJson->setData($responseData);
return $resultJson;
}
}
<?php
/**
*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Controller\Adminhtml\Notification;
use Magento\Framework\App\Action\HttpGetActionInterface as HttpGetActionInterface;
class Index extends \Magento\AdminNotification\Controller\Adminhtml\Notification implements HttpGetActionInterface
{
/**
* @return void
*/
public function execute()
{
$this->_view->loadLayout();
$this->_setActiveMenu(
'Magento_AdminNotification::system_adminnotification'
)->_addBreadcrumb(
__('Messages Inbox'),
__('Messages Inbox')
);
$this->_view->getPage()->getConfig()->getTitle()->prepend(__('Notifications'));
$this->_view->renderLayout();
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Controller\Adminhtml\Notification;
use Magento\AdminNotification\Controller\Adminhtml\Notification;
use Magento\AdminNotification\Model\NotificationService;
use Magento\Backend\App\Action;
use Magento\Framework\App\Action\HttpGetActionInterface;
use Magento\Framework\Exception\LocalizedException;
/**
* AdminNotification MarkAsRead controller
*/
class MarkAsRead extends Notification implements HttpGetActionInterface
{
/**
* Authorization level of a basic admin session
*
* @see _isAllowed()
*/
const ADMIN_RESOURCE = 'Magento_AdminNotification::mark_as_read';
/**
* @var NotificationService
*/
private $notificationService;
/**
* @param Action\Context $context
* @param NotificationService $notificationService
*/
public function __construct(Action\Context $context, NotificationService $notificationService)
{
parent::__construct($context);
$this->notificationService = $notificationService;
}
/**
* @inheritdoc
*/
public function execute()
{
$notificationId = (int)$this->getRequest()->getParam('id');
if ($notificationId) {
try {
$this->notificationService->markAsRead($notificationId);
$this->messageManager->addSuccessMessage(__('The message has been marked as Read.'));
} catch (LocalizedException $e) {
$this->messageManager->addErrorMessage($e->getMessage());
} catch (\Exception $e) {
$this->messageManager->addExceptionMessage(
$e,
__("We couldn't mark the notification as Read because of an error.")
);
}
return $this->getResponse()->setRedirect($this->_redirect->getRedirectUrl($this->getUrl('*')));
}
return $this->_redirect('adminhtml/*/');
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Controller\Adminhtml\Notification;
use Magento\AdminNotification\Controller\Adminhtml\Notification;
use Magento\AdminNotification\Model\InboxFactory as InboxModelFactory;
use Magento\Backend\App\Action;
use Magento\Framework\App\Action\HttpPostActionInterface;
/**
* AdminNotification MassMarkAsRead controller
*/
class MassMarkAsRead extends Notification implements HttpPostActionInterface
{
/**
* Authorization level of a basic admin session
*
* @see _isAllowed()
*/
const ADMIN_RESOURCE = 'Magento_AdminNotification::mark_as_read';
/**
* @var InboxModelFactory
*/
private $inboxModelFactory;
/**
* @param Action\Context $context
* @param InboxModelFactory $inboxModelFactory
*/
public function __construct(Action\Context $context, InboxModelFactory $inboxModelFactory)
{
parent::__construct($context);
$this->inboxModelFactory = $inboxModelFactory;
}
/**
* @inheritdoc
*/
public function execute()
{
$ids = $this->getRequest()->getParam('notification');
if (!is_array($ids)) {
$this->messageManager->addErrorMessage(__('Please select messages.'));
} else {
try {
foreach ($ids as $id) {
$model = $this->inboxModelFactory->create()->load($id);
if ($model->getId()) {
$model->setIsRead(1)->save();
}
}
$this->messageManager->addSuccessMessage(
__('A total of %1 record(s) have been marked as Read.', count($ids))
);
} catch (\Magento\Framework\Exception\LocalizedException $e) {
$this->messageManager->addErrorMessage($e->getMessage());
} catch (\Exception $e) {
$this->messageManager->addExceptionMessage(
$e,
__("We couldn't mark the notification as Read because of an error.")
);
}
}
return $this->_redirect('adminhtml/*/');
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Controller\Adminhtml\Notification;
use Magento\AdminNotification\Controller\Adminhtml\Notification;
use Magento\AdminNotification\Model\InboxFactory as InboxModelFactory;
use Magento\Backend\App\Action;
use Magento\Framework\App\Action\HttpPostActionInterface;
/**
* AdminNotification MassRemove controller
*/
class MassRemove extends Notification implements HttpPostActionInterface
{
/**
* Authorization level of a basic admin session
*
* @see _isAllowed()
*/
const ADMIN_RESOURCE = 'Magento_AdminNotification::adminnotification_remove';
/**
* @var InboxModelFactory
*/
private $inboxModelFactory;
/**
* @param Action\Context $context
* @param InboxModelFactory $inboxModelFactory
*/
public function __construct(Action\Context $context, InboxModelFactory $inboxModelFactory)
{
parent::__construct($context);
$this->inboxModelFactory = $inboxModelFactory;
}
/**
* @inheritdoc
*/
public function execute()
{
$ids = $this->getRequest()->getParam('notification');
if (!is_array($ids)) {
$this->messageManager->addErrorMessage(__('Please select messages.'));
} else {
try {
foreach ($ids as $id) {
$model = $this->inboxModelFactory->create()->load($id);
if ($model->getId()) {
$model->setIsRemove(1)->save();
}
}
$this->messageManager->addSuccessMessage(__('Total of %1 record(s) have been removed.', count($ids)));
} catch (\Magento\Framework\Exception\LocalizedException $e) {
$this->messageManager->addErrorMessage($e->getMessage());
} catch (\Exception $e) {
$this->messageManager->addExceptionMessage(
$e,
__("We couldn't remove the messages because of an error.")
);
}
}
return $this->_redirect('adminhtml/*/');
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Controller\Adminhtml\Notification;
use Magento\AdminNotification\Controller\Adminhtml\Notification;
use Magento\AdminNotification\Model\InboxFactory as InboxModelFactory;
use Magento\Backend\App\Action;
use Magento\Framework\App\Action\HttpGetActionInterface;
/**
* AdminNotification Remove controller
*/
class Remove extends Notification implements HttpGetActionInterface
{
/**
* Authorization level of a basic admin session
*
* @see _isAllowed()
*/
const ADMIN_RESOURCE = 'Magento_AdminNotification::adminnotification_remove';
/**
* @var InboxModelFactory
*/
private $inboxModelFactory;
/**
* @param Action\Context $context
* @param InboxModelFactory $inboxModelFactory
*/
public function __construct(Action\Context $context, InboxModelFactory $inboxModelFactory)
{
parent::__construct($context);
$this->inboxModelFactory = $inboxModelFactory;
}
/**
* @inheritdoc
*/
public function execute()
{
if ($id = $this->getRequest()->getParam('id')) {
$model = $this->inboxModelFactory->create()->load($id);
if (!$model->getId()) {
return $this->_redirect('adminhtml/*/');
}
try {
$model->setIsRemove(1)->save();
$this->messageManager->addSuccessMessage(__('The message has been removed.'));
} catch (\Magento\Framework\Exception\LocalizedException $e) {
$this->messageManager->addErrorMessage($e->getMessage());
} catch (\Exception $e) {
$this->messageManager->addExceptionMessage(
$e,
__("We couldn't remove the messages because of an error.")
);
}
return $this->_redirect('adminhtml/*/');
}
return $this->_redirect('adminhtml/*/');
}
}
<?php
/**
*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Controller\Adminhtml\System\Message;
use Magento\Framework\Controller\ResultFactory;
class ListAction extends \Magento\Backend\App\AbstractAction
{
/**
* Authorization level of a basic admin session
*/
const ADMIN_RESOURCE = 'Magento_AdminNotification::show_list';
/**
* @var \Magento\Framework\Json\Helper\Data
* @deprecated 100.3.0
*/
protected $jsonHelper;
/**
* @var \Magento\AdminNotification\Model\ResourceModel\System\Message\Collection
*/
protected $messageCollection;
/**
* Initialize ListAction
*
* @param \Magento\Backend\App\Action\Context $context
* @param \Magento\Framework\Json\Helper\Data $jsonHelper
* @param \Magento\AdminNotification\Model\ResourceModel\System\Message\Collection $messageCollection
*/
public function __construct(
\Magento\Backend\App\Action\Context $context,
\Magento\Framework\Json\Helper\Data $jsonHelper,
\Magento\AdminNotification\Model\ResourceModel\System\Message\Collection $messageCollection
) {
$this->jsonHelper = $jsonHelper;
$this->messageCollection = $messageCollection;
parent::__construct($context);
}
/**
* @return \Magento\Framework\Controller\Result\Json
*/
public function execute()
{
$severity = $this->getRequest()->getParam('severity');
if ($severity) {
$this->messageCollection->setSeverity($severity);
}
$result = [];
foreach ($this->messageCollection->getItems() as $item) {
$result[] = [
'severity' => $item->getSeverity(),
'text' => $item->getText(),
];
}
if (empty($result)) {
$result[] = [
'severity' => (string)\Magento\Framework\Notification\MessageInterface::SEVERITY_NOTICE,
'text' => __(
'You have viewed and resolved all recent system notices. '
. 'Please refresh the web page to clear the notice alert.'
)
];
}
/** @var \Magento\Framework\Controller\Result\Json $resultJson */
$resultJson = $this->resultFactory->create(ResultFactory::TYPE_JSON);
$resultJson->setData($result);
return $resultJson;
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Model\Config\Source;
/**
* AdminNotification update frequency source
*
* @codeCoverageIgnore
* @api
* @since 100.0.2
*/
class Frequency implements \Magento\Framework\Option\ArrayInterface
{
/**
* @return array
*/
public function toOptionArray()
{
return [
1 => __('1 Hour'),
2 => __('2 Hours'),
6 => __('6 Hours'),
12 => __('12 Hours'),
24 => __('24 Hours')
];
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Model;
use Magento\Framework\Escaper;
use Magento\Framework\App\ObjectManager;
use Magento\Framework\Config\ConfigOptionsListConstants;
/**
* AdminNotification Feed model
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
* @api
* @since 100.0.2
*/
class Feed extends \Magento\Framework\Model\AbstractModel
{
const XML_USE_HTTPS_PATH = 'system/adminnotification/use_https';
const XML_FEED_URL_PATH = 'system/adminnotification/feed_url';
const XML_FREQUENCY_PATH = 'system/adminnotification/frequency';
const XML_LAST_UPDATE_PATH = 'system/adminnotification/last_update';
/**
* @var Escaper
*/
private $escaper;
/**
* Feed url
*
* @var string
*/
protected $_feedUrl;
/**
* @var \Magento\Backend\App\ConfigInterface
*/
protected $_backendConfig;
/**
* @var \Magento\AdminNotification\Model\InboxFactory
*/
protected $_inboxFactory;
/**
* @var \Magento\Framework\HTTP\Adapter\CurlFactory
*
*/
protected $curlFactory;
/**
* Deployment configuration
*
* @var \Magento\Framework\App\DeploymentConfig
*/
protected $_deploymentConfig;
/**
* @var \Magento\Framework\App\ProductMetadataInterface
*/
protected $productMetadata;
/**
* @var \Magento\Framework\UrlInterface
*/
protected $urlBuilder;
/**
* @param \Magento\Framework\Model\Context $context
* @param \Magento\Framework\Registry $registry
* @param \Magento\Backend\App\ConfigInterface $backendConfig
* @param InboxFactory $inboxFactory
* @param \Magento\Framework\HTTP\Adapter\CurlFactory $curlFactory
* @param \Magento\Framework\App\DeploymentConfig $deploymentConfig
* @param \Magento\Framework\App\ProductMetadataInterface $productMetadata
* @param \Magento\Framework\UrlInterface $urlBuilder
* @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource
* @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
* @param array $data
* @param Escaper|null $escaper
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
\Magento\Framework\Model\Context $context,
\Magento\Framework\Registry $registry,
\Magento\Backend\App\ConfigInterface $backendConfig,
\Magento\AdminNotification\Model\InboxFactory $inboxFactory,
\Magento\Framework\HTTP\Adapter\CurlFactory $curlFactory,
\Magento\Framework\App\DeploymentConfig $deploymentConfig,
\Magento\Framework\App\ProductMetadataInterface $productMetadata,
\Magento\Framework\UrlInterface $urlBuilder,
\Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
\Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
array $data = [],
Escaper $escaper = null
) {
parent::__construct($context, $registry, $resource, $resourceCollection, $data);
$this->_backendConfig = $backendConfig;
$this->_inboxFactory = $inboxFactory;
$this->curlFactory = $curlFactory;
$this->_deploymentConfig = $deploymentConfig;
$this->productMetadata = $productMetadata;
$this->urlBuilder = $urlBuilder;
$this->escaper = $escaper ?? ObjectManager::getInstance()->get(
Escaper::class
);
}
/**
* Init model
*
* @return void
* phpcs:disable Magento2.CodeAnalysis.EmptyBlock
*/
protected function _construct()
{
}
/**
* Retrieve feed url
*
* @return string
*/
public function getFeedUrl()
{
$httpPath = $this->_backendConfig->isSetFlag(self::XML_USE_HTTPS_PATH) ? 'https://' : 'http://';
if ($this->_feedUrl === null) {
$this->_feedUrl = $httpPath . $this->_backendConfig->getValue(self::XML_FEED_URL_PATH);
}
return $this->_feedUrl;
}
/**
* Check feed for modification
*
* @return $this
*/
public function checkUpdate()
{
if ($this->getFrequency() + $this->getLastUpdate() > time()) {
return $this;
}
$feedData = [];
$feedXml = $this->getFeedData();
$installDate = strtotime($this->_deploymentConfig->get(ConfigOptionsListConstants::CONFIG_PATH_INSTALL_DATE));
if ($feedXml && $feedXml->channel && $feedXml->channel->item) {
foreach ($feedXml->channel->item as $item) {
$itemPublicationDate = strtotime((string)$item->pubDate);
if ($installDate <= $itemPublicationDate) {
$feedData[] = [
'severity' => (int)$item->severity,
'date_added' => date('Y-m-d H:i:s', $itemPublicationDate),
'title' => $this->escapeString($item->title),
'description' => $this->escapeString($item->description),
'url' => $this->escapeString($item->link),
];
}
}
if ($feedData) {
$this->_inboxFactory->create()->parse(array_reverse($feedData));
}
}
$this->setLastUpdate();
return $this;
}
/**
* Retrieve Update Frequency
*
* @return int
*/
public function getFrequency()
{
return $this->_backendConfig->getValue(self::XML_FREQUENCY_PATH) * 3600;
}
/**
* Retrieve Last update time
*
* @return int
*/
public function getLastUpdate()
{
return $this->_cacheManager->load('admin_notifications_lastcheck');
}
/**
* Set last update time (now)
*
* @return $this
*/
public function setLastUpdate()
{
$this->_cacheManager->save(time(), 'admin_notifications_lastcheck');
return $this;
}
/**
* Retrieve feed data as XML element
*
* @return \SimpleXMLElement
*/
public function getFeedData()
{
$curl = $this->curlFactory->create();
$curl->setConfig(
[
'timeout' => 2,
'useragent' => $this->productMetadata->getName()
. '/' . $this->productMetadata->getVersion()
. ' (' . $this->productMetadata->getEdition() . ')',
'referer' => $this->urlBuilder->getUrl('*/*/*')
]
);
$curl->write(\Zend_Http_Client::GET, $this->getFeedUrl(), '1.0');
$data = $curl->read();
$data = preg_split('/^\r?$/m', $data, 2);
$data = trim($data[1]);
$curl->close();
try {
$xml = new \SimpleXMLElement($data);
} catch (\Exception $e) {
return false;
}
return $xml;
}
/**
* Retrieve feed as XML element
*
* @return \SimpleXMLElement
*/
public function getFeedXml()
{
try {
$data = $this->getFeedData();
$xml = new \SimpleXMLElement($data);
} catch (\Exception $e) {
$xml = new \SimpleXMLElement('<?xml version="1.0" encoding="utf-8" ?>');
}
return $xml;
}
/**
* Converts incoming data to string format and escapes special characters.
*
* @param \SimpleXMLElement $data
* @return string
*/
private function escapeString(\SimpleXMLElement $data)
{
return $this->escaper->escapeHtml((string)$data);
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Model;
use Magento\Framework\Notification\MessageInterface;
use Magento\Framework\Notification\NotifierInterface;
use Magento\AdminNotification\Model\InboxInterface;
/**
* AdminNotification Inbox model
*
* @method int getSeverity()
* @method \Magento\AdminNotification\Model\Inbox setSeverity(int $value)
* @method string getDateAdded()
* @method \Magento\AdminNotification\Model\Inbox setDateAdded(string $value)
* @method string getTitle()
* @method \Magento\AdminNotification\Model\Inbox setTitle(string $value)
* @method string getDescription()
* @method \Magento\AdminNotification\Model\Inbox setDescription(string $value)
* @method string getUrl()
* @method \Magento\AdminNotification\Model\Inbox setUrl(string $value)
* @method int getIsRead()
* @method \Magento\AdminNotification\Model\Inbox setIsRead(int $value)
* @method int getIsRemove()
* @method \Magento\AdminNotification\Model\Inbox setIsRemove(int $value)
*
* @api
* @since 100.0.2
*/
class Inbox extends \Magento\Framework\Model\AbstractModel implements NotifierInterface, InboxInterface
{
/**
* @return void
*/
protected function _construct()
{
$this->_init(\Magento\AdminNotification\Model\ResourceModel\Inbox::class);
}
/**
* {@inheritdoc}
*/
public function getSeverities($severity = null)
{
$severities = [
MessageInterface::SEVERITY_CRITICAL => __('critical'),
MessageInterface::SEVERITY_MAJOR => __('major'),
MessageInterface::SEVERITY_MINOR => __('minor'),
MessageInterface::SEVERITY_NOTICE => __('notice'),
];
if ($severity !== null) {
if (isset($severities[$severity])) {
return $severities[$severity];
}
return null;
}
return $severities;
}
/**
* {@inheritdoc}
*/
public function loadLatestNotice()
{
$this->setData([]);
$this->getResource()->loadLatestNotice($this);
return $this;
}
/**
* {@inheritdoc}
*/
public function getNoticeStatus()
{
return $this->getResource()->getNoticeStatus($this);
}
/**
* Parse and save new data
*
* @param array $data
* @return $this
*/
public function parse(array $data)
{
$this->getResource()->parse($this, $data);
return $this;
}
/**
* Add new message
*
* @param int $severity
* @param string $title
* @param string|string[] $description
* @param string $url
* @param bool $isInternal
* @throws \Magento\Framework\Exception\LocalizedException
* @return $this
*/
public function add($severity, $title, $description, $url = '', $isInternal = true)
{
if (!$this->getSeverities($severity)) {
throw new \Magento\Framework\Exception\LocalizedException(__('Wrong message type'));
}
if (is_array($description)) {
$description = '<ul><li>' . implode('</li><li>', $description) . '</li></ul>';
}
$date = date('Y-m-d H:i:s');
$this->parse(
[
[
'severity' => $severity,
'date_added' => $date,
'title' => $title,
'description' => $description,
'url' => $url,
'internal' => $isInternal,
],
]
);
return $this;
}
/**
* Add critical severity message
*
* @param string $title
* @param string|string[] $description
* @param string $url
* @param bool $isInternal
* @return $this
*/
public function addCritical($title, $description, $url = '', $isInternal = true)
{
$this->add(MessageInterface::SEVERITY_CRITICAL, $title, $description, $url, $isInternal);
return $this;
}
/**
* Add major severity message
*
* @param string $title
* @param string|string[] $description
* @param string $url
* @param bool $isInternal
* @return $this
*/
public function addMajor($title, $description, $url = '', $isInternal = true)
{
$this->add(MessageInterface::SEVERITY_MAJOR, $title, $description, $url, $isInternal);
return $this;
}
/**
* Add minor severity message
*
* @param string $title
* @param string|string[] $description
* @param string $url
* @param bool $isInternal
* @return $this
*/
public function addMinor($title, $description, $url = '', $isInternal = true)
{
$this->add(MessageInterface::SEVERITY_MINOR, $title, $description, $url, $isInternal);
return $this;
}
/**
* Add notice
*
* @param string $title
* @param string|string[] $description
* @param string $url
* @param bool $isInternal
* @return $this
*/
public function addNotice($title, $description, $url = '', $isInternal = true)
{
$this->add(MessageInterface::SEVERITY_NOTICE, $title, $description, $url, $isInternal);
return $this;
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Model;
/**
* AdminNotification Inbox interface
*
* @api
* @since 100.0.2
*/
interface InboxInterface
{
/**
* Retrieve Severity collection array
*
* @param int|null $severity
* @return array|string|null
* @api
*/
public function getSeverities($severity = null);
/**
* Retrieve Latest Notice
*
* @return $this
* @api
*/
public function loadLatestNotice();
/**
* Retrieve notice statuses
*
* @return array
* @api
*/
public function getNoticeStatus();
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Model;
/**
* Notification service model
*
* @api
* @since 100.0.2
*/
class NotificationService
{
/**
* @var \Magento\AdminNotification\Model\InboxFactory $notificationFactory
*/
protected $_notificationFactory;
/**
* @param \Magento\AdminNotification\Model\InboxFactory $notificationFactory
*/
public function __construct(\Magento\AdminNotification\Model\InboxFactory $notificationFactory)
{
$this->_notificationFactory = $notificationFactory;
}
/**
* Mark notification as read
*
* @param int $notificationId
* @return void
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function markAsRead($notificationId)
{
$notification = $this->_notificationFactory->create();
$notification->load($notificationId);
if (!$notification->getId()) {
throw new \Magento\Framework\Exception\LocalizedException(__('Wrong notification ID specified.'));
}
$notification->setIsRead(1);
$notification->save();
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
/**
* AdminNotification Inbox model
*/
namespace Magento\AdminNotification\Model\ResourceModel\Grid;
/**
* @api
* @since 100.0.2
*/
class Collection extends \Magento\AdminNotification\Model\ResourceModel\Inbox\Collection
{
/**
* Add remove filter
*
* @return Collection|\Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
*/
protected function _initSelect()
{
parent::_initSelect();
$this->addRemoveFilter();
return $this;
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Model\ResourceModel;
/**
* Inbox resource model
*
* @api
* @since 100.0.2
*/
class Inbox extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
{
/**
* AdminNotification Resource initialization
*
* @return void
*/
protected function _construct()
{
$this->_init('adminnotification_inbox', 'notification_id');
}
/**
* Load latest notice
*
* @param \Magento\AdminNotification\Model\Inbox $object
* @return $this
*/
public function loadLatestNotice(\Magento\AdminNotification\Model\Inbox $object)
{
$connection = $this->getConnection();
$select = $connection->select()->from(
$this->getMainTable()
)->order(
$this->getIdFieldName() . ' DESC'
)->where(
'is_read != 1'
)->where(
'is_remove != 1'
)->limit(
1
);
$data = $connection->fetchRow($select);
if ($data) {
$object->setData($data);
}
$this->_afterLoad($object);
return $this;
}
/**
* Get notifications grouped by severity
*
* @param \Magento\AdminNotification\Model\Inbox $object
* @return array
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function getNoticeStatus(\Magento\AdminNotification\Model\Inbox $object)
{
$connection = $this->getConnection();
$select = $connection->select()->from(
$this->getMainTable(),
[
'severity' => 'severity',
'count_notice' => new \Zend_Db_Expr('COUNT(' . $this->getIdFieldName() . ')')
]
)->group(
'severity'
)->where(
'is_remove=?',
0
)->where(
'is_read=?',
0
);
return $connection->fetchPairs($select);
}
/**
* Save notifications (if not exists)
*
* @param \Magento\AdminNotification\Model\Inbox $object
* @param array $data
* @return void
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function parse(\Magento\AdminNotification\Model\Inbox $object, array $data)
{
$connection = $this->getConnection();
foreach ($data as $item) {
$select = $connection->select()->from($this->getMainTable())->where('title = ?', $item['title']);
if (empty($item['url'])) {
$select->where('url IS NULL');
} else {
$select->where('url = ?', $item['url']);
}
if (isset($item['internal'])) {
$row = false;
unset($item['internal']);
} else {
$row = $connection->fetchRow($select);
}
if (!$row) {
$connection->insert($this->getMainTable(), $item);
}
}
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Model\ResourceModel\Inbox;
/**
* AdminNotification Inbox model
*
* @api
* @since 100.0.2
*/
class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
{
/**
* Resource collection initialization
*
* @return void
*/
protected function _construct()
{
$this->_init(
\Magento\AdminNotification\Model\Inbox::class,
\Magento\AdminNotification\Model\ResourceModel\Inbox::class
);
}
/**
* Add remove filter
*
* @return $this
*/
public function addRemoveFilter()
{
$this->getSelect()->where('is_remove=?', 0);
return $this;
}
}
<?php
/**
* Critical messages collection
*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Model\ResourceModel\Inbox\Collection;
/**
* @api
* @since 100.0.2
*/
class Critical extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
{
/**
* Resource collection initialization
*
* @return void
*/
protected function _construct()
{
$this->_init(
\Magento\AdminNotification\Model\Inbox::class,
\Magento\AdminNotification\Model\ResourceModel\Inbox::class
);
}
/**
* @return $this
*/
protected function _initSelect()
{
parent::_initSelect();
$this->addOrder(
'notification_id',
self::SORT_ORDER_DESC
)->addFieldToFilter(
'is_read',
['neq' => 1]
)->addFieldToFilter(
'is_remove',
['neq' => 1]
)->addFieldToFilter(
'severity',
\Magento\Framework\Notification\MessageInterface::SEVERITY_CRITICAL
)->setPageSize(
1
);
return $this;
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
/**
* Collection of unread notifications
*/
namespace Magento\AdminNotification\Model\ResourceModel\Inbox\Collection;
/**
* @api
* @since 100.0.2
*/
class Unread extends \Magento\AdminNotification\Model\ResourceModel\Inbox\Collection
{
/**
* Init collection select
*
* @return \Magento\AdminNotification\Model\ResourceModel\Inbox\Collection\Unread
*/
protected function _initSelect()
{
parent::_initSelect();
$this->addFilter('is_remove', 0);
$this->addFilter('is_read', 0);
$this->setOrder('date_added');
return $this;
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Model\ResourceModel\System;
/**
* @api
* @since 100.0.2
*/
class Message extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
{
/**
* Flag that notifies whether Primary key of table is auto-incremented
*
* @var bool
*/
protected $_isPkAutoIncrement = false;
/**
* Resource initialization
*
* @return void
*/
protected function _construct()
{
$this->_init('admin_system_messages', 'identity');
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Model\ResourceModel\System\Message;
/**
* @api
* @since 100.0.2
*/
class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
{
/**
* System message list
*
* @var \Magento\Framework\Notification\MessageList
*/
protected $_messageList;
/**
* Number of messages by severity
*
* @var array
*/
protected $_countBySeverity = [];
/**
* @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory
* @param \Psr\Log\LoggerInterface $logger
* @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
* @param \Magento\Framework\Event\ManagerInterface $eventManager
* @param \Magento\Framework\Notification\MessageList $messageList
* @param mixed $connection
* @param \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource
*/
public function __construct(
\Magento\Framework\Data\Collection\EntityFactory $entityFactory,
\Psr\Log\LoggerInterface $logger,
\Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
\Magento\Framework\Event\ManagerInterface $eventManager,
\Magento\Framework\Notification\MessageList $messageList,
\Magento\Framework\DB\Adapter\AdapterInterface $connection = null,
\Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource = null
) {
$this->_messageList = $messageList;
parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $connection, $resource);
}
/**
* Resource collection initialization
*
* @return void
*/
protected function _construct()
{
$this->_init(
\Magento\AdminNotification\Model\System\Message::class,
\Magento\AdminNotification\Model\ResourceModel\System\Message::class
);
}
/**
* Initialize db query
*
* @return void
*/
protected function _initSelect()
{
parent::_initSelect();
$this->addOrder('severity', self::SORT_ORDER_ASC)->addOrder('created_at');
}
/**
* Initialize system messages after load
*
* @return void
*/
protected function _afterLoad()
{
foreach ($this->_items as $key => $item) {
$message = $this->_messageList->getMessageByIdentity($item->getIdentity());
if ($message) {
$item->setText($message->getText());
if (array_key_exists($message->getSeverity(), $this->_countBySeverity)) {
$this->_countBySeverity[$message->getSeverity()]++;
} else {
$this->_countBySeverity[$message->getSeverity()] = 1;
}
} else {
unset($this->_items[$key]);
}
}
}
/**
* Set message severity filter
*
* @param int $severity
* @return $this
*/
public function setSeverity($severity)
{
$this->addFieldToFilter('severity', ['eq' => $severity * 1]);
return $this;
}
/**
* Retrieve number of messages by severity
*
* @param int $severity
* @return int
*/
public function getCountBySeverity($severity)
{
return isset($this->_countBySeverity[$severity]) ? $this->_countBySeverity[$severity] : 0;
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Model\ResourceModel\System\Message\Collection;
/**
* @api
* @since 100.0.2
*/
class Synchronized extends \Magento\AdminNotification\Model\ResourceModel\System\Message\Collection
{
/**
* Unread message list
*
* @var \Magento\Framework\Notification\MessageInterface[]
*/
protected $_unreadMessages = [];
/**
* Store new messages in database and remove outdated messages
*
* @return $this|\Magento\Framework\Model\ResourceModel\Db\AbstractDb
*/
public function _afterLoad()
{
$messages = $this->_messageList->asArray();
$persisted = [];
$unread = [];
foreach ($messages as $message) {
if ($message->isDisplayed()) {
foreach ($this->_items as $persistedKey => $persistedMessage) {
if ($message->getIdentity() == $persistedMessage->getIdentity()) {
$persisted[$persistedKey] = $persistedMessage;
continue 2;
}
}
$unread[] = $message;
}
}
$removed = array_diff_key($this->_items, $persisted);
foreach ($removed as $removedItem) {
$removedItem->delete();
}
foreach ($unread as $unreadItem) {
$item = $this->getNewEmptyItem();
$item->setIdentity($unreadItem->getIdentity())->setSeverity($unreadItem->getSeverity())->save();
}
if (count($removed) || count($unread)) {
$this->_unreadMessages = $unread;
$this->clear();
$this->load();
} else {
parent::_afterLoad();
}
return $this;
}
/**
* Retrieve list of unread messages
*
* @return \Magento\Framework\Notification\MessageInterface[]
*/
public function getUnread()
{
return $this->_unreadMessages;
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Model\System;
/**
* @codeCoverageIgnore
* @api
* @since 100.0.2
*/
class Message extends \Magento\Framework\Model\AbstractModel implements \Magento\Framework\Notification\MessageInterface
{
/**
* @return void
*/
protected function _construct()
{
$this->_init(\Magento\AdminNotification\Model\ResourceModel\System\Message::class);
}
/**
* Check whether
*
* @return bool
*/
public function isDisplayed()
{
return true;
}
/**
* Retrieve message text
*
* @return string
*/
public function getText()
{
return $this->getData('text');
}
/**
* Retrieve message severity
*
* @return int
*/
public function getSeverity()
{
return $this->_getData('severity');
}
/**
* Retrieve unique message identity
*
* @return string
*/
public function getIdentity()
{
return $this->_getData('identity');
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Model\System\Message;
use Magento\Store\Model\Store;
/**
* @deprecated 100.1.0
*/
class Baseurl implements \Magento\Framework\Notification\MessageInterface
{
/**
* @var \Magento\Framework\UrlInterface
*/
protected $_urlBuilder;
/**
* @var \Magento\Framework\App\Config\ScopeConfigInterface
*/
protected $_config;
/**
* @var \Magento\Store\Model\StoreManagerInterface
*/
protected $_storeManager;
/**
* @var \Magento\Framework\App\Config\ValueFactory
*/
protected $_configValueFactory;
/**
* @param \Magento\Framework\App\Config\ScopeConfigInterface $config
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
* @param \Magento\Framework\UrlInterface $urlBuilder
* @param \Magento\Framework\App\Config\ValueFactory $configValueFactory
*/
public function __construct(
\Magento\Framework\App\Config\ScopeConfigInterface $config,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Framework\UrlInterface $urlBuilder,
\Magento\Framework\App\Config\ValueFactory $configValueFactory
) {
$this->_urlBuilder = $urlBuilder;
$this->_config = $config;
$this->_storeManager = $storeManager;
$this->_configValueFactory = $configValueFactory;
}
/**
* Get url for config settings where base url option can be changed
*
* @return string
*/
protected function _getConfigUrl()
{
$output = '';
$defaultUnsecure = $this->_config->getValue(Store::XML_PATH_UNSECURE_BASE_URL, 'default');
$defaultSecure = $this->_config->getValue(Store::XML_PATH_SECURE_BASE_URL, 'default');
if ($defaultSecure == \Magento\Store\Model\Store::BASE_URL_PLACEHOLDER ||
$defaultUnsecure == \Magento\Store\Model\Store::BASE_URL_PLACEHOLDER
) {
$output = $this->_urlBuilder->getUrl('adminhtml/system_config/edit', ['section' => 'web']);
} else {
/** @var $dataCollection \Magento\Config\Model\ResourceModel\Config\Data\Collection */
$dataCollection = $this->_configValueFactory->create()->getCollection();
$dataCollection->addValueFilter(\Magento\Store\Model\Store::BASE_URL_PLACEHOLDER);
/** @var $data \Magento\Framework\App\Config\ValueInterface */
foreach ($dataCollection as $data) {
if ($data->getScope() == 'stores') {
$code = $this->_storeManager->getStore($data->getScopeId())->getCode();
$output = $this->_urlBuilder->getUrl(
'adminhtml/system_config/edit',
['section' => 'web', 'store' => $code]
);
break;
} elseif ($data->getScope() == 'websites') {
$code = $this->_storeManager->getWebsite($data->getScopeId())->getCode();
$output = $this->_urlBuilder->getUrl(
'adminhtml/system_config/edit',
['section' => 'web', 'website' => $code]
);
break;
}
}
}
return $output;
}
/**
* Retrieve unique message identity
*
* @return string
*/
public function getIdentity()
{
// md5() here is not for cryptographic use.
// phpcs:ignore Magento2.Security.InsecureFunction
return md5('BASE_URL' . $this->_getConfigUrl());
}
/**
* Check whether
*
* @return bool
*/
public function isDisplayed()
{
return (bool)$this->_getConfigUrl();
}
/**
* Retrieve message text
*
* @return \Magento\Framework\Phrase
*/
public function getText()
{
return __(
'{{base_url}} is not recommended to use in a production environment to declare the Base Unsecure '
. 'URL / Base Secure URL. We highly recommend changing this value in your Magento '
. '<a href="%1">configuration</a>.',
$this->_getConfigUrl()
);
}
/**
* Retrieve message severity
*
* @return int
*/
public function getSeverity()
{
return self::SEVERITY_CRITICAL;
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Model\System\Message;
/**
* @api
* @since 100.0.2
*/
class CacheOutdated implements \Magento\Framework\Notification\MessageInterface
{
/**
* @var \Magento\Framework\UrlInterface
*/
protected $_urlBuilder;
/**
* @var \Magento\Framework\AuthorizationInterface
*/
protected $_authorization;
/**
* @var \Magento\Framework\App\Cache\TypeListInterface
*/
protected $_cacheTypeList;
/**
* @param \Magento\Framework\AuthorizationInterface $authorization
* @param \Magento\Framework\UrlInterface $urlBuilder
* @param \Magento\Framework\App\Cache\TypeListInterface $cacheTypeList
*/
public function __construct(
\Magento\Framework\AuthorizationInterface $authorization,
\Magento\Framework\UrlInterface $urlBuilder,
\Magento\Framework\App\Cache\TypeListInterface $cacheTypeList
) {
$this->_authorization = $authorization;
$this->_urlBuilder = $urlBuilder;
$this->_cacheTypeList = $cacheTypeList;
}
/**
* Get array of cache types which require data refresh
*
* @return array
*/
protected function _getCacheTypesForRefresh()
{
$output = [];
foreach ($this->_cacheTypeList->getInvalidated() as $type) {
$output[] = $type->getCacheType();
}
return $output;
}
/**
* Retrieve unique message identity
*
* @return string
*/
public function getIdentity()
{
// md5() here is not for cryptographic use.
// phpcs:ignore Magento2.Security.InsecureFunction
return md5('cache' . implode(':', $this->_getCacheTypesForRefresh()));
}
/**
* Check whether
*
* @return bool
*/
public function isDisplayed()
{
return $this->_authorization->isAllowed(
'Magento_Backend::cache'
) && count(
$this->_getCacheTypesForRefresh()
) > 0;
}
/**
* Retrieve message text
*
* @return string
*/
public function getText()
{
$cacheTypes = implode(', ', $this->_getCacheTypesForRefresh());
$message = __('One or more of the Cache Types are invalidated: %1. ', $cacheTypes) . ' ';
$url = $this->_urlBuilder->getUrl('adminhtml/cache');
$message .= __('Please go to <a href="%1">Cache Management</a> and refresh cache types.', $url);
return $message;
}
/**
* Retrieve problem management url
*
* @return string|null
*/
public function getLink()
{
return $this->_urlBuilder->getUrl('adminhtml/cache');
}
/**
* Retrieve message severity
*
* @return int
*/
public function getSeverity()
{
return \Magento\Framework\Notification\MessageInterface::SEVERITY_CRITICAL;
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Model\System\Message\Media;
/**
* @api
* @since 100.0.2
*/
abstract class AbstractSynchronization implements \Magento\Framework\Notification\MessageInterface
{
/**
* @var \Magento\MediaStorage\Model\File\Storage\Flag
*/
protected $_syncFlag;
/**
* Message identity
*
* @var string
*/
protected $_identity;
/**
* Is displayed flag
*
* @var bool
*/
protected $_isDisplayed = null;
/**
* @param \Magento\MediaStorage\Model\File\Storage\Flag $fileStorage
*/
public function __construct(\Magento\MediaStorage\Model\File\Storage\Flag $fileStorage)
{
$this->_syncFlag = $fileStorage->loadSelf();
}
/**
* Check if message should be displayed
*
* @return bool
*/
abstract protected function _shouldBeDisplayed();
/**
* Retrieve unique message identity
*
* @return string
*/
public function getIdentity()
{
return $this->_identity;
}
/**
* Check whether
*
* @return bool
*/
public function isDisplayed()
{
if (null === $this->_isDisplayed) {
$output = $this->_shouldBeDisplayed();
if ($output) {
$this->_syncFlag->setState(\Magento\MediaStorage\Model\File\Storage\Flag::STATE_NOTIFIED);
$this->_syncFlag->save();
}
$this->_isDisplayed = $output;
}
return $this->_isDisplayed;
}
/**
* Retrieve message severity
*
* @return int
*/
public function getSeverity()
{
return \Magento\Framework\Notification\MessageInterface::SEVERITY_MAJOR;
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Model\System\Message\Media\Synchronization;
/**
* Media synchronization error message class.
*
* @api
* @since 100.0.2
*/
class Error extends \Magento\AdminNotification\Model\System\Message\Media\AbstractSynchronization
{
/**
* Message identity
*
* @var string
*/
protected $_identity = 'MEDIA_SYNCHRONIZATION_ERROR';
/**
* Check whether
*
* @return bool
*/
protected function _shouldBeDisplayed()
{
$data = $this->_syncFlag->getFlagData();
return !empty($data['has_errors']);
}
/**
* Retrieve message text
*
* @return \Magento\Framework\Phrase
*/
public function getText()
{
return __(
'We were unable to synchronize one or more media files. Please refer to the log file for details.'
);
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Model\System\Message\Media\Synchronization;
/**
* Media synchronization success message class.
*
* @api
* @since 100.0.2
*/
class Success extends \Magento\AdminNotification\Model\System\Message\Media\AbstractSynchronization
{
/**
* Message identity
*
* @var string
*/
protected $_identity = 'MEDIA_SYNCHRONIZATION_SUCCESS';
/**
* Check whether
*
* @return bool
*/
protected function _shouldBeDisplayed()
{
$state = $this->_syncFlag->getState();
$data = $this->_syncFlag->getFlagData();
$hasErrors = !empty($data['has_errors']);
return !$hasErrors && \Magento\MediaStorage\Model\File\Storage\Flag::STATE_FINISHED == $state;
}
/**
* Retrieve message text
*
* @return \Magento\Framework\Phrase
*/
public function getText()
{
return __('Synchronization of media storages has been completed.');
}
}
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\AdminNotification\Model\System\Message;
use Magento\Store\Model\Store;
/**
* @api
* @since 100.0.2
*/
class Security implements \Magento\Framework\Notification\MessageInterface
{
/**
* Cache key for saving verification result
*/
const VERIFICATION_RESULT_CACHE_KEY = 'configuration_files_access_level_verification';
/**
* File path for verification
*
* @var string
*/
private $_filePath = 'app/etc/config.php';
/**
* Time out for HTTP verification request
*
* @var int
*/
private $_verificationTimeOut = 2;
/**
* @var \Magento\Framework\App\CacheInterface
*/
protected $_cache;
/**
* @var \Magento\Backend\App\ConfigInterface
*/
protected $_backendConfig;
/**
* @var \Magento\Framework\App\Config\ScopeConfigInterface
*/
protected $_config;
/**
* @var \Magento\Framework\HTTP\Adapter\CurlFactory
*/
protected $_curlFactory;
/**
* @param \Magento\Framework\App\CacheInterface $cache
* @param \Magento\Backend\App\ConfigInterface $backendConfig
* @param \Magento\Framework\App\Config\ScopeConfigInterface $config
* @param \Magento\Framework\HTTP\Adapter\CurlFactory $curlFactory
*/
public function __construct(
\Magento\Framework\App\CacheInterface $cache,
\Magento\Backend\App\ConfigInterface $backendConfig,
\Magento\Framework\App\Config\ScopeConfigInterface $config,
\Magento\Framework\HTTP\Adapter\CurlFactory $curlFactory
) {
$this->_cache = $cache;
$this->_backendConfig = $backendConfig;
$this->_config = $config;
$this->_curlFactory = $curlFactory;
}
/**
* Check verification result and return true if system must to show notification message
*
* @return bool
*/
private function _canShowNotification()
{
if ($this->_cache->load(self::VERIFICATION_RESULT_CACHE_KEY)) {
return false;
}
if ($this->_isFileAccessible()) {
return true;
}
$adminSessionLifetime = (int)$this->_backendConfig->getValue('admin/security/session_lifetime');
$this->_cache->save(true, self::VERIFICATION_RESULT_CACHE_KEY, [], $adminSessionLifetime);
return false;
}
/**
* If file is accessible return true or false
*
* @return bool
*/
private function _isFileAccessible()
{
$unsecureBaseURL = $this->_config->getValue(Store::XML_PATH_UNSECURE_BASE_URL, 'default');
/** @var $http \Magento\Framework\HTTP\Adapter\Curl */
$http = $this->_curlFactory->create();
$http->setConfig(['timeout' => $this->_verificationTimeOut]);
$http->write(\Zend_Http_Client::POST, $unsecureBaseURL . $this->_filePath);
$responseBody = $http->read();
$responseCode = \Zend_Http_Response::extractCode($responseBody);
$http->close();
return $responseCode == 200;
}
/**
* Retrieve unique message identity
*
* @return string
*/
public function getIdentity()
{
return 'security';
}
/**
* Check whether
*
* @return bool
*/
public function isDisplayed()
{
return $this->_canShowNotification();
}
/**
* Retrieve message text
*
* @return \Magento\Framework\Phrase
*/
public function getText()
{
return __(
'Your web server is set up incorrectly and allows unauthorized access to sensitive files. '
. 'Please contact your hosting provider.'
);
}
/**
* Retrieve message severity
*
* @return int
*/
public function getSeverity()
{
return \Magento\Framework\Notification\MessageInterface::SEVERITY_CRITICAL;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment