Current File : /var/www/prestashop/modules/ps_mbo/src/Traits/Hooks/UseDisplayDashboardTop.php |
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
declare(strict_types=1);
namespace PrestaShop\Module\Mbo\Traits\Hooks;
use Exception;
use Hook;
use PrestaShop\Module\Mbo\Exception\ExpectedServiceNotFoundException;
use PrestaShop\Module\Mbo\Helpers\ErrorHelper;
use PrestaShop\Module\Mbo\Tab\TabInterface;
use PrestaShopDatabaseException;
use PrestaShopException;
use Symfony\Bundle\FrameworkBundle\Routing\Router;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use ToolsCore as Tools;
trait UseDisplayDashboardTop
{
/**
* The controller of configuration page
*
* @var string
*/
protected static $ADMIN_MODULES_CONTROLLER = 'AdminModules';
/**
* Module with push content & link to addons on configuration page
*
* @var string[]
*/
protected static $MODULES_WITH_CONFIGURATION_PUSH = [
'contactform',
'blockreassurance',
];
/**
* The hook is sometimes called multiple times in the same execution because it's called directly in tpl files & in
* some configurations, multiple files can call/extend those.
* Try to limit this behavior by adding this tiny boolean attribute and test it on exec.
*
* @var bool
*/
protected $alreadyProcessedPage = false;
protected $controllersWithRecommendedModules = [
TabInterface::RECOMMENDED_BUTTON_TYPE => TabInterface::TABS_WITH_RECOMMENDED_MODULES_BUTTON,
TabInterface::RECOMMENDED_AFTER_CONTENT_TYPE => TabInterface::TABS_WITH_RECOMMENDED_MODULES_AFTER_CONTENT,
];
/**
* @return void
*
* @throws Exception
*/
public function bootUseDisplayDashboardTop(): void
{
if (method_exists($this, 'addAdminControllerMedia')) {
$this->addAdminControllerMedia('loadMediaForDashboardTop');
}
}
/**
* Hook displayDashboardTop.
* Includes content just below the toolbar.
*
* @return string
*
* @throws Exception
*/
public function hookDisplayDashboardTop(): string
{
// Check if this page has already been processed by the hook to avoid duplicate content
if ($this->alreadyProcessedPage) {
return '';
}
$this->alreadyProcessedPage = true;
$values = Tools::getAllValues();
$moduleCacheDir = sprintf('%s/var/modules/ps_mbo/', rtrim(_PS_ROOT_DIR_, '/'));
$createApiUserLockFile = $moduleCacheDir . 'createApiUser.lock';
if (
isset($values['controller']) &&
($values['controller'] === 'AdminPsMboModule') &&
file_exists($createApiUserLockFile)
) {
return $this->displayFailedApiUser();
}
//Check if we are on configuration page & if the module needs to have a push on this page
$shouldDisplayMessageInConfigPage = isset($values['controller'])
&& ($values['controller'] === self::$ADMIN_MODULES_CONTROLLER)
&& isset($values['configure'])
&& in_array($values['configure'], self::$MODULES_WITH_CONFIGURATION_PUSH);
return $shouldDisplayMessageInConfigPage
? $this->displayPushOnConfigurationPage($values['configure'])
: $this->displayRecommendedModules($values['controller'] ?? '');
}
/**
* @throws PrestaShopDatabaseException
* @throws PrestaShopException
*/
public function useDisplayDashboardTopExtraOperations(): void
{
$hookName = 'actionMboRecommendedModules';
$id_hook = Hook::getIdByName($hookName, false);
if (!$id_hook) {
$new_hook = new Hook();
$new_hook->name = pSQL($hookName);
$new_hook->title = '';
$new_hook->position = true;
$new_hook->add();
}
}
/**
* Insert a block on the top of the configuration with a link to addons
*
* @param string $moduleName
*
* @return string
*/
protected function displayPushOnConfigurationPage(string $moduleName): string
{
switch ($moduleName) {
case 'contactform':
$this->smarty->assign([
'catchPhrase' => $this->trans(
'For even more security on your website forms, consult our Security & Access modules category on the',
[],
'Modules.Mbo.Global'
),
'linkTarget' => $this->trans(
'https://addons.prestashop.com/en/429-website-security-access?utm_source=back-office&utm_medium=native-contactform&utm_campaign=back-office-EN&utm_content=security',
[],
'Modules.Mbo.Links'
),
'linkText' => $this->trans('PrestaShop Addons Marketplace', [], 'Modules.Mbo.Global'),
]);
break;
case 'blockreassurance':
$this->smarty->assign([
'catchPhrase' => $this->trans(
'Discover more modules to improve your shop on',
[],
'Modules.Mbo.Global'
),
'linkTarget' => $this->trans(
'https://addons.prestashop.com/en/517-blocks-tabs-banners?utm_source=back-office&utm_medium=modules&utm_campaign=back-office-EN',
[],
'Modules.Mbo.Links'
),
'linkText' => $this->trans('PrestaShop Addons Marketplace', [], 'Modules.Mbo.Global'),
]);
break;
default:
$this->smarty->assign([
'catchPhrase' => $this->trans(
'Discover more modules to improve your shop on',
[],
'Modules.Mbo.Global'
),
'linkTarget' => $this->trans(
'https://addons.prestashop.com/?utm_source=back-office&utm_medium=modules&utm_campaign=back-office-EN',
[],
'Modules.Mbo.Links'
),
'linkText' => $this->trans('PrestaShop Addons Marketplace', [], 'Modules.Mbo.Global'),
]);
}
return $this->fetch('module:ps_mbo/views/templates/hook/push-configuration.tpl');
}
private function displayFailedApiUser(): string
{
try {
/** @var \Twig\Environment $twig */
$twig = $this->get('twig');
/** @var Router $router*/
$router = $this->get('router');
if (null === $twig || null === $router) {
throw new ExpectedServiceNotFoundException(
'Some services not found in UseDisplayDashboardTop'
);
}
return $twig->render(
'@Modules/ps_mbo/views/templates/hook/twig/failed-api-user.html.twig', [
'module_manager_link' => $router->generate('admin_module_manage'),
]
);
} catch (Exception $e) {
ErrorHelper::reportError($e);
return '';
}
}
/**
* Compute & include data with recommended modules when needed
*
* @throws Exception
*/
protected function displayRecommendedModules(string $controller): string
{
$recommendedModulesDisplayed = true;
// Ask to modules if recommended modules should be displayed in this context
Hook::exec('actionMboRecommendedModules', [
'recommendedModulesDisplayed' => &$recommendedModulesDisplayed,
'controller' => $controller,
]);
$afterContentType = TabInterface::RECOMMENDED_AFTER_CONTENT_TYPE;
$recommendedButtonType = TabInterface::RECOMMENDED_BUTTON_TYPE;
// We want to "hide" recommended modules from this controller
if (!$recommendedModulesDisplayed) {
// If we are trying to display as button, hide the button
if (
in_array(
$controller,
$this->controllersWithRecommendedModules[$recommendedButtonType]
)
) {
return '';
} elseif (
in_array(
$controller,
$this->controllersWithRecommendedModules[$afterContentType]
)
) {
// We are trying to display after content, so move them to button adn remove from after content
foreach ($this->controllersWithRecommendedModules[$afterContentType] as $k => $afterContentController) {
if ($afterContentController === $controller) {
unset($this->controllersWithRecommendedModules[$afterContentType][$k]);
break;
}
}
$this->controllersWithRecommendedModules[TabInterface::RECOMMENDED_BUTTON_TYPE][] = $controller;
}
}
$shouldAttachRecommendedModulesAfterContent = $this->shouldAttachRecommendedModules($afterContentType);
$shouldAttachRecommendedModulesButton = $this->shouldAttachRecommendedModules($recommendedButtonType);
if (!$shouldAttachRecommendedModulesAfterContent && !$shouldAttachRecommendedModulesButton) {
return '';
}
try {
/** @var UrlGeneratorInterface $router */
$router = $this->get('router');
if (null === $router) {
throw new ExpectedServiceNotFoundException(
'Some services not found in UseDisplayDashboardTop'
);
}
$recommendedModulesUrl = $router->generate(
'admin_mbo_recommended_modules',
[
'tabClassName' => Tools::getValue('controller'),
'recommendation_format' => $shouldAttachRecommendedModulesButton ? 'modal' : 'card',
]
);
} catch (Exception $exception) {
// Avoid fatal errors on ServiceNotFoundException
ErrorHelper::reportError($exception);
return '';
}
$this->smarty->assign([
'shouldAttachRecommendedModulesAfterContent' => $shouldAttachRecommendedModulesAfterContent,
'shouldAttachRecommendedModulesButton' => $shouldAttachRecommendedModulesButton,
'shouldUseLegacyTheme' => $this->isAdminLegacyContext(),
'recommendedModulesCloseTranslated' => $this->trans('Close', [], 'Admin.Actions'),
'recommendedModulesUrl' => $recommendedModulesUrl,
'recommendedModulesTitleTranslated' => $this->getRecommendedModulesButtonTitle($controller),
]);
return $this->fetch('module:ps_mbo/views/templates/hook/recommended-modules.tpl');
}
/**
* Indicates if the recommended modules should be attached
*
* @param string $type If we want `afterContent` or `button` related modules
*
* @return bool
*/
protected function shouldAttachRecommendedModules(string $type): bool
{
if ($type === TabInterface::RECOMMENDED_BUTTON_TYPE) {
$modules = $this->controllersWithRecommendedModules[TabInterface::RECOMMENDED_BUTTON_TYPE];
} elseif ($type === TabInterface::RECOMMENDED_AFTER_CONTENT_TYPE) {
$modules = $this->controllersWithRecommendedModules[TabInterface::RECOMMENDED_AFTER_CONTENT_TYPE];
} else {
return false;
}
return in_array(Tools::getValue('controller'), $modules, true);
}
/**
* Add JS and CSS file
*
* @return void
*
* @see \PrestaShop\Module\Mbo\Traits\Hooks\UseActionAdminControllerSetMedia
*/
protected function loadMediaForDashboardTop(): void
{
// has to be loaded in header to prevent flash of content
$this->context->controller->addJs($this->getPathUri() . 'views/js/recommended-modules.js?v=' . $this->version);
if (
$this->shouldAttachRecommendedModules(TabInterface::RECOMMENDED_BUTTON_TYPE)
|| $this->shouldAttachRecommendedModules(TabInterface::RECOMMENDED_AFTER_CONTENT_TYPE)
) {
$this->context->controller->addCSS($this->getPathUri() . 'views/css/recommended-modules.css');
}
}
/**
* Customize title button recommended modules
*/
private function getRecommendedModulesButtonTitle(string $controller): string
{
switch ($controller) {
case 'AdminEmails':
$title = $this->trans('Automate emails', [], 'Modules.Mbo.Recommendedmodulesandservices');
break;
case 'AdminOrders':
$title = $this->trans('Boost sales', [], 'Modules.Mbo.Recommendedmodulesandservices');
break;
case 'AdminCartRules':
case 'AdminSpecificPriceRule':
$title = $this->trans('Create a discount strategy', [], 'Modules.Mbo.Recommendedmodulesandservices');
break;
case 'AdminCmsContent':
$title = $this->trans('Customize pages', [], 'Modules.Mbo.Recommendedmodulesandservices');
break;
case 'AdminContacts':
case 'AdminCustomers':
case 'AdminCustomerThreads':
$title = $this->trans('Improve customer experience', [], 'Modules.Mbo.Recommendedmodulesandservices');
break;
case 'AdminGroups':
$title = $this->trans('Improve customer targeting', [], 'Modules.Mbo.Recommendedmodulesandservices');
break;
case 'AdminStats':
$title = $this->trans('Improve data strategy', [], 'Modules.Mbo.Recommendedmodulesandservices');
break;
case 'AdminMeta':
case 'AdminSearchConf':
$title = $this->trans('Improve SEO', [], 'Modules.Mbo.Recommendedmodulesandservices');
break;
case 'AdminShipping':
$title = $this->trans('Improve shipping', [], 'Modules.Mbo.Recommendedmodulesandservices');
break;
case 'AdminPayment':
$title = $this->trans(
'Improve the checkout experience',
[],
'Modules.Mbo.Recommendedmodulesandservices'
);
break;
case 'AdminImages':
$title = $this->trans('Improve visuals', [], 'Modules.Mbo.Recommendedmodulesandservices');
break;
case 'AdminDeliverySlip':
$title = $this->trans('Make shipping easier', [], 'Modules.Mbo.Recommendedmodulesandservices');
break;
case 'AdminCarriers':
$title = $this->trans('Make your deliveries easier', [], 'Modules.Mbo.Recommendedmodulesandservices');
break;
case 'AdminStatuses':
$title = $this->trans('Optimize order management', [], 'Modules.Mbo.Recommendedmodulesandservices');
break;
case 'AdminProducts':
$title = $this->trans('Optimize product catalog', [], 'Modules.Mbo.Recommendedmodulesandservices');
break;
case 'AdminFeatures':
$title = $this->trans('Optimize product creation', [], 'Modules.Mbo.Recommendedmodulesandservices');
break;
case 'AdminManufacturers':
$title = $this->trans('Promote brands', [], 'Modules.Mbo.Recommendedmodulesandservices');
break;
case 'AdminInvoices':
case 'AdminSlip':
$title = $this->trans('Simplify accounting', [], 'Modules.Mbo.Recommendedmodulesandservices');
break;
case 'AdminAdminPreferences':
$title = $this->trans('Simplify store management', [], 'Modules.Mbo.Recommendedmodulesandservices');
break;
default:
$title = $this->trans('Recommended modules', [], 'Modules.Mbo.Recommendedmodulesandservices');
break;
}
return $title;
}
}