Location: PHPKode > projects > SolarPHP > solar-system-1.1.1/solar/source/solar/Solar/Cli/MakeVendor/Data/Controller_Bread.txt
{:php}
/**
 * 
 * Base page-controller class for models.
 * 
 */
abstract class {:vendor}_Controller_Bread extends {:vendor}_Controller_Page
{
    /**
     * 
     * A form for editing a single record.
     * 
     * @var Solar_Form
     * 
     */
    public $form;
    
    /**
     * 
     * A single record.
     * 
     * @var Solar_Sql_Model_Record
     * 
     */
    public $item;
    
    /**
     * 
     * The record columns to show for the item.
     * 
     * @var array
     * 
     */
    public $item_cols = array();
    
    /**
     * 
     * A collection of records.
     * 
     * @var Solar_Sql_Model_Collection
     * 
     */
    public $list;
    
    /**
     * 
     * The record columns to show for the list.
     * 
     * @var array
     * 
     */
    public $list_cols = array();
    
    /**
     * 
     * The name of the main model.
     * 
     * Override this in child classes.
     * 
     * @var string
     * 
     */
    public $model_name;
    
    /**
     * 
     * The current search term, if any.
     * 
     * @var string
     * 
     */
    public $search_term;
    
    /**
     * 
     * The current authenticated user.
     * 
     * @var Solar_User
     * 
     */
    public $user;
    
    /**
     * 
     * The default action when no action is specified.
     * 
     * @var string
     * 
     */
    protected $_action_default = 'browse';
    
    /**
     * 
     * Use only these columns for the form in the given action, and when 
     * loading record data for that action.
     * 
     * When empty, uses all columns.
     * 
     * The format is `'action' => array('col', 'col', 'col' ...)`.
     * 
     * @var array
     * 
     */
    protected $_form_cols = array(
        'add'  => array(),
        'edit' => array(),
    );
    
    /**
     * 
     * An instance of the model catalog.
     * 
     * @var Solar_Sql_Model_Catalog
     * 
     */
    protected $_model;
    
    /**
     * 
     * The default order to use for lists.
     * 
     * @var string|array
     * 
     */
    protected $_order = null;
    
    /**
     * 
     * Which columns to use when building a search query.
     * 
     * Search will be disabled if there are no columns listed here.
     * 
     * @var array
     * 
     */
    protected $_search_cols = array();
    
    /**
     * 
     * Setup logic to register and retain a model catalog.
     * 
     * @return void
     * 
     */
    protected function _setup()
    {
        // parent logic
        parent::_setup();
        
        // set properties from registry
        $this->_model = Solar_Registry::get('model_catalog');
        $this->user   = Solar_Registry::get('user');
        
        // if model name not preset, use the last part of the class name.
        // e.g., `Vendor_Something_FooBar => foo_bar`.
        if (! $this->model_name) {
            $inflect = Solar_Registry::get('inflect');
            $name = strrchr(get_class($this), '_');
            $this->model_name = strtolower($inflect->camelToUnder($name));
        }
    }
    
    // -----------------------------------------------------------------------
    // 
    // Actions
    // 
    // -----------------------------------------------------------------------
    
    /**
     * 
     * Browse records by page.
     * 
     * @return void
     * 
     */
    public function actionBrowse()
    {
        // is the user allowed access?
        if (! $this->_isUserAllowed()) {
            return;
        }
        
        // set the collection
        $this->_setList(array(
            'page'        => $this->_query('page', 1),
            'paging'      => $this->_query('paging', 10),
            'count_pages' => true,
        ));
    }
    
    /**
     * 
     * View one record by ID.
     * 
     * @param int $id The record ID to view.
     * 
     * @return void
     * 
     */
    public function actionRead($id = null)
    {
        // need an id
        if (! $id) {
            return $this->_error('ERR_NO_ID_SPECIFIED');
        }
        
        // set the record; does it exist?
        if (! $this->_setItem($id)) {
            return $this->_error('ERR_NO_SUCH_ITEM');
        }
        
        // is the user allowed access?
        if (! $this->_isUserAllowed()) {
            return;
        }
    }
    
