Jump to content


Photo

Upgrade Safe Configuration - custom multi-module extensions

Customizatoion Module extension

  • Please log in to reply
6 replies to this topic

#1 windsor

windsor

    Advanced Member

  • Moderators
  • 272 posts
  • LocationTampa, Florida USA

Posted 17 June 2013 - 03:42 PM

What is the best practice to install a new extension that consists of multiple modules?

 

Example:

 

      app/protected/extensions/vehicles/components

      app/protected/extensions/vehicles/components/VehicleCustomManagement.php

      app/protected/extensions/vehicles/models

      app/protected/extensions/vehicles/modules  

      app/proected/extensions/vehicles/modules/cars

      app/proected/extensions/vehicles/modules/cars/components

      app/proected/extensions/vehicles/modules/cars/models

      app/proected/extensions/vehicles/modules/cars/modules

      app/protected/extensions/vehicles/utils

      app/protected/extensions/vehicles/utils/VehicleInstallUtil.php

    

 

The existing examples (ZurmoZoo, Invoice) seem to require adding any new Modules to the app/protected/modules directory.

 

Even when the new code is set up as an extension under app/protected/extensions.

 

By way of example (in app/protected/config/perInstanceConfig):

 

...
foreach (array('animals') as $index => $moduleName)
    {
        $instanceConfig['import'][] = "application.modules.$moduleName.*";           // Not Coding Standard
        $instanceConfig['import'][] = "application.modules.$moduleName.adapters.*";  
...

 

   If you have a lot of custom modules, this results in a jumble of new directories insde the app/protected/modules directory.

  This can be problematic, at upgrade time if there are accidental naming conflicts.

 

  I have tried a few different techniques to attempt to save custom modules under  /app/protected/extensions/newExtension/newModule

  with the goal of having all custom code under one single directory structure.

 

  but keep getting this error :

 

exception 'CException' with message 'Alias "newModule.NewModule" is invalid. Make sure it points to an existing PHP file and the file is readable.' 
in ...YiiBase.php(196)

   

 Even after explicitly setting (in config/perInstanceConfig.php):

       

        Yii::setPathOfAlias('newModule',  INSTANCE_ROOT . '/protected/extensions/newExtension/modules/newModule')

 

 

  After a lot of experiment and reading ...

        1. it looks like when Yii::createApplication('WebApplication', $config) is called from index.php(61) ,

        2. the $config file is read into the new application instance.

        3. the new application instance does not contain any references to Yii path alias's that were previously set in the perInstanceConfig.php.

            (and possibly anywhere else?)

 

    This makes sense, because no where in perInstanceConfig.php examples are we merging any new component array into the existing $config

    (which is declared initially in index.php and subsequently updated with config/common.php)

 

 

  

 

    Feels like getting closer, but solution still elusive.  Any ideas from the Yii experts?



#2 raysto

raysto

    Zurmo Team

  • Administrators
  • 1,973 posts

Posted 18 June 2013 - 01:46 PM

Can you join the Developer Sessions today at 10:00AM Chicago Time: http://zurmo.org/for...earning-session We can answer your question.


Ray Stoeckicht
Zurmo Team
Try Zurmo Pro


#3 windsor

windsor

    Advanced Member

  • Moderators
  • 272 posts
  • LocationTampa, Florida USA

Posted 18 June 2013 - 07:02 PM

Per Jason's request in the Dev  session , Here's how to replicate the issue using the ZurmoZoo example code:

 

 

Step 1.  Move the animals module:

                    setenv INSTANCE_ROOT='/var/www/zurmozoo/app'

                     mkdir -p $INSTANCE_ROOT/protected/extensions/zurmozoo/modules/animals

                     mv $INSTANCE_ROOT/protected/modules/animals/*  $INSTANCE_ROOT/protected/extensions/zurmozoo/modules/animals

 

Step 2.  Change $INSTANCE_ROOT/protected/config/perInstanceConfig.php like so:

 

<?php
    /**
     * Custom configuration for the Zurmo Zoo project.
     */

  //For Debugging
   $customModulePath = INSTANCE_ROOT .DIRECTORY_SEPARATOR. 'protected' .DIRECTORY_SEPARATOR. 'extensions' .DIRECTORY_SEPARATOR.'zurmozoo' .DIRECTORY_SEPARATOR. 'modules';
 //For Debugging
   Yii::SetPathOfAlias('animals' . $customModulePath .DIRECTORY_SEPARATOR.  'animals');
//For Debugging
   echo(is_file(Yii::getPathOfAlias('animals') .DIRECTORY_SEPARATOR.  .'AnimalsModule.php') . PHP_EOL);

    $customModules = array (
           'animals',
    );

    $instanceConfig   = array(
        'modules' => $customModules,
           
    );

    $instanceConfig['components']['custom']['class'] =
        'application.extensions.zurmozoo.components.ZurmoZooCustomManagement';
    $instanceConfig['import'][] = "application.extensions.zurmozoo.*";                          // Not Coding Standard
    $instanceConfig['import'][] = "application.extensions.zurmozoo.components.*";               // Not Coding Standard
    $instanceConfig['import'][] = "application.extensions.zurmozoo.utils.*";                    // Not Coding Standard

    foreach ($customModules as $index => $moduleName)
    {
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.*";                           // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.adapters.*";                  // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.adapters.columns.*";          // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.dataproviders.*";             // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.elements.*";                  // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.elements.actions.*";          // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.elements.actions.security.*"; // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.elements.derived.*";          // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.components.*";                // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.controllers.*";               // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.controllers.filters.*";       // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.exceptions.*";                // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.forms.*";                     // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.forms.attributes.*";          // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.interfaces.*";                // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.models.*";                    // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.modules.*";                   // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.rules.*";                     // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.rules.attributes.*";          // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.rules.policies.*";            // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.tests.unit.*";                // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.tests.unit.files.*";          // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.tests.unit.models.*";         // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.tests.unit.walkthrough.*";    // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.utils.*";                     // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.utils.charts.*";              // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.utils.sanitizers.*";          // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.utils.security.*";            // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.utils.analyzers.*";           // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.validators.*";                // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.views.*";                     // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.views.attributetypes.*";      // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.views.charts.*";              // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.views.related.*";             // Not Coding Standard
        $instanceConfig['import'][] = "ext.zurmozoo.modules.$moduleName.widgets.*";                   // Not Coding Standard
    }

?>

  Step 3.   Set up a watch in your debugger for this symbol: 

          Yii::getPathOfAlias('animals')

  Step 4.  Set breakpoint in your debugger on:

  

                    app/index.php ( line 61)

                    app/index.php ( line 62)

 

---------------------------------------------------------------------------------------------------------------------------------

 

TEST 1: Run update schema from the command line

                

                 see this error:

"exception 'CException' with message 'Alias "animals.AnimalsModule" is invalid."...

 

TEST 2: Run the Debugger

             break on app/index.php ( line 61)

             inspect   Yii::getPathOfAlias('animals') => '../protected/extensions/zurmozoo/modules/animals'

             step over

             break on app/index.php ( line 62)

             inspect   Yii::getPathOfAlias('animals') => '../protected/modules/animals'

 

    

-----------------------------------------------------------------------------------------------------------------------------------

 

As noted above, it seems we need a:

       $config = CMAP::mergeArray(...) 

 

so that

       app/index.php (line 61) gets the custom configuration for modules.

 

please advise.



#4 Jason

Jason

    Administrator

  • Administrators
  • 864 posts
  • LocationChicago

Posted 20 June 2013 - 08:19 PM

ext.zurmozoo.modules.$moduleName.*

 

should be

application.extensions.zurmozoo.modules.$moduleName.*

Jason Green
Zurmo Team
Need support? Upgrade now


#5 windsor

windsor

    Advanced Member

  • Moderators
  • 272 posts
  • LocationTampa, Florida USA

Posted 21 June 2013 - 01:55 PM

Yii::getPathOfAlias('application.extensions') is the same as Yii::getPathOfAlias('ext')

 

From: http://www.yiiframew...asics.namespace:

 

 

For convenience, Yii predefines the following root aliases:

  • system: refers to the Yii framework directory;
  • zii: refers to the Zii library directory;
  • application: refers to the application's base directory;
  • webroot: refers to the directory containing the entry script file.
  • ext: refers to the directory containing all third-party extensions.

 

In doing more testing, confirmed failing CMap::arrayMerge($config, $instanceConfig) at line 111 in main.php

 

The problem is in Yii Code for Cmap.php public static function mergeArray($a,$b )on line 290.

 

      For some reason this line of code does not correctly add a new array element, when it should:

 

                if (is_integer($k)) is_set($res[$k]) ? res[] =$v : $res[$k] = $v;

 

      when $instanceConfig['modules'][ ] = 'animals'  is set in PerInstanceConfig.php

   

      $res correctly gets set to $config['modules'] as expected

     

      $k correctly gets set to integer 0 , as expected, because $k represents the array index for $instanceConfig['modules][0]

 

      $v correctly gets set to 'animals'

 

     $res[ ] =$v does not get set in the above code , even though $k will be an integer = 0 AND $res[$k] is set to 'accounts'

 

 

** Note: there is a known bug in certain versions of Xdebug, where local variables do not show up in the debugger. This is not the same issue.

What is happening here is that the array appears to be expanded, but value is null. It seems to happen only on certain recursive calls.

 

*** Note 2:  Xampp 1.8.1, WIndows 7, PHP5.4, Xdebug 2.2.1, Zurmo 2.0



#6 windsor

windsor

    Advanced Member

  • Moderators
  • 272 posts
  • LocationTampa, Florida USA

Posted 21 June 2013 - 04:11 PM

After even more research, i am starting to get that modules should be kept under the application.modules directory, for reasons other than the above.

 

So it appears that best practice would dictate that we should not try to have an extensions.zurmozoo.modules directory, and instead keep any modules under application.modules.  This is unfortunate, in that we would have to spread out custom code in multiple locations. however, it seems Yii expects a single modules directory for each CApplication instance. so this appears to be an architecture issue.

 

If anyone has a better way to accomplish keeping all custom code in one directory tree, please share.



#7 raysto

raysto

    Zurmo Team

  • Administrators
  • 1,973 posts

Posted 21 June 2013 - 07:54 PM

Interesting feedback. We can get into this more on next week's Dev Session.


Ray Stoeckicht
Zurmo Team
Try Zurmo Pro






Also tagged with one or more of these keywords: Customizatoion, Module, extension

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users