Maneira correta de atualizar o pai de um tema no Magento 2

14

No Magento 2, você pode especificar um tema pai no theme.xmlarquivo de um 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>

A primeira vez que o Magento vê um tema, ele usa esse valor para definir um parent_idna themetabela. Essa é a fonte da verdade para onde está o pai de um tema.

No entanto, se você tentar alterar esse valor após a adição de um tema ao sistema , o Magento não atualizará a parent_idcoluna e os Magento\Theme\Model\Themeobjetos instanciados ainda terão o tema pai original. (Mesmo se você limpar o cache.)

Eu posso corrigir isso alterando manualmente o parent_idvalor - isso parece um hack. Onde parent_idnormalmente está definido no código principal do Magento, e quais ações do usuário acionam isso? ou seja, existe uma maneira de dizer ao Magento "por favor recarregue esse tema"

Alan Storm
fonte
2
Sim, eu também notei isso e a única maneira de encontrar isso para modificar isso depois que o tema foi registrado é modificar o banco de dados diretamente. Possivelmente um bug?
Gareth Daine

Respostas:

2

ATUALIZADO EM 20160310

Conclusão

É sempre definido via updateTheme()ou a partir da coleção (via DB) se o seuappState->getMode() == AppState::MODE_PRODUCTION

Responda

Para responder à pergunta Qual é o caminho para o Magento recarregar o arquivo theme.xml, a resposta é:

Definir o estado de aplicação para developerusar SetEnv MAGE_MODE developerem .htaccess(ou nginx equivalente) e, em seguida, em log para a área de administração (ou actualizar qualquer via de administração) de gatilho Magento\Theme\Model\Theme\Plugin\Registration::beforeDispatch().

A tabela de temas no banco de dados é atualizada devido a

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

Veja a análise abaixo para obter detalhes.

Análise

Uau, o código Magento 2 parece realmente complexo para mim. Você estudou esta função beforeDispatch()que chama updateThemeData()mas apenasif ($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);
        }
    }

Provavelmente você já passou por esse código.

beforeDispatch()é chamado apenas através de rotas administrativas e não nas rotas de front-end. Aqui está um 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))

Na verdade, vejo beforeDispatch()chamadas updateThemeData()que contêm esse nugget:

//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());
            }
//...

O que parece realmente (finalmente) se referir a um caminho XML de configuração, $themeData->getParentTheme()->getFullPath()mas essa função ainda usa $themeData->getParentTheme(). Ah, acho que a lógica é ' Se estou atualizando um tema registrado que tenha um parentId na coleção (via DB), procure um caminho pai na configuração e atualize a coleção '.Então talvez seja isso.

Caso contrário, estou completamente desapontado com a forma como Magento\Theme\Model\Theme::getParentTheme()implementa o getParentId()que é declarado na interface do tema. Certamente não é mágico. Como você diz, ele precisa vir do banco de dados por meio da coleção ou do caminho XML de configuração do tema (se ele foi alterado ou ainda não está definido), mas não consigo encontrar uma definição de getParentId(). Talvez seja sempre definido via updateTheme()OR da coleção (via DB) tão ruim que seja o seu appState->getMode() == AppState::MODE_PRODUCTION.

Achei útil recolher informações de dentro updateThemeData()adicionando alguma saída de log:

//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());
            }
//...

O qual fará o logon /var/log/debug.log. Com o estado do aplicativo definido como developer, posso ver que o ID pai é sempre definido em todas as atualizações da página de administração, independentemente de terem sido alteradas theme.xmlou não. Com o estado productiondo aplicativo, a função nunca é executada, então concluo:

É sempre definido via updateTheme()OR da coleção (via DB) tão ruim se o seuappState->getMode() == AppState::MODE_PRODUCTION

Eu acho que você provavelmente está no developerestado de aplicativo. defaulto estado do aplicativo será acionado updateThemeData()também, é claro. Na depuração adicional, registrei o caminho completo do tema para o tema pai do Luma, que era frontend/Magento/blank. A capital Mme surpreendeu, então talvez algo para observar.

Malachy
fonte
0

O exposto acima não pareceu funcionar para mim, então fui com o hack.

Espero que ajude alguém.

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)

caso contrário, mude.

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

then quit mysql;

 bin/magento setup:static-content:deploy 

ou

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

grunt exec:[theme]

grunt less:[theme]
wwsiv2
fonte