# Knowledge Base

#### General:

- How to assign controller action to Backend or Frontend?
- How to (override) ApPHP framework helper classes?
- How to define default controller and action (start page) for application?
- How to define my own default action for all project controllers?
- How to display time and date formats in my local language?
- How to detect mobile, tablet ot desktop devices?

#### Modules:

- How to define multiple translation for module in config file?
- How to create SEO links for module?
- How to install/update module?
- How to allow search in module?

#### Debugging and Error Handling:

- How to turn "On" debug mode?
- How to enable error logging?

### General: ¶

Q: How to assign controller action to Backend or Frontend?

A: Directy CMF has embedded features to define any action in controller (or a whole controller) to be assigned to Backend or Frontend only (that means only appropriate template will be used).
To assign action to Frontend use `Website::setFrontend();`

    public function viewAllAction($menuId = 0)
    {
        // Set frontend mode
        Website::setFrontend();

        // Your code here...
    }

To assign action to Backend use `Website::setBackend();`

    public function addAction($menuId = 0)
    {
        // Set backend mode
        Website::setBackend();

        // Your code here...
    }

For advanced use you may define directly backend mode and check privilege access.
To do this simply call `Website::prepareBackendAction();`

    public function addAction($menuId = 0)
    {
        // Set backend mode
        // 1st param - action name. e.g. "manage", "add", "insert", "edit", "update" or "delete"
        // 2st param - privilege category, e.g. "posts", "restaurant_info", "restaurant_menus" etc.
        // 3st param - redirtion path, e.g. "modules/manage", "posts/view", "modules/settings/code/restaurant" etc.
        Website::prepareBackendAction('add', 'restaurant_info', 'modules/settings/code/restaurant');

        // Your code here...
    }

Q: How to extend (override) ApPHP framework helper classes?

A: To override ApPHP framework helper classes you have to do following:

1. Create directory named `helpers` in `protected/` directory of your application.
2. Copy into this directory a required helper class from the framework directory.
3. Change the code of this class according to yuor needs.

There is also another solution:

1. Create directory named `helpers` in `protected/` directory of your application.
2. Copy into this directory a required helper class from the framework directory.
3. Rename an original helper class in directory `helpers` of yuor application without prefix `"C"`, for example: `CHtml` > `Html`.
4. Create an empty class with original helper name and extend it from the class created on the previous step.
5. In the new class override only the method you need. When new update of ApPHP framework will be released simply replace the code of the class created on step 3.
6. Add to extended class constructor with `parent::__construct();`
7. Before call of extended file - create an object of such class type and then use it.

Structure of directory `helpers`

- protected/ application directory
  - helpers/ directory of helpers classes
    - Html.php original framework helper class
    - CHtml.php extended class

Code of CHtml class

    <?php
    include('Html.php');

    class CHtml extends Html
    {
        /**
         * Class default constructor
         */
        public function __construct()
        {
            parent::__construct();
        }

        public static function overridedMethod()
        {
            // ...
        }

    );

Q: How to define default controller and action for application?

A: To define default controller and action for application you have to define them in `protected/config/main.php`:

    <?php
    return array(
        // Default settings
        'defaultController' => 'pages',
        'defaultAction' => 'view',
    );

or redefine it in module `module/config/[module-name].php` file using the same syntax:

    <?php
    return array(
        // Default settings (optional, if defined - will be used as application default settings)
        'defaultController' => 'posts',
        'defaultAction' => 'index',
    );

Q: How to define my own default action for all project controllers?

A: By default the default action for each controller is `index` -> `indexAction`. If you want to change it go to `framework/core/CRouter.php`, find there

    <?php
    /**   @var string */
    private $_defaultAction = 'index';

and re-declare action value according to yuor needs. Remeber: these changes will affect all controllers in the project.

Q: How to display time and date formats in my local language?

A: To display date or datetime string in your local language you have to use `CLocale` helper:

    <?php
    // Use string format
    echo CLocale::date('F j Y, g:ia', $dateTime);
    // Use Unix format
    echo CLocale::date('F j Y, g:ia', strtotime($dateTime), true);

Q: How to detect mobile, tablet ot desktop devices?

A: To detect what device your visitor uses you have to use following code:

    <?php
    // Call mobile detect componenet
    $detect = A::app()->getMobileDetect();
    // Test if this is a mobile device
    if($detect->isMobile()) echo 'You work on a mobile device!';
    if($detect->isTablet()) echo 'You work on a tablet device!';
    if(!$detect->isMobile() && !$detect->isTablet()) echo 'You work on desktop!';

