Maneira moderna de reescrever arquivos lib

21

O problema é bem conhecido: as libclasses são carregadas exclusivamente através do carregador automático e não podemos alterá-las além de:

  • Copiando-os inteiramente para um codePool verificado antes da lib.
  • Instalando o carregador automático PSR-0 , especificando um mapa de classe de carregamento automático e, em seguida, copiando o arquivo inteiramente na estrutura de pastas. [minha solução atual]

Estou em uma situação difícil, porque quero potencialmente tocar em muitos desses arquivos - mas, por uma questão de sanidade e estabilidade / capacidade de atualização da loja, não quero copiar classes inteiras da biblioteca.

Agora, obviamente, existem soluções em potencial para esse problema, mas todos eles vêm com seu próprio conjunto de problemas:

  • Siga a rota da AOP e use uma biblioteca baseada em PHP como o Go! AOP : Por último, verifiquei que isso exigirá que as classes Magento sejam carregadas pelo carregador automático do compositor, e não apenas uma disponível. A Flyingmana fez algum trabalho nesta área, mas definitivamente não está pronta para uso em produção e minhas necessidades são mais imediatas. Também quero enviar como uma extensão, o que exigiria mais configurações do compositor.
  • Siga a rota AOP e use uma extensão PHP nativa : provavelmente a mais favorável nesse momento, mas seria necessário instalar uma extensão separada, sem mencionar que não funcionaria com o HHVM.
  • Use o classkit e / ou runkit do PHP: é outra extensão nativa do PHP e, portanto, apresenta o mesmo problema acima.
  • Faça o patch de sites de chamada para usar minha própria \Danslo\Varien_Xversão com namespaced ( ) e depois estenda a partir do original ( \Varien_X): existem muitos callites para corrigir e isso exigiria uma quantidade tola de reescritas. Não é uma opção.
  • Role o meu: deve ser possível:

    1. Escreva meu próprio carregador automático.
    2. Copie a classe original para uma pasta separada ( {root_dir}/var/tmp), envolva-a namespace \Magento { < original contents > }.
    3. Inclua esse arquivo.
    4. Incluir minha classe modificada OriginalClass extends Magento\OriginalClass {}

A desvantagem disso é óbvia: geração dinâmica de código, regex, um pouco de sobrecarga para carregar classes reescritas. Mas tenho quase certeza de que, neste momento, seria melhor copiar ~ 5000 linhas de código quando eu apenas quiser tocar / adicionar ~ 100 linhas.

Sei que estou pedindo muito, mas há algo moderno e relativamente limpo por aí que ajude a resolver esse problema?

Daniel Sloof
fonte
1
Você já encontrou a solução de observador da Alans? stackoverflow.com/a/4636662/158325
B00MER

Respostas:

9

Decidiu implementar o Go! Estrutura de AOP no Magento.

Veja Danslo_Aop no github.

Daniel Sloof
fonte
2

Siga a rota da AOP e use uma biblioteca baseada em PHP como o Go! AOP: Por último, verifiquei que isso exigirá que as classes Magento sejam carregadas pelo carregador automático do compositor, e não apenas uma disponível. A Flyingmana fez algum trabalho nesta área, mas definitivamente não está pronta para uso em produção e minhas necessidades são mais imediatas. Também quero enviar como uma extensão, o que exigiria mais configurações do compositor.

Quero adicionar o Go! O framework AOP pode funcionar sem o compositor, eu posso ajudar na configuração (basta criar um problema no github para isso). O Composer é necessário apenas para integração transparente com aplicativos modernos.

Basta substituir um include $filenameou require $filenameno seu bootstrap por include FilterInjectorTransformer::rewrite($filename)e configurar um carregador automático para Go! AOP em si.

lisachenko
fonte
1
Uau, legal. Definitivamente vou tentar isso.
Daniel Sloof
0

Vá com a abordagem do carregador automático. Renomeie / all / classes na lib com um prefixo:

find lib -name '*.php' -exec sed -e 's,^class ,class Oldlib_,' {} +

Execute o seguinte "override fixer" sempre que adicionar um arquivo ao mylib:

find lib -name '*.php' -print | while read FILE
do
    classname=$(echo ${FILE}|sed -e 's,^lib/,,' -e 's,\.php$,,' -e 's,/,_,g')
    if [ ! -f mylib/${FILE#lib/} ]; then
        # ensure is_a works by providing a stub with correct classname
        echo "class ${classname} extends Oldlib_${classname} {}" > mylib/${classname}.php
    elif [ -f mylib/${classname}.php ]; then
        # we have a new override, but the old file still exists
        rm mylib/${classname}.php
    fi
done

Ensine o carregador automático a retornar mylib/${classname}.phpse ele existe e mylib/full/path/to/class.phpse não existe e existe mylib/full/path/to/class.php.

Coloque suas substituições mylib/full/path/to/class.phpe estenda a versão Oldlib_.

As atualizações simplesmente reverterão o prefixo na lib / atualizá-lo, reaplicar o prefixo, executar novamente o fixador de substituição. O que resta são coisas que foram movidas lib/e foram substituídas anteriormente, mas isso não está relacionado ao problema. Seu problema pode ser o número de arquivos do diretório mylib /, mas acredito que você possa resolver isso :).

Melvyn
fonte
Essa abordagem apresenta muitos riscos e itens a serem mantidos, especialmente em relação às atualizações. Ele também quebra a regra "não toque no núcleo". Além disso, não é uma opção viável para desenvolvedores de extensões.
beeplogic
Com todo o respeito ~, embora sua solução funcione ... ela não pode ser considerada uma a modernmaneira de reescrever arquivos lib. Programação imperativa é velha escola;)
Eddie B
0

Além disso, você pode definir o fluxo personalizado e adicioná-lo no caminho do carregamento automático. Funciona com qualquer carregador automático e requer adoção mínima. Veja exemplo

KAndy
fonte