    /**
     * 
     * Edit a record by ID.
     * 
     * @param int $id The record id.
     * 
     * @return void
     * 
     */
    public function actionEdit($id = null)
    {
        // need an id
        if (! $id) {
            return $this->_error('ERR_NO_ID_SPECIFIED');
        }
        
        // process: cancel
        if ($this->_isProcess('cancel')) {
            // forward back to reading
            return $this->_redirect("/{$this->_controller}/read/$id");
        }
        
        // process: delete
        if ($this->_isProcess('delete')) {
            // forward to the delete method for confirmation
            return $this->_redirect("/{$this->_controller}/delete/$id");
        }
        
        // set the record; does it exist?
        if (! $this->_setItem($id)) {
            return $this->_error('ERR_NO_SUCH_ITEM');
        }
        
        // is the user allowed access?
        if (! $this->_isUserAllowed()) {
            return;
        }
        
        // process: save
        if ($this->_isProcess('save')) {
            $this->_saveItem();
        }
        
        // set the form-building hints for the record
        $this->_setFormItem();
        
        // catch flash indicating a successful add
        if ($this->_session->getFlash('success_added')) {
            $this->form->setStatus(Solar_Form::STATUS_SUCCESS);
            $this->form->feedback = $this->locale('SUCCESS_ADDED');
        }
        
        // turn off http caching
        $this->_response->setNoCache();
    }
    
    /**
     * 
     * Add a new record.
     * 
     * @return void
     * 
     */
    public function actionAdd()
    {
        // is the user allowed access?
        if (! $this->_isUserAllowed()) {
            return;
        }
        
        // process: cancel
        if ($this->_isProcess('cancel')) {
            // forward back to browse
            return $this->_redirect("/{$this->_controller}/browse");
        }
        
        // set a new record
        $this->_setItemNew();
        
        // process: save
        if ($this->_isProcess('save') && $this->_saveItem()) {
            // save a flash value for the next page
            $this->_session->setFlash('success_added', true);
            // redirect to editing using the primary-key value
            $id = $this->item->getPrimaryVal();
            return $this->_redirectNoCache("/{$this->_controller}/edit/$id");
        }
        
        // set the form-building hints for the item
        $this->_setFormItem();
        
        // turn off http caching
        $this->_response->setNoCache();
    }
    
    /**
     * 
     * Delete a record by ID; asks for confirmation before actually deleting.
     * 
     * @param int $id The record ID.
     * 
     * @return void
     * 
     */
    public function actionDelete($id = null)
    {
        // need an id
        if (! $id) {
            return $this->_error('ERR_NO_ID_SPECIFIED');
        }
        
        // set the record; does it exist?
        if (! $this->_setItem($id)) {
            return $this->_error('ERR_NO_SUCH_ITEM');
        }
        
        // is the user allowed access?
        if (! $this->_isUserAllowed()) {
            return;
        }
        
        // process: delete confirm
        if ($this->_isProcess('delete_confirm')) {
            // delete it
            $this->item->delete();
            // redirect to browse
            $this->_redirectNoCache("/{$this->_controller}");
        }
        
        // turn off http caching
        $this->_response->setNoCache();
    }
    
    /**
     * 
     * Search records for a term.
     * 
     * @return void
     * 
     */
    public function actionSearch()
    {
        // make sure search is enabled
        if (! $this->_search_cols) {
            return $this->_error('ERR_SEARCH_NOT_ENABLED');
        }
        
        // is the user allowed access?
        if (! $this->_isUserAllowed()) {
            return;
        }
        
        // set the form, which also populates the values
        $this->_setFormSearch();
        
        // should we do a search?
        $this->search_term = $this->form->getValue('q');
        if (! $this->search_term) {
            return;
        }
        
        // force the term string to lower-case, and replace spaces with
        // wildcards, to allow a very generous result set.
        $term = strtolower($this->search_term);
        $term = str_replace(' ', '%', $term);
        
        // build the where clause and bind values
        $where = array();
        $bind  = array();
        foreach ($this->_search_cols as $col) {
            // force lower-case comparison
            $where[]    = "LOWER({$this->model_name}.{$col}) LIKE :$col";
            $bind[$col] = "%{$term}%";
        }
        
        // build the fetch params
        $fetch = array(
            'where'       => implode(' OR ', $where),
            'bind'        => $bind,
            'page'        => $this->_query('page', 1),
            'paging'      => $this->_query('paging', 10),
            'count_pages' => true,
        );
        
        // set the collection
        $this->_setList($fetch);
    }
    
