4

I'm trying to find a way to get a list of all magento 1.9 blocks with their names programmatically.

I.e:

$blocks= [
    'core/text_tag_css_admin' => 'Mage_Core_Block_Text_Tag_Css_Admin',
    'core/text_list_item' => 'Mage_Core_Block_Text_List_Item',
    'core/text_list_link' => 'Mage_Core_Block_Text_List_Link',
]

I searched but I haven't found anything on how to approach this problem.

Here's the code I have so far in case it will help someone else.

        public function toOptionArray()
        {
            /**
             * @var $blocks Mage_Core_Model_Config_Element
             */
            $blocks = Mage::getConfig()->getNode('global/blocks')->asArray();

            $classes = [];
            $options = [];
            $realClasses = [];


            foreach ($blocks as $key => $value) {
                $classes[$key] = $value['class'];
            }


            foreach ($classes as $key => $class) {
                $classKeys = explode('_', $class);
                $moduleDir = Mage::getModuleDir('', $classKeys[0] . '_' . $classKeys[1]);
                $moduleDir = $moduleDir . DS . $classKeys[2];
                if (empty($moduleDir))
                    continue;
                $files = [];
                $files = $this->listFIles($moduleDir);
                $relativeClasses = $this->getRelativeClasses($files, $moduleDir);
                foreach ($relativeClasses as $relativeClass) {
                    $realClass = $class . $relativeClass;
                    $realClasses[] = $realClass;
                }
            }

            $result = [];
            sort($realClasses);
        //TODO: Eliminate abstract classes
        foreach ($realClasses as $realClass) {
            try {
                //throws fatal error so can't be caught
                $r = new ReflectionClass($realClass);
            } catch (Exception $e) {

            }
            if (isset($r) && !$r->isAbstract())
                $result[] = array('value' => $realClass, 'label' => $realClass);
        }
        return $result;

        }


        protected function getRelativeClasses($files, $moduleDir)
        {
            if (empty($files) || !file_exists($moduleDir))
                return [];
            $classes = [];
            foreach ($files as $file) {
                $filePath = $file->getPathname();
                $relativeClassPath = str_replace($moduleDir, '', $filePath);
                $relativeClassPath = str_replace('.php', '', $relativeClassPath);
                $relativeClassPath = str_replace(DS, '_', $relativeClassPath);
                $classes[] = $relativeClassPath;
            }

            return $classes;
        }


        protected function listFIles($dir)
        {
            if (!file_exists($dir))
                return [];
            $files = [];
            $di = new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS);
            $it = new RecursiveIteratorIterator($di);

            foreach ($it as $file) {
                if (pathinfo($file, PATHINFO_EXTENSION) == "php") {
                    $files[] = $file;
                }
            }
            return $files;
        }

2 Answers 2

2

