cancel
Showing results for 
Search instead for 
Did you mean: 

setting target Module Name when generating a block

0 Kudos

setting target Module Name when generating a block

Feature request from dbsdsun, posted on GitHub May 18, 2015

Problem:

  1. One block may template files. The Module Name is used to determine the template file location.
  2. MoudleB_BlockB can extend ModuleA_BlockA by specification in di.xml as following:

In this case, the MoudleB_BlockB should use ModuleA as its module name, rather than MoudleB.

Solution:

Set target module name when generating a block as follwing. And this is last chance to set target module name. in file lib/internal/Magento/Framework/View/Layout/Generator/Block.php, after line 157, add one line line155. $block = $this->createBlock($className, $elementName, [ line156. 'data' => $this->evaluateArguments($data['arguments']) line157. ]); new line. $block->setModuleName($block->extractModuleName($className)); line158. if (!empty($attributes['template'])) { line159. $block->setTemplate($attributes['template']); line160. }

5 Comments
apiuser
New Member

Comment from paliarush, posted on GitHub May 19, 2015

Hello @dbsdsun,

Looks like mentioned di.xml content is missing in the problem description. Please provide more details.

Thank you.

apiuser
New Member

Comment from dbsdsun, posted on GitHub May 20, 2015

In magento 2, a block can be extended as following:

  1. add a preference in di.xml <?xml version="1.0"?>

  2. extend \Magento\Theme\Block\Html\Title class namespace Sample\HelloWorld\Block;

use Magento\Framework\View\Element\Template;

class HelloTitle extends \Magento\Theme\Block\Html\Title { public function getPageTitle() { return 'haha9999'; } }

  1. HelloTitle->__toHtml() will locate template file with ModuleName public function getTemplateFile($template = null) { $params = ['module' => $this->getModuleName()];

To use the correct template file html/title.phtml, the ModuleName should be Magento_Theme. In the current Magento2, the ModuleName will be Sample_HelloWorld, which is wrong.

  1. When generating a block, the extended class is found with Magento\Framework\ObjectManager\Config->getPreference($type). But the ModuleName is not set to correct value (Magento_Theme, in my example). protected function generateBlock( Layout\ScheduledStructure $scheduledStructure, Layout\Data\Structure $structure, $elementName ) { ......................... // create block $className = $attributes['class']; $block = $this->createBlock($className, $elementName, [ 'data' => $this->evaluateArguments($data['arguments']) ]); // NEEDS TO SET MODULENAME if (!empty($attributes['template'])) { $block->setTemplate($attributes['template']); }
apiuser
New Member

Comment from victorgugo, posted on GitHub May 20, 2015

Hello, @dbsdsun

Thank you for interesting in Magento 2. Sorry, but from summary and description I couldn't catch what is the issue

  1. Could you please clarify what functionality is working wrong?
  2. Please, provide what problem you are solving, your steps, actual and expected behavior.
  3. It would be also good if you format your proposed code snippet for solution of this problem, beacuse now it's little bit not readable

Thanks in advance

apiuser
New Member

Comment from dbsdsun, posted on GitHub May 22, 2015

Let me make it simple. this is the function in file lib\internal\Magento\Framework\View\Layout\Generator\Block.php, I put some comments in it

    /**
     * Create block and set related data
     *
     * @param \Magento\Framework\View\Layout\ScheduledStructure $scheduledStructure
     * @param \Magento\Framework\View\Layout\Data\Structure $structure
     * @param string $elementName
     * @return \Magento\Framework\View\Element\AbstractBlock
     */
    protected function generateBlock(
        Layout\ScheduledStructure $scheduledStructure,
        Layout\Data\Structure $structure,
        $elementName
    ) {
        list(, $data) = $scheduledStructure->getElement($elementName);
        $attributes = $data['attributes'];

        if (!empty($attributes['group'])) {
            $structure->addToParentGroup($elementName, $attributes['group']);
        }

        // create block
        // setp 1. create a block object
        $className = $attributes['class'];
        $block = $this->createBlock($className, $elementName, [
            'data' => $this->evaluateArguments($data['arguments'])
        ]);

        // setp 2. set template (eg. "html/title.phtml"), if this block has template attribute
        if (!empty($attributes['template'])) {
            $block->setTemplate($attributes['template']);
        }

        // step 3. deal with attribute "ttl"
        if (!empty($attributes['ttl'])) {
            $ttl = (int)$attributes['ttl'];
            $block->setTtl($ttl);
        }
        return $block;
    }

When Magento2 locates a template file of a block, the attribute (eg. "html/title.phtml") is not enough. Magento2 also needs ModuleName of the block. Therefore, ModuleName also needs to be set in step 2. One line of code is needed.

$block->setModuleName($block->extractModuleName($className));

The slice of code should look like the following.

        // setp 2. set template (eg. "html/title.phtml"), if this block has template attribute
        if (!empty($attributes['template'])) {
            $block->setTemplate($attributes['template']);
            $block->setModuleName($block->extractModuleName($className));
        }
apiuser
New Member

Comment from dbsdsun, posted on GitHub Jun 01, 2015

Your current unit test doesn't cover "override a block with preference in di.xml". In the furture, if a block is overrided by another block, this issue will be seen.