    // -----------------------------------------------------------------------
    // 
    // Support methods.
    // 
    // -----------------------------------------------------------------------
    
    /**
     * 
     * Checks if user is allowed access to this class, the current action,
     * and the current item.
     * 
     * @return bool
     * 
     */
    protected function _isUserAllowed()
    {
        $allowed = $this->user->access->isAllowed(
            get_class($this),
            $this->_action,
            $this->item
        );
        
        if ($allowed) {
            return true;
        }
        
        // not allowed, but why?
        if ($this->user->auth->isValid()) {
            $this->_error('ERR_NOT_ALLOWED_ACCESS');
        } else {
            $this->_error('ERR_NOT_LOGGED_IN');
        }
        
        // _error() set status code 500, but 403 (Forbidden) is better here
        $this->_response->setStatusCode(403);
        return false;
    }
    
    /**
     * 
     * Sets $this->item from a primary key value.
     * 
     * @param int $id The primary key for the record.
     * 
     * @return Solar_Sql_Model_Record A record on success, or null on failure.
     * 
     */
    protected function _setItem($id)
    {
        $model = $this->_model->getModel($this->model_name);
        $this->item = $model->fetch($id);
        return $this->item;
    }
    
    /**
     * 
     * Sets $this->item as a new record.
     * 
     * @return Solar_Sql_Model_Record A new record.
     * 
     */
    protected function _setItemNew()
    {
        $model = $this->_model->getModel($this->model_name);
        $this->item = $model->fetchNew();
        return $this->item;
    }
    
    /**
     * 
     * Sets $this->list based on fetch parameters.
     * 
     * @param Solar_Sql_Model_Params_Fetch|array The fetch parameters.
     * 
     * @return Solar_Sql_Model_Collection A collection on success, or an empty
     * array on failure.
     * 
     */
    protected function _setList($fetch = null)
    {
        if ($this->_order && empty($fetch['order'])) {
            $fetch['order'] = $this->_order;
        }
        
        $model = $this->_model->getModel($this->model_name);
        $this->list = $model->fetchAll($fetch);
        return $this->list;
    }
    
    /**
     * 
     * Loads $this->item with data from the current request POST data, then
     * saves it.
     * 
     * @return bool True if the save was a success, false if it was a failure.
     * 
     */
    protected function _saveItem()
    {
        $this->_loadItem();
        return $this->item->save();
    }
    
    /**
     * 
     * Loads $this->item with data from the current request POST data.
     * 
     * @return void
     * 
     */
    protected function _loadItem()
    {
        $model      = $this->_model->getModel($this->model_name);
        $array_name = $model->array_name;
        $data       = $this->_request->post($array_name, array());
        
        $cols = array();
        if (! empty($this->_form_cols[$this->_action])) {
            $cols = $this->_form_cols[$this->_action];
        }
        
        $this->item->load($data, $cols);
    }
    
    /**
     * 
     * Sets $this->form using $this->item and $this->_form_cols for the form
     * hints.
     * 
     * @return Solar_Form
     * 
     */
    protected function _setFormItem()
    {
        $cols = array();
        if (! empty($this->_form_cols[$this->_action])) {
            $cols = $this->_form_cols[$this->_action];
        }
        
        $this->form = $this->item->newForm($cols);
        return $this->form;
    }
    
    /**
     * 
     * Sets $this->form as a search form.
     * 
     * @return Solar_Form
     * 
     */
    protected function _setFormSearch()
    {
        $this->form = Solar::factory('Solar_Form');
        
        $uri = Solar::factory('Solar_Uri_Action', array(
            'uri' => "/{$this->_controller}/search",
        ));
        
        $this->form->attribs['action'] = $uri->get();
        $this->form->attribs['method'] = "get";
        
        $this->form->setElement('q', array(
            'type'  => 'text',
        ));
        
        $this->form->populate();
        
        return $this->form;
    }
    
    /**
     * 
     * Sets the <title> string in the view before rendering.
     * 
     * @return void
     * 
     */
    protected function _preRender()
    {
        parent::_preRender();
        
        $title = ucwords($this->_controller)
               . ' : '
               . ucwords($this->_action);
               
        $this->_view_object->head()->setTitle($title);
    }
}
Return current item: SolarPHP