You can find them in two steps:

  1. find all module aliases:

    $aliases = Mage::getConfig()->getNode('global/blocks');
    

    using n98-magerun dev:console, I get output like this:

    screenshot

  2. for each module alias, find all classes. For the rewrites it is easy, because the full mapping is available (like core/profiler => 'Aoe_Profiler_Block_Profiler'. For all others, you will have to search the file system. For each entry:

    1. convert the class value to a path (Mage_Page_Block => Mage/Page/Block)
    2. search for all files in app/code/*/$path/**. You can use glob() for that.
    3. For the class alias, combine the module alias (e.g. page) and the last part of the file path, replacing / with _ and lowercasing (e.g. Html/Head.php, converted to html_head)
    4. For the class name, either parse the file, or combine the class value (Mage_Page_Block) and the last part of the file path, replacing / with _ (Html_Head)
1
  • Hi Fabian, as I was typing the comment to the other answer I noticed your answer. This is what I did so far and I'll post code above. The only problem with this I've come across so far is the fact that I get all classes including abstract ones. I tried to use reflection to eliminate abstract classes and also get the alias but it throws fatal errors because some non-abstract classes use abstract methods but they don't have them declared so it's a very big mess. I'll try your idea to create the alias instead. Thanks for trying to help
    – gabtzi
    Commented Jun 22, 2017 at 8:18
1

You can try this code snippet.

<?php
define('MAGENTO_ROOT', getcwd());
$mageFilename = MAGENTO_ROOT . '/app/Mage.php';
require_once $mageFilename;
ini_set('display_errors', 1);
Mage::app();
echo "<pre>";

/**
 * Collect blocks from given layout element.
 *
 * @param Mage_Core_Model_Layout_Element $layoutElements
 * @param array $blocks
 * @return array $blocks
 */
function collectBlocks(Mage_Core_Model_Layout_Element $layoutElements,
                       array $blocks)
{
    foreach ($layoutElements as $layoutElemKey => $layoutElement) {
        if ($layoutElemKey == 'block') {
            $blockType          = (string) $layoutElement['type'];
            $blockClass         = (string) Mage::getConfig()->getBlockClassName($blockType);
            $blocks[$blockType] = $blockClass;
            if ($layoutElement->block) {
                $blocks = collectBlocks($layoutElement->block, $blocks);
            }
        }
    }

    return $blocks;
}

//specifiy pacakge/theme
$area    = 'frontend';
$package = 'base';
$theme   = 'default';

$blocks = array();

//generate layout update xml
$layout          = Mage::getModel('core/layout');
$layoutUpdateXml = $layout->getUpdate()
    ->getFileLayoutUpdatesXml($area, $package, $theme);


//go through update xml file and collects blocks
foreach ($layoutUpdateXml as $layoutElements) {
    $blocks = collectBlocks($layoutElements, $blocks);
}
print_r($blocks);

Place this code sample in the root folder and load the file in a browser. You will see all blocks which are used by a package/theme.

If you want this inside your application, then use the same logic according to your need.

Below I am providing you the output which this script provides :

Array ( [core/template] => Mage_Core_Block_Template [page/html] => Mage_Page_Block_Html [page/html_head] => Mage_Page_Block_Html_Head [page/js_cookie] => Mage_Page_Block_Js_Cookie [core/text_list] => Mage_Core_Block_Text_List [page/html_notices] => Mage_Page_Block_Html_Notices [page/html_header] => Mage_Page_Block_Html_Header [page/template_links] => Mage_Page_Block_Template_Links [page/switch] => Mage_Page_Block_Switch [page/html_topmenu] => Mage_Page_Block_Html_Topmenu [page/html_wrapper] => Mage_Page_Block_Html_Wrapper [page/html_welcome] => Mage_Page_Block_Html_Welcome [page/html_breadcrumbs] => Mage_Page_Block_Html_Breadcrumbs [core/messages] => Mage_Core_Block_Messages [page/html_footer] => Mage_Page_Block_Html_Footer [page/html_cookieNotice] => Mage_Page_Block_Html_CookieNotice [core/profiler] => Mage_Core_Block_Profiler [catalog/product_price_template] => Mage_Catalog_Block_Product_Price_Template [sales/order_email_items] => Mage_Sales_Block_Order_Email_Items [sales/order_totals] => Mage_Sales_Block_Order_Totals [tax/sales_order_tax] => Mage_Tax_Block_Sales_Order_Tax [sales/order_email_invoice_items] => Mage_Sales_Block_Order_Email_Invoice_Items [sales/order_invoice_totals] => Mage_Sales_Block_Order_Invoice_Totals [sales/order_email_shipment_items] => Mage_Sales_Block_Order_Email_Shipment_Items [sales/order_email_creditmemo_items] => Mage_Sales_Block_Order_Email_Creditmemo_Items [sales/order_creditmemo_totals] => Mage_Sales_Block_Order_Creditmemo_Totals [checkout/onepage_progress] => Mage_Checkout_Block_Onepage_Progress [checkout/onepage_payment_info] => Mage_Checkout_Block_Onepage_Payment_Info [checkout/onepage_payment_methods] => Mage_Checkout_Block_Onepage_Payment_Methods [checkout/onepage_shipping_method_available] => Mage_Checkout_Block_Onepage_Shipping_Method_Available [checkout/onepage_shipping_method_additional] => Mage_Checkout_Block_Onepage_Shipping_Method_Additional [checkout/onepage_review_info] => Mage_Checkout_Block_Onepage_Review_Info [checkout/cart_totals] => Fingent_Commitbuy_Block_Cart_Totals [checkout/agreements] => Mage_Checkout_Block_Agreements [paypal/express_review_details] => Mage_Paypal_Block_Express_Review_Details [paypal/payflow_link_iframe] => Mage_Paypal_Block_Payflow_Link_Iframe [paypal/payflow_advanced_iframe] => Mage_Paypal_Block_Payflow_Advanced_Iframe [paypal/hosted_pro_iframe] => Mage_Paypal_Block_Hosted_Pro_Iframe [rss/list] => Mage_Rss_Block_List [rss/wishlist] => Mage_Rss_Block_Wishlist [rss/catalog_new] => Mage_Rss_Block_Catalog_New [rss/catalog_special] => Mage_Rss_Block_Catalog_Special [rss/catalog_salesrule] => Mage_Rss_Block_Catalog_Salesrule [rss/catalog_tag] => Mage_Rss_Block_Catalog_Tag [rss/catalog_notifyStock] => Mage_Rss_Block_Catalog_NotifyStock [rss/catalog_review] => Mage_Rss_Block_Catalog_Review [rss/catalog_category] => Mage_Rss_Block_Catalog_Category [rss/order_new] => Mage_Rss_Block_Order_New [rss/order_status] => Mage_Rss_Block_Order_Status [centinel/authentication_start] => Mage_Centinel_Block_Authentication_Start [centinel/authentication_complete] => Mage_Centinel_Block_Authentication_Complete )

1
  • Hi Rajeev, I tried your code above and while it seems to work it doesn't present all block types used in the frontend. I've tried passing different values to package and theme variables and there are still lots of blocks missing. I went ahead and tried a different approach by scanning the php files.
    – gabtzi
    Commented Jun 22, 2017 at 8:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.