### Modules ¶

Q: How to define multiple translation for module in config file?

A: You may translate your module into other languages and tell the framework to copy these files into `messages/` directory according to related language.
Below the definition of multiple translation for module in config file:

    <messages installationPath="protected/messages/*">
        <en default="true">
            <filename>webforms.php</filename>
        </en>
        <es>
            <filename>webforms.php</filename>
        </es>
        <de>
            <filename>webforms.php</filename>
        </de>
    </messages>

Single file translation definition:

    <messages installationPath="protected/messages/*">
        <filename>news.php</filename>
    </messages>

Q: How to create SEO links for module?

A: First of all you have to define special rules in your module config file, then you may use allowed formats in your code. Check the example below, now instead of `pages/view/id/3` you may use following format for module links: `pages/view/3`, `pages/view/3/Test-Page`, `pages/3/Test-Page` etc.

    <?php
    return array(
        // URL manager
        'urlManager' => array(
            'rules' => array(
                'pages/view/id/([0-9]+)' => 'pages/view/id/{$0}',
                'pages/view/([0-9]+)' => 'pages/view/id/{$0}',
                'pages/view/([0-9]+)/(.*?)' => 'pages/view/id/{$0}',
                'pages/([0-9]+)' => 'pages/view/id/{$0}',
                'pages/([0-9]+)/(.*?)' => 'pages/view/id/{$0}',
            ),
        ),
    );

Q: How to install/update module?

A: The complete guide to installation and updating modules could be found here.

Q: How to allow search in module?

A: To allow search in module yuo have to perform following:

1. Add to yuor module SQL command that adds this module to `search_categories` table:

    // Example for module News, where callback class is model "News" and callback method is "search"
    INSERT INTO `<DB_PREFIX>search_categories` (`id`, `category_code`, `category_name`, `callback_class`, `callback_method`, `items_count`, `is_active`)
    VALUES (NULL, 'news', 'News', 'News', 'search', '20', 1);

2. Add the callback method (usually "search") to the model (callback class) and write the code that returns all records according to the search parameters. Below the example of such method for module News:

    <?php
    /**
     * Performs search in news
     * @param string $keywords
     * @param mixed $itemsCount
     * @return array array('0'=>array(news), '1'=>total)
     */
    public function search($keywords = '', $itemsCount = 10)
    {
        $result = array();

        if($keywords !== ''){

            $limit = !empty($itemsCount) ? '0, '.(int)$itemsCount : '';
            $condition = CConfig::get('db.prefix').$this->_table.'.is_published = 1 AND '.
                CConfig::get('db.prefix').$this->_tableTranslation.'.news_text LIKE :keywords OR '.
                CConfig::get('db.prefix').$this->_tableTranslation.'.news_header LIKE :keywords';

            // Count total items in result
            $total = $this->count(array('condition'=>$condition), array(':keywords'=>'%'.$keywords.'%'));

            // Prepare news result
            $news = $this->findAll(array('condition'=>$condition, 'limit' => $limit), array(':keywords'=>'%'.$keywords.'%'));
            foreach($news as $key => $val){
                $result[0][] = array(
                    'date'    => $val['created_at'],
                    'title'   => $val['news_header'],
                    'content' => $val['news_text'],
                    'link'    => Website::prepareLinkByFormat('news', 'news_link_format', $val['id'], $val['news_header'])
                );
            }

            $result[1] = $total;
        }

        return $result;
    }

### Debugging and Error Handling ¶

Q: How to turn "On" debug mode?

A: Find more information how to turn "On" debug mode: Debug Mode Info.

Q: How to enable error logging?

A: Directy CMF has embedded features to log errors, warnings, etc.
To enable logger you have turn it "On" via `config/config.main.php` file.

    // Logger settings
    'log' => array(
       'enable'	=> true,
       'path' 	=> 'protected/tmp/logs/',
       'fileExtension' => 'php',
       'dateFormat'	=> 'Y-m-d H:i:s',
       'threshold' 	=> 1,
       'filePermissions' => 0644,
       'lifetime' 	=> 30	/* in days */
    ),

After logger is turned "On" you may use it by yourself in the code with following syntax:

    CLog::addMessage('error', 'Error description');
    CLog::addMessage('debug', 'Debug description');
    CLog::addMessage('info', 'Info description');

Example of usage:

    try{
       // Your code here...
    }catch(Exception $e){
       CLog::addMessage('debug', 'Exception caught: ',  $e->getMessage(), "\n");
    }