# Application Modules - Structure

Each module represents a separate physical directory, where placed it's all files. Some of the files may be moved to another folders according to develop needs while installation/unstallation process. All modules must be placed in `protected/modules/` directory.
Below the minimum file structure for the standard module. Take in account that you may define update files like: `update.002.mysql.sql`, `update.003.mysql.sql`, etc. While updating procedure the system will run them automatically according to their order.

- modules/ directory where all modules are placed
  - module/
    - config/
      - main.php main configuration
    - data/
      - install.mysql.sql
      - uninstall.mysql.sql
      - update.mysql.sql
    - CHANGELOG
    - info.xml

Here the file structure for a real News module:

- modules/ directory where all modules are placed
  - news/ directory for storing News module files
    - components/ module components folder
      - NewsComponent.php module main component
    - config/
      - main.php main configuration
      - news.php special configuration (movable file)
    - controllers/ module controllers
      - NewsController.php
    - data/ module data files
      - install.mysql.sql
      - uninstall.mysql.sql
      - update.002.mysql.sql
      - update.003.mysql.sql
    - images/ module images
      - icon.png
    - messages/ module messages (localization files)
      - news.php
    - models/ module models
      - News.php
    - vews/ model views
      - news/ view files for controller CNews
        - add.php
        - edit.php
        - manage.php
        - view.php
        - viewall.php
    - CHANGELOG change log file
    - info.xml main information file

`info.xml` - change log file ¶

    Version 0.0.1
    ----------------------------
    Initial release

`info.xml` - main information file ¶

    <?xml version="1.0" encoding="utf-8"?>
    <install version="1.0" type="module">
        <name>News</name>
        <description>News module allows creating and displaying news on the site</description>
        <version>0.0.1</version>
        <creationDate>15/08/2013</creationDate>
        <lastChangedDate>29/09/2013</lastChangedDate>
        <author>ApPHP</author>
        <authorEmail>info@apphp.com</authorEmail>
        <authorUrl>http://www.apphp.com</authorUrl>
        <copyright>ApPHP</copyright>
        <license>LGPL</license>
        <manual></manual>
        <icon>images/modules/news/icon.png</icon>
        <moduleType>application</moduleType>
        <code>news</code>
        <files>
            <filename>info.xml</filename>
            <components>
                <filename>NewsComponent.php</filename>
            </components>
            <config installationPath="protected/config/">
                <filename exclude="yes">main.php</filename>
                <filename>news.php</filename>
            </config>
            <controllers>
                <filename>NewsController.php</filename>
            </controllers>
            <data>
                <install>install.mysql.sql</install>
                <update>
                    <filename>update.002.mysql.sql</filename>
                    <filename>update.003.mysql.sql</filename>
                </update>
                <uninstall>uninstall.mysql.sql</uninstall>
            </data>
            <images installationPath="images/modules/news/">
                <filename>icon.png</filename>
            </images>
            <robots exclude="yes">
                <filename>robots.txt</filename>
            </robots>
            <messages installationPath="protected/messages/*">
               	<filename>news.php</filename>
            </messages>
        </files>
    </install>

`config/main.php` - main configuration file ¶

    <?php
    return array(
        // Module classes
        'classes' => array(
            'NewsComponent',
            'News',
        ),
        // Management links
        'managementLinks' => array(
            A::t('news', 'News') => 'news/manage'
        ),
    );

`config/news.php` - special configuration (movable file, will be copied to `protected/config/` directory) ¶

    <?php
    return array(
        // Module components (optional)
        'components' => array(
            'NewsComponent' => array('enable' => true, 'class' => 'NewsComponent'),
        ),

        // URL manager (optional)
        'urlManager' => array(
            'rules' => array(
                'news/view/id/([0-9]+)' => 'news/view/id/{$0}',
                'news/view/id/([0-9]+)/(.*?)' => 'news/view/id/{$0}',
                'news/view/([0-9]+)' => 'news/view/id/{$0}',
                'news/view/([0-9]+)/(.*?)' => 'news/view/id/{$0}',
                'news/([0-9]+)' => 'news/view/id/{$0}',
                'news/([0-9]+)/(.*?)' => 'news/view/id/{$0}',
            ),
        ),

        // Default settings (optional, if defined - will be used as application default settings)
        'defaultController' => 'pages',
        'defaultAction' => 'view',
    );

`components/NewsComponent.php` - module main component ¶

    <?php
    class NewsComponent extends CComponent
    {
        const NL = "\n";

        /**
         * Draws last news side block
         */
        public static function drawNewsBlock($title = '')
        {
            $output = '';
            $headerLength = 80;
            $newsCount = 3;

            $headerLength = ModulesSettings::model()->param('news', 'news_header_length');
            $newsCount = ModulesSettings::model()->param('news', 'news_count');

            // Fetch datetime format from settings table
            // Or $settings = Bootstrap::init()->getSettings();
            $settings = Settings::model()->findByPk(1);
            $dateTimeFormat = $settings->date_format;

            $news = News::model()->findAll(
                array(
                    'condition'=>'is_published = :isPublished AND created_at < :currentDate',
                    'order'=>'created_at DESC', 'limit'=>'0, '.(int)$newsCount
                ),
                array(':isPublished'=>1, ':currentDate'=>LocalTime::currentDateTime())
            );

            $output .= '<div class="side-panel-block">';
            $output .= '<h3 class="title">'.$title.'</h3>';
            if(is_array($news) && count($news) > 0){
                foreach($news as $key => $val){
                    $output .= '<div class="block-body">
                        <p class="block-title">
                            <a href="news/view/id/'.$val['id'].'">
                                '.CString::substr($val['news_header'], $headerLength).'
                            </a>
                        </p>
                        <p class="block-date">'.date($dateTimeFormat, strtotime($val['created_at'])).'</p>
                        <p class="block-content">'.CString::substr(strip_tags($val['news_text']), 125, '', true).'
                            <a class="more more-news" href="news/view/id/'.$val['id'].'">
                                '.A::t('news', 'read more').' »
                            </a>
                        </p>
                    </div>';
                }
            }else{
                $output .= A::t('news', 'No News Found');
            }
            $output .= '</div>';

            return $output;
        }
    }