Forma correcta de actualizar el padre de un tema en Magento 2

14

En Magento 2, puede especificar un tema principal en el theme.xmlarchivo de un tema .

<theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Config/etc/theme.xsd">
    <title>Theme Title</title>
    <parent>Package/base-theme</parent>
    <media>
        <preview_image>media/preview.jpg</preview_image>
    </media>
</theme>

La primera vez que Magento ve un tema, usa este valor para establecer un parent_iden la themetabla. Esta es la fuente de la verdad sobre dónde está el padre de un tema.

Sin embargo, si intenta cambiar este valor después de que se haya agregado un tema al sistema , Magento no puede actualizar la parent_idcolumna y los Magento\Theme\Model\Themeobjetos instanciados seguirán teniendo el tema principal original. (Incluso si borra el caché).

Puedo arreglar esto cambiando manualmente el parent_idvalor, eso parece un truco. ¿Dónde se parent_idestablece normalmente en el código central de Magento y qué acciones del usuario desencadenan esto? es decir, ¿hay alguna manera de decirle a Magento "vuelva a cargar este tema"

Alan Storm
fuente
2
Sí, también he notado esto y la única forma en que he encontrado modificar esto después de que el tema ha sido registrado es modificar la base de datos directamente. Posiblemente un error?
Gareth Daine

Respuestas:

2

ACTUALIZADO EN 20160310

Conclusión

Siempre se establece a través de updateTheme()o desde la colección (a través de DB) si suappState->getMode() == AppState::MODE_PRODUCTION

Responder

Para responder la pregunta ¿Cuál es la forma de hacer que Magento vuelva a cargar el archivo theme.xml? La respuesta es:

Establezca el estado de la aplicación en developer usar SetEnv MAGE_MODE developerin .htaccess(o nginx equivalente) y luego inicie sesión en el área de administración (o actualice cualquier ruta de administración) para activar Magento\Theme\Model\Theme\Plugin\Registration::beforeDispatch().

La tabla de temas en la base de datos se actualiza debido a

