Adding Custom Bricks

Discussion in 'aMember Pro v.4' started by pwwatson, Mar 28, 2012.

  1. pwwatson

    pwwatson New Member

    Joined:
    Jul 10, 2010
    Messages:
    17
    Hey Guys,
    I'm trying to add custom bricks based on the Field Bricks. When I add the following code to the bricks.php file, it works perfectly. Code:
    <code>
    class Am_Form_Brick_Accounts extends Am_Form_Brick
    {
    protected $field = null;
    static function createAvailableBricks($className)
    {
    $res = array();
    foreach(Am_Di::getInstance()->userTable->customFields()->getAll() as $field)
    {
    if (strpos($field->name, 'aff_') === 0) continue;
    if (!is_numeric(strpos($field->name, 'account')) || strpos($field->name, 'account') != 0) continue;
    $res[] = new self('my-'.$field->getName());
    }
    return $res;
    }
    public function __construct($id = null, $config = null)
    {
    $numAccounts = Am_Di::getInstance()->user->maxaccounts;
    parent::__construct($id, $config);
    $fieldName = str_replace('my-', '', $id);
    $this->field = Am_Di::getInstance()->userTable->customFields()->get($fieldName);
    $accountNum = str_replace('account','',$fieldName);
    $accountNo = intval($accountNum);
    // to make it fault-tolerant when customfield is deleted
    if (!$this->field && $accountNo <= $numAccounts)
    $this->field = new Am_CustomFieldText($fieldName, $fieldName);
    }
    function getName()
    {
    return $this->field->title;
    }
    function insertBrick(HTML_QuickForm2_Container $form)
    {
    $numAccounts = Am_Di::getInstance()->user->maxaccounts;
    $accountNum = str_replace('account','',$this->field->name);
    $accountNo = intval($accountNum);
    if ($accountNo <= $numAccounts) {
    $this->field->addToQF2($form);
    $elementarray = $form->getElementsByName($this->field->name);
    $element = $elementarray[0];
    if($this->getConfig('isDisabled'))
    {
    $element->toggleFrozen(true);
    }
    }
    }
    function getFieldName() { return $this->field->name; }
    public function initConfigForm(Am_Form $form)
    {
    $element =& $form->addAdvCheckbox("isDisabled")->setLabel("Is Disabled?");

    }
    }
    </code>

    However, of course this will be overwritten on upgrade. So what I'm trying to do is create a plugin to do it. I have the plugin file MyBricks.php being:
    <code>
    <?php
    class Am_Plugin_MyBricks extends Am_Plugin
    {
    const PLUGIN_STATUS = self::STATUS_PRODUCTION;
    const PLUGIN_REVISION = '1.0.0';

    protected $id;
    protected $done = false;
    public function __construct(Am_Di $di, array $config)
    {
    $this->id = $di->config->get('myBricks');
    // print_rre($this->id);
    parent::__construct($di, $config);
    }
    function onLoadBricks()
    {
    require_once dirname(__FILE__) . '/AccountsBrick.php';

    }
    }
    </code>
    and then the AccountsBrick.php file holds the Am_Form_Brick_Accounts class. However, when I do this, the bricks show up in the profile form editing, but when I try to view the profile after adding some of these bricks, I get the "An Error has Occurred" page. Any ideas?

    Thanks,
    Paul
  2. alexander

    alexander Administrator Staff Member

    Joined:
    Jan 8, 2003
    Messages:
    6,279
    What error did you get exactly? Check aMember CP -> Logs -> Error log. There should be exact error/backtrace listed.
  3. pwwatson

    pwwatson New Member

    Joined:
    Jul 10, 2010
    Messages:
    17
    The error was:
    Error in Am_Form_Brick::createFromRecord cannot create class [Am_Form_Brick_Accounts] - not defined

    with expanded information being:
    Exception Am_Exception_InternalError
    Am_Form_Brick::createFromRecord [ application/default/models/SavedForm.php : 106 ]
    SavedForm->getBricks [ library/Am/Form/Profile.php : 11 ]
    Am_Form_Profile->initFromSavedForm [ application/default/controllers/ProfileController.php : 40 ]
    ProfileController->indexAction [ library/Am/Controller.php : 139 ]
    Am_Controller->_runAction [ library/Am/Controller.php : 116 ]
    Am_Controller->dispatch [ library/Zend/Controller/Dispatcher/Standard.php : 295 ]
    Zend_Controller_Dispatcher_Standard->dispatch [ library/Zend/Controller/Front.php : 954 ]
    Zend_Controller_Front->dispatch [ library/Am/App.php : 1377 ]
    Am_App->run [ index.php : 41 ]
  4. caesar

    caesar aMember Pro Developer Staff Member

    Joined:
    Oct 16, 2009
    Messages:
    2,295
    Hello,

    I recommend you to put code of your brick to file application/configs/site.php (rename site-dist.php to site.php in case of site.php does not exists) . It should fix your issue and this file (site.php) never overwritten while upgrade. Also you will avoid creation of unnecessary plugin in this case.
  5. pwwatson

    pwwatson New Member

    Joined:
    Jul 10, 2010
    Messages:
    17
    Doing this doesn't seem to work. The bricks don't appear in the profile forms editor.
  6. alex

    alex aMember Pro Customer Staff Member

    Joined:
    Jan 24, 2004
    Messages:
    6,021
    Strange, could you please attach your site.php file (ZIP it first), and what other files do you see in amember/application/configs/ folder along with this site.php?
  7. pwwatson

    pwwatson New Member

    Joined:
    Jul 10, 2010
    Messages:
    17
    Attached is my configs folder.
  8. alex

    alex aMember Pro Customer Staff Member

    Joined:
    Jan 24, 2004
    Messages:
    6,021
    site.php must look like
    PHP:
    <?php

        
    class Am_Form_Brick_Accounts extends Am_Form_Brick  
        

            protected 
    $field null
            static function 
    createAvailableBricks($className
            { 
                
    $res = array(); 
                foreach(
    Am_Di::getInstance()->userTable->customFields()->getAll() as $field
                { 
                    if (
    strpos($field->name'aff_') === 0) continue; 
                    if (!
    is_numeric(strpos($field->name'account')) || strpos($field->name'account') != 0) continue; 
                    
    $res[] = new self('my-'.$field->getName()); 
                } 
                return 
    $res
            } 
            public function 
    __construct($id null$config null
            { 
                
    $numAccounts Am_Di::getInstance()->user->maxaccounts
                
    parent::__construct($id$config); 
                
    $fieldName =  str_replace('my-'''$id); 
                
    $this->field Am_Di::getInstance()->userTable->customFields()->get($fieldName); 
                
    $accountNum str_replace('account','',$fieldName); 
                
    $accountNo intval($accountNum); 
                
    // to make it fault-tolerant when customfield is deleted  
                
    if (!$this->field && $accountNo <= $numAccounts
                    
    $this->field = new Am_CustomFieldText($fieldName$fieldName); 
            } 
            function 
    getName() 
            { 
                return 
    $this->field->title
            } 
            function 
    insertBrick(HTML_QuickForm2_Container $form
            { 
                
    $numAccounts Am_Di::getInstance()->user->maxaccounts
                echo 
    "num Accounts = $numAccounts"
                
    $accountNum str_replace('account','',$this->field->name); 
                
    $accountNo intval($accountNum); 
                if (
    $accountNo <= $numAccounts) { 
                    
    $this->field->addToQF2($form); 
                    
    $elementarray $form->getElementsByName($this->field->name); 
                    
    $element $elementarray[0]; 
                    if(
    $this->getConfig('isDisabled')) 
                    { 
                        
    $element->toggleFrozen(true); 
                    } 
                } 
            } 
            function 
    getFieldName() { return $this->field->name; } 
            public function 
    initConfigForm(Am_Form $form
            { 
                
    $element =& $form->addAdvCheckbox("isDisabled")->setLabel("Is Disabled?"); 
                 
            } 
        } 
     
        
  9. pwwatson

    pwwatson New Member

    Joined:
    Jul 10, 2010
    Messages:
    17
    Alex,
    Should there be a closing ?> at the end of the file? I tried it both with and without and while it seems to work, when I save the changes to the profile page, it does save the changes, however, it then throws me to a blank page -- no error message, completely blank. When I look at the log, it shows an error:

    You must be authorized to access this area

    and yet I am logged in as admin. The expanded info is:

    Exception Am_Exception_AccessDenied
    Am_Di->getUserService [ library/sf/sfServiceContainer.php : 184 ]
    sfServiceContainer->getService [ library/sf/sfServiceContainerBuilder.php : 66 ]
    sfServiceContainerBuilder->getService [ library/Am/Di.php : 236 ]
    Am_Di->getService [ library/sf/sfServiceContainer.php : 276 ]
    sfServiceContainer->__get [ application/configs/site.php : 19 ]
    Am_Form_Brick_Accounts->__construct [ application/configs/site.php : 13 ]
    Am_Form_Brick_Accounts::createAvailableBricks [ library/Am/Form/Brick.php : 170 ]
    Am_Form_Brick::getAvailableBricks [ library/Am/Form/Profile.php : 23 ]
    Am_Form_Profile->getAvailableBricks [ library/Am/Form/Element/BricksEditor.php : 21 ]
    Am_Form_Element_BricksEditor->__construct [ application/default/controllers/AdminSavedFormController.php : 59 ]
    Am_Form_Admin_SavedForm->init [ library/Am/Form.php : 31 ]
    Am_Form->__construct [ library/Am/Form/Admin.php : 18 ]
    Am_Form_Admin->__construct [ application/default/controllers/AdminSavedFormController.php : 28 ]
    Am_Form_Admin_SavedForm->__construct [ application/default/controllers/AdminSavedFormController.php : 204 ]
    AdminSavedFormController->createForm [ library/Am/Grid/Editable.php : 207 ]
    Am_Grid_Editable->createForm [ library/Am/Grid/Editable.php : 145 ]
    Am_Grid_Editable->getForm [ library/Am/Grid/Editable.php : 414 ]
    Am_Grid_Editable->doFormActions [ library/Am/Grid/Action/Abstract.php : 136 ]
    Am_Grid_Action_Abstract->_runFormAction [ library/Am/Grid/Action/Edit.php : 19 ]
    Am_Grid_Action_Edit->run [ library/Am/Grid/Editable.php : 221 ]
    Am_Grid_Editable->actionRun [ library/Am/Grid/ReadOnly.php : 394 ]
    Am_Grid_ReadOnly->run [ library/Am/Grid/ReadOnly.php : 431 ]
    Am_Grid_ReadOnly->runWithLayout [ library/Am/Controller/Grid.php : 22 ]
    Am_Controller_Grid->indexAction [ library/Am/Controller.php : 139 ]
    Am_Controller->_runAction [ library/Am/Controller.php : 116 ]
    Am_Controller->dispatch [ library/Zend/Controller/Dispatcher/Standard.php : 295 ]
    Zend_Controller_Dispatcher_Standard->dispatch [ library/Zend/Controller/Front.php : 954 ]
    Zend_Controller_Front->dispatch [ library/Am/App.php : 1377 ]
    Am_App->run [ index.php : 41 ]
  10. alex

    alex aMember Pro Customer Staff Member

    Joined:
    Jan 24, 2004
    Messages:
    6,021
    In the constructor, you are accessing "user" "service" of Di container:
    $numAccounts = Am_Di::getInstance()->user->maxaccounts;

    it causes problems, as you are not logged-in as USER (logged as admin though) and throws an exception when brick is created to place it in the form editor.

    to fix it, move all the code that relies on user into insertBrick method.
  11. pwwatson

    pwwatson New Member

    Joined:
    Jul 10, 2010
    Messages:
    17
    OK, now the site code looks like this:

    PHP:
      <?php

            
    class Am_Form_Brick_Accounts extends Am_Form_Brick
            
    {
                protected 
    $field null;
                static function 
    createAvailableBricks($className)
                {
                    
    $res = array();
                    foreach(
    Am_Di::getInstance()->userTable->customFields()->getAll() as $field)
                    {
                        if (
    strpos($field->name'aff_') === 0) continue;
                        if (!
    is_numeric(strpos($field->name'account')) || strpos($field->name'account') != 0) continue;
                        
    $res[] = new self('my-'.$field->getName());
                    }
                    return 
    $res;
                }
                public function 
    __construct($id null$config null)
                {
                    
    parent::__construct($id$config);
                    
    $fieldName =  str_replace('my-'''$id);
                    
    $this->field Am_Di::getInstance()->userTable->customFields()->get($fieldName);
                    
    // to make it fault-tolerant when customfield is deleted
                    
    if (!$this->field)
                        
    $this->field = new Am_CustomFieldText($fieldName$fieldName);
                }
                function 
    getName()
                {
                    return 
    $this->field->title;
                }
                function 
    insertBrick(HTML_QuickForm2_Container $form)
                {
                    
    $numAccounts Am_Di::getInstance()->user->maxaccounts;
                    
    $accountNum str_replace('account','',$this->field->name);
                    
    $accountNo intval($accountNum);
                    if (
    $accountNo <= $numAccounts) {
                        
    $this->field->addToQF2($form);
                        
    $elementarray $form->getElementsByName($this->field->name);
                        
    $element $elementarray[0];
                        if(
    $this->getConfig('isDisabled'))
                        {
                            
    $element->toggleFrozen(true);
                        }
                    }
                }
                function 
    getFieldName() { return $this->field->name; }
                public function 
    initConfigForm(Am_Form $form)
                {
                    
    $element =& $form->addAdvCheckbox("isDisabled")->setLabel("Is Disabled?");

                }
            }
     
    However, when I go to the profile forms editor and click save, it still throws me to a blank page. There's no error in the logs, just throws me to a blank page. Curious...
  12. alex

    alex aMember Pro Customer Staff Member

    Joined:
    Jan 24, 2004
    Messages:
    6,021
    Could you please submit a ticket with access details? It would be easier and faster to resolve.
  13. pwwatson

    pwwatson New Member

    Joined:
    Jul 10, 2010
    Messages:
    17
    For those of you interested, alex found the problem. It was a tab character before the <?php in the site.php file.
  14. mark_sch

    mark_sch aMember Pro Customer

    Joined:
    Aug 22, 2006
    Messages:
    11
    I created a custom brick and included it in site.php. it worked but it causes the newsletter brick to disappear. The one I created below is just a copy of the HTML text brick with a placeholder added so I can create bricks to automatically place pre-determined HTML in sign up forms. Anybody have this issue or know why it causes the newsletter brick to disappear in the form editor?

    PHP:
    class Am_Form_Brick_MyCustomText extends Am_Form_Brick
    {
        static 
    $counter 0;
        public function 
    __construct($id null$config null)
        {
            
    $this->name ___('Custom text');
            
    parent::__construct($id$config);
        }
        public function 
    initConfigForm(Am_Form $form)
        {
            
    $form->addTextarea('html', array('rows' => 15'class' => 'el-wide''placeholder' => '<p><b>My Custom Text</b></p>'))
                ->
    setLabel(___('HTML Code that will be displayed'));
            
    $form->addText('label', array('class' => 'el-wide'))->setLabel(___('Label'));
            
    $form->addAdvCheckbox('no_label')->setLabel(___('Remove Label'));
        }

        public function 
    insertBrick(HTML_QuickForm2_Container $form)
        {
            
    $attrs $data = array();
            
    $data['content'] = $this->getConfig('html');
            if (
    $this->getConfig('no_label')) {
                
    $attrs['class'] = 'no-label';
            } else {
                
    $data['label'] = $this->getConfig('label');
            }
            
    $form->addStatic('html' . (++self::$counter), $attrs$data);
        }
        public function 
    isMultiple()
        {
            return 
    true;
        }
    }
  15. caesar

    caesar aMember Pro Developer Staff Member

    Joined:
    Oct 16, 2009
    Messages:
    2,295
    @mark_sch please extract code of your brick class to separate file (you may call it brick.php and put this file to folder configs) then in file site.php add the following code:
    PHP:
    Am_Di::getInstance()->hook->add(Am_Event::LOAD_BRICKS'myLoadBrick');

    function 
    myLoadBrick()
    {
        include_once 
    'brick.php';
    }
    It should fix your issue for sure.

Share This Page