Table Of Contents

Previous topic

Slideshow

Next topic

Layout i386

An Extension Module Example

Requirements

User should be able to add new RSS feed and read the existing feed.

Design

Server Side

  • List view of existing RSS feed.
  • Save action for new RSS feed.

Client Side

  • Enable option to click on the RSS feed and load the items.
  • Provide option to add new RSS feed - accept the URL and title.

Implementation

Getting Started

Create the bootstrap vtlib script in root folder of Vtiger to activate the module entry.

include_once 'vtlib/Vtiger/Module.php';
$Vtiger_Utils_Log = true;

$MODULENAME = 'MyRss';

$moduleInstance = Vtiger_Module::getInstance($MODULENAME);
if ($moduleInstance || file_exists('modules/'.$MODULENAME)) {
   echo "Module already present - choose a different name.";
} else {
   $moduleInstance = new Vtiger_Module();
   $moduleInstance->name = $MODULENAME;
   $moduleInstance->parent= 'Tools';
   $moduleInstance->save();

   mkdir('modules/'.$MODULENAME);
   echo "OK\n";
}

Schema

Vtiger_Utils::CreateTable('vtiger_myrss',
'(id integer not null auto_increment, url varchar(255), title varchar(50), primary key (id))');

Directory Structure

Code

schema.xml

<?xml version="1.0"?>
<schema>
    <tables>
        <table>vtiger_myrss</table>
    </tables>
</schema>

MyRss.php

<?php

class MyRss {
        function vtlib_handler($moduleName, $eventType) {
                if ($eventType == 'module.postinstall') {
                        $data = array('url' => 'https://www.vtiger.com/blogs/?feed=rss2',
                                    'title' => 'Vtiger Blogs');
                                MyRss_Record_Model::create($data);
                }
        }
}

views/List.php

<?php
class MyRss_List_View extends Vtiger_Index_View {
        // We are overriding the default SideBar UI to list our feeds.
        public function preProcess(Vtiger_Request $request, $display = true) {
                $feeds = MyRss_Record_Model::findAll();
                $viewer = $this->getViewer($request);
                $viewer->assign('FEEDS', $feeds);
                return parent::preProcess($request, $display);
        }

        // Injecting custom javascript resources
        public function getHeaderScripts(Vtiger_Request $request) {
                $headerScriptInstances = parent::getHeaderScripts($request);
                $moduleName = $request->getModule();
                $jsFileNames = array(
                        "modules.$moduleName.resources.jquery_rss_min", // . = delimiter
                );
                $jsScriptInstances = $this->checkAndConvertJsScripts($jsFileNames);
                $headerScriptInstances = array_merge($headerScriptInstances, $jsScriptInstances);
                return $headerScriptInstances;
        }
}

models/Record.php

<?php
class MyRss_Record_Model extends Vtiger_Base_Model {
        public function save() {
                $db = PearDatabase::getInstance();
                $db->pquery('INSERT INTO vtiger_myrss (url, title) VALUES(?,?)', array(
                        $this->get('url'), $this->get('title')
                ));
                return $db->getLastInsertID();
        }
        static function create($data) {
                $instance = self::findWithUrl($data['url']);
                if ($instance) {
                        throw new Exception('Duplicate Feed');
                }
                $instance = new self($data);
                return $instance->save();
        }
        static function findWithUrl($url) {
                $db = PearDatabase::getInstance();
                $rs = $db->pquery('SELECT * FROM vtiger_myrss WHERE url=?', array($url));
                return $db->num_rows($rs)? new self($db->fetch_array($rs)) : NULL;
        }
        static function findAll() {
                $db = PearDatabase::getInstance();
                $instances = array();
                $rs = $db->pquery('SELECT * FROM vtiger_myrss ORDER BY id DESC', array());
                if ($db->num_rows($rs)) {
                        while ($data = $db->fetch_array($rs)) {
                                $instances[] = new self($data);
                        }
                }
                return $instances;
        }
}

actions/Save.php

<?php
class MyRss_Save_Action extends Vtiger_Action_Controller {
        public function checkPermission() {
                return true;
        }
        public function process(Vtiger_Request $request) {
                $feedurl = $request->get('url');
                if (empty($feedurl)) {
                        throw new Exception('URL cannot be empty');
                }

                $data = array('url' => $feedurl, 'title' => $feedurl);
                MyRss_Record_Model::create($data);

                $response = new Vtiger_Response();
                $response->setResult(array('feed' => $data));
                return $response;
        }
}

Index.tpl

<div class="listViewPageDiv">
        <div class="listViewTopMenuDiv">
                <div class="listViewActionsDiv">
                        <div id="RssFeedTitle">
                             Learn more about RSS
                             <a href="http://en.wikipedia.org/wiki/RSS" target="_blank">here</a>.
                        </div>
                </div>
        </div>
        <div id="RssFeedContainer" class="listViewEntriesDiv">
                &leftarrow; Selected feed content will be displayed here.
        </div>
</div>
<div id="RssFeedAddFormTpl" style="display: none;">
        <div class="modelContainer">
                <form method="GET" action="javascript:;" class="RssFeedAddForm">
                        <div class="modal-header">
                                <a class="close" data-dismiss="modal">x</a>
                                <h3>New RSS Feed</h3>
                        </div>
                        <div class="modal-body">
                                RSS Feed: <input type="text" name="url" class="validate[required]">
                        </div>
                        <div class="modal-footer">
                                <a class="cancelLink cancelLinkContainer pull-right" data-dismiss="modal">
                                 {vtranslate('LBL_CANCEL')}</a>
                                <button class="btn btn-success" type="submit">Add</button>
                        </div>
                </form>
        </div>
</div>

resources/MyRss.js

jQuery.Class('MyRss_List_Js', {}, {

        registerEvents: function() {
                this.registerFeedClick();
                this.registerFeedAdd();
        },

        registerFeedClick: function() {
                jQuery('[data-feedurl]').click(function(e){
                        e.preventDefault();
                        var feedAnchor = jQuery(this);
                        var feedurl = feedAnchor.data('feedurl');
                        jQuery('#RssFeedTitle').text(feedAnchor.html() + ' - ' + feedurl);
                        var options = {
                                limit: 50
                        }
                        jQuery('#RssFeedContainer').empty().rss(feedurl, options);
                });
        },

        registerFeedAdd: function() {
                jQuery('#RssFeedAdd').click(function(e){
                        var formTplClone = jQuery('#RssFeedAddFormTpl').clone().css({display: 'block'});
                        app.showModalWindow(formTplClone, function(){
                                var targetForm = jQuery('.RssFeedAddForm', formTplClone);
                                targetForm.validationEngine(app.validationEngineOptions);
                                targetForm.submit(function(){
                                        if (!targetForm.validationEngine('validate')) {
                                                return;
                                        }
                                        var params = 'module=MyRss&action=Save&';
                                        params += jQuery(targetForm).serialize();
                                        AppConnector.request(params).then(function(response){
                                                window.location.reload();
                                                //app.hideModalWindow();
                                        });
                                });
                        });
                });
        }

});

Distribution

You can achieve through Package Export API

Deployment

Go to Module Manager Import the module.

You can achieve through Package Import API