\\Magento\Theme\Model\Theme\Plugin\Registration::updateThemeData()
\\...
$themeData->setParentId($parentTheme->getId());`.
\\...

Vea el análisis a continuación para más detalles.

Análisis

Wow, el código de Magento 2 me parece realmente complejo. ¿Has estudiado esta función beforeDispatch()que llama updateThemeData()pero soloif ($this->appState->getMode() != AppState::MODE_PRODUCTION)

//namespace: namespace Magento\Theme\Model\Theme\Plugin;
//class: Registration
//file: app/code/Magento/Theme/Model/Theme/Plugin/Registration.php 

     /**
     * Add new theme from filesystem and update existing
     *
     * @param AbstractAction $subject
     * @param RequestInterface $request
     *
     * @return void
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */
    public function beforeDispatch(
        AbstractAction $subject,
        RequestInterface $request
    ) {
        try {
            if ($this->appState->getMode() != AppState::MODE_PRODUCTION) {
                $this->themeRegistration->register();
                $this->updateThemeData();
            }
        } catch (LocalizedException $e) {
            $this->logger->critical($e);
        }
    }

Probablemente hayas leído este código.

beforeDispatch()se llama solo a través de rutas de administrador y no en rutas de front-end. Aquí hay un rastro:

#0 [internal function]: Magento\Theme\Model\Theme\Plugin\Registration->beforeDispatch(Object(Magento\Backend\Controller\Adminhtml\Dashboard\Index\Interceptor), Object(Magento\Framework\App\Request\Http))
#1 \magento2\lib\internal\Magento\Framework\Interception\Interceptor.php(122): call_user_func_array(Array, Array)
#2 \magento2\var\generation\Magento\Backend\Controller\Adminhtml\Dashboard\Index\Interceptor.php(39): Magento\Backend\Controller\Adminhtml\Dashboard\Index\Interceptor->___callPlugins('dispatch', Array, Array)
#3 \magento2\lib\internal\Magento\Framework\App\FrontController.php(55): Magento\Backend\Controller\Adminhtml\Dashboard\Index\Interceptor->dispatch(Object(Magento\Framework\App\Request\Http))
#4 [internal function]: Magento\Framework\App\FrontController->dispatch(Object(Magento\Framework\App\Request\Http))
#5 \magento2\lib\internal\Magento\Framework\Interception\Interceptor.php(74): call_user_func_array(Array, Array)
#6 \magento2\lib\internal\Magento\Framework\Interception\Chain\Chain.php(70): Magento\Framework\App\FrontController\Interceptor->___callParent('dispatch', Array)
#7 \magento2\lib\internal\Magento\Framework\Interception\Interceptor.php(136): Magento\Framework\Interception\Chain\Chain->invokeNext('Magento\\Framewo...', 'dispatch', Object(Magento\Framework\App\FrontController\Interceptor), Array, 'install')
#8 \magento2\lib\internal\Magento\Framework\Module\Plugin\DbStatusValidator.php(69): Magento\Framework\App\FrontController\Interceptor->Magento\Framework\Interception\{closure}(Object(Magento\Framework\App\Request\Http))
#9 [internal function]: Magento\Framework\Module\Plugin\DbStatusValidator->aroundDispatch(Object(Magento\Framework\App\FrontController\Interceptor), Object(Closure), Object(Magento\Framework\App\Request\Http))
#10 \magento2\lib\internal\Magento\Framework\Interception\Interceptor.php(141): call_user_func_array(Array, Array)
#11 \magento2\var\generation\Magento\Framework\App\FrontController\Interceptor.php(26): Magento\Framework\App\FrontController\Interceptor->___callPlugins('dispatch', Array, Array)
#12 \magento2\lib\internal\Magento\Framework\App\Http.php(115): Magento\Framework\App\FrontController\Interceptor->dispatch(Object(Magento\Framework\App\Request\Http))
#13 \magento2\lib\internal\Magento\Framework\App\Bootstrap.php(258): Magento\Framework\App\Http->launch()
#14 \magento2\index.php(39): Magento\Framework\App\Bootstrap->run(Object(Magento\Framework\App\Http))

En realidad, veo beforeDispatch()llamadas updateThemeData()que contienen esta pepita:

//namespace: namespace Magento\Theme\Model\Theme\Plugin;
//class: Registration
//file: app/code/Magento/Theme/Model/Theme/Plugin/Registration.php 
//function: updateThemeData()

//...
            if ($themeData->getParentTheme()) {
                $parentTheme = $this->themeLoader->getThemeByFullPath(
                    $themeData->getParentTheme()->getFullPath()
                );
                $themeData->setParentId($parentTheme->getId());
            }
//...

Lo que parece referirse realmente (finalmente) a una ruta XML de configuración, $themeData->getParentTheme()->getFullPath()pero esa función aún se usa $themeData->getParentTheme(). Oh, creo que la lógica es ' Si estoy actualizando un tema registrado que tiene un parentId en la colección (a través de la base de datos), busque una ruta principal en la configuración y actualice la colección '.Entonces tal vez esto es todo.

De lo contrario, estoy completamente perdido en cuanto a cómo se Magento\Theme\Model\Theme::getParentTheme()implementa lo getParentId()que se declara en la interfaz del tema. Seguramente no es magia. Como usted dice, debe provenir de la base de datos a través de la colección o de la ruta XML de configuración del tema (si cambió o aún no está definida), pero no puedo encontrar una definición de getParentId(). Tal vez siempre se establece a través de updateTheme()OR de la colección (a través de DB), por lo que es muy malo si su appState->getMode() == AppState::MODE_PRODUCTION.

Me resultó útil obtener información desde adentro updateThemeData()agregando algunos resultados de registro:

//namespace: namespace Magento\Theme\Model\Theme\Plugin;
//class: Registration
//file: app/code/Magento/Theme/Model/Theme/Plugin/Registration.php 
//function: updateThemeData()

//...
            if ($themeData->getParentTheme()) {
                $parentTheme = $this->themeLoader->getThemeByFullPath(
                    $themeData->getParentTheme()->getFullPath()
                );
            $this->logger->addDebug("Theme parent full path ".$themeData->getParentTheme()->getFullPath());
            $this->logger->addDebug("Theme parent new ID ".$parentTheme->getId());                    $themeData->setParentId($parentTheme->getId());
            }
//...

Que se registrará en /var/log/debug.log. Con el estado de la aplicación configurado en developerPuedo ver que la ID principal siempre se establece en cada actualización de la página de administración, ya sea que se haya cambiado theme.xmlo no. Con el estado de productionla aplicación, la función nunca se ejecuta, así que concluyo:

Siempre se establece a través de updateTheme()OR desde la colección (a través de DB), por lo que es muy malo si suappState->getMode() == AppState::MODE_PRODUCTION

Creo que probablemente todos estén en developerestado de aplicación. defaultel estado de la aplicación también se activará, updateThemeData()por supuesto. En la depuración adicional, registré la ruta completa del tema para el tema principal de Luma que era frontend/Magento/blank. La capital Mme sorprendió, así que tal vez algo a tener en cuenta.

Malachy
fuente
0

Lo anterior no parecía funcionar para mí, así que fui con el truco.

Espero que ayude a alguien.

using the command line

 mysql

 SHOW databases;

 use magento; (or whatever your DB's name is)

 SHOW tables

 SELECT * FROM theme; 

(Check the **parent_id** of theme in question, it should be the same number as **theme_id** of theme you want as the parent)

si no es así, cámbielo.

 UPDATE theme SET parent_id  = '[value]' WHERE theme_title = '[Theme name]';

then quit mysql;

 bin/magento setup:static-content:deploy 

o

grunt clean:[theme] (For example:  grunt clean:blank)

grunt exec:[theme]

grunt less:[theme]
wwsiv2
fuente