Table of Contents

Creating Your mooSocial First Plugin

NOTE: We’re currently working on documenting these sections. We believe the information here is accurate, however be aware we are also still working on this chapter. Additional information will be provided as we go which should make this chapter more solid.

Sample Plugin: https://www.moosocial.com//wiki/lib/plugins/ckgedit/fckeditor/userfiles/file/moo-note-1.0.zip

Welcome to the mooSocial guides

It is designed to start from the basics, and slowly increase to more sophisticated concepts until you know everything there is to know about building awesome mooSocial plugin .

mooSocial is built on CakePHP 2 framework and its plugins are designed base on CakePHP plugin so that you can set up a combination of controllers , models, and views and release them as a packaged .

Development Mode

To enable this setting, go to Home> System Admin> System Setting> Sytem Mode> Production Mode> Develelopment Mode

There are three modes:

Frontend

Creating a Plugin

How to create plugin

Let’s begin to create a Note plugin .In this tutorial we will be making a simple plugin that will let users write notes and save them as prefix_notes table on the mooSocial system for each mooSocial page . To start out, we need to create plugin by go to Home> Plugins Manager> Manage> Create New PLugin (See image) . This tutorial demonstrates how to create controller , model , view in mooSocial

Plugin Name , Key

The first task in creating a mooSocial Plugin is to think about what the plugin will do, and make a unique key for your plugin. Key only contains letters, numbers and the underscore '_' with no space

Example: ContactManager

Plugin Files

Basic directory structure

After that , our plugin’s basic directory structure should look like this:

info.xml

This file contains the standard plugin information .

PluginNamePlugin.php
Config/bootstrap.php

This file contains the configuration of your plugin .

Config/routes.php

This file contains your routers configuration plugin .

Note : Routing is a feature that maps URLs to controller actions . It will help plugins to make pretty URLs more configurable and flexible.

Config/install/install.sql

This file contains sql query strings that will be executed during installation proccess.

Config/install/uninstall.sql

This file contains sql query strings that will be executed during uninstallation proccess.

Config/install/upgrade.xml

This file contains sql query strings that will be executed during upgrade proccess.'

Creating Note Database

Execute the following SQL statements into your database

install.sql
CREATE TABLE IF NOT EXISTS {PREFIX}notes (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    user_id INT(11) NOT NULL,
    title VARCHAR(50),
    body TEXT,
    uri  VARCHAR(150),
    created DATETIME DEFAULT NULL,
    modified DATETIME DEFAULT NULL,
    like_count INT(11) DEFAULT '0',
    dislike_count INT(11) DEFAULT '0',
    comment_count INT(11) DEFAULT '0',
    FULLTEXT KEY title (title,body)
)ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
 
INSERT INTO {PREFIX}notes (user_id,title,body,created,modified,uri)
VALUES ('1', 'The title', 'This is the post body.', NOW(), NOW(),'uri_1'),
       ('1', 'A title once again', 'And the post body follows.', NOW(), NOW(),'uri_2'),
       ('1', 'Title strikes back', 'This is really exciting! Not.', NOW(), NOW(),'uri_3');
 
INSERT INTO `{PREFIX}tasks` (`title`, `plugin`, `timeout`, `processes`, `semaphore`, `started_last`, `started_count`, `completed_last`, `completed_count`, `failure_last`, `failure_count`, `success_last`, `success_count`, `enable`, `class`) VALUES
('Reminder', 'note', 300, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 'Note_Task_Reminder');

Create Note Model

Create a new model file Plugin/Note/Model/Note.php and copy the code below

Plugin model class files go in /app/Plugin/Note/Model/, and the file we’ll be creating will be saved to /app/Plugin/Note/Model/Note.php. The completed file should look like this:

/app/Plugin/Note/Model/Note.php
<?php
App::uses('NoteAppModel', 'Note.Model');
/**
 * Note Model
 *
 */
class Note extends NoteAppModel {
    public $mooFields = array('title','href','plugin','type','url');
 
    public $belongsTo = array( 'User' );
    public $validate = array(
        'title' => array(
            'rule' => 'notEmpty'
        ),
        'body' => array(
            'rule' => 'notEmpty'
        )
    );
 
    public $belongsTo = array( 'User'  => array('counterCache' => true ));
    public $mooFields = array('title','href','plugin','type');
    public function getHref($row)
    {
        if(isset($row['id']))
        {
            $request = Router::getRequest();
            return $request->base.'/notes/view/'.$row['id'];
        }
        return '';
    }
}

Naming conventions are very important in CakePHP. By naming our model Note, CakePHP can automatically infer that this model will be used in the NotesController, and will be tied to a database table called notes

CakePHP will dynamically create a model object for you if it cannot find a corresponding file in /app/Model. This also means that if you accidentally name your file wrong (for example, note.php or notes.php instead of Note.php), CakePHP will not recognize any of your settings and will use the defaults instead.

For more on models, such as table prefixes, callbacks, and validation , see http://book.cakephp.org/2.0/en/models.html

Create a Notes Controller

Next, we’ll create a controller for our notes. The controller is where all the business logic for notes interaction will happen . We will define functions : index , create , delete , update in NotesController . Users can access the logic there by requesting : mooSite/notes/index , mooSite/notes/create , mooSite/notes/delete , mooSite/notes/update .

We’ll place this new controller in a file called NotesController.php inside the /app/Plugin/Note/Controller directory. Here’s what the basic controller should look like:

/app/Plugin/Note/Controller/NotesControoler.php
<?php
class NotesController extends NoteAppController {
    /**
    * Scaffold
    *
    * @var mixed
    */
    public $scaffold;
    public function admin_index(){
    }
 
    public function index() {
        $this->set('notes', $this->Note->find('all'));
    }
 
    public function view($id = null) {
        if (!$id) {
            throw new NotFoundException(__d('Note', 'Invalid note'));
        }
        $note = $this->Note->findById($id);
        if (!$note) {
            throw new NotFoundException(__d('Note', 'Invalid note'));
        }
        $this->set('note', $note);
 
        $this->likesComments($id);
    }
 
    private function likesComments($id) {
        //comment
        $this->Comment = ClassRegistry::init('Comment');
        $comments = $this->Comment->getComments($id, 'Note_Note');
        $comment_count = $this->Comment->getCommentsCount($id, 'Note_Note');
        $page = 1;
 
        $data['bIsCommentloadMore'] = $comment_count - $page * RESULTS_LIMIT;
        $data['comments'] = $comments;
        $this->set('data', $data);
        $this->set('comment_count', $comment_count);
 
        //like
        $this->Like = ClassRegistry::init('Like');
        $likes = $this->Like->getLikes($id, 'Note_Note');
        $dislikes = $this->Like->getDisLikes($id, 'Note_Note');
 
        $this->set('likes', $likes);
        $this->set('dislikes', $dislikes);
    }
 
    public function add() {
        if ($this->request->is('post')) {
            $this->Note->create();
            $this->request->data['Note']['user_id'] = $this->Session->read('uid');
            if ($this->Note->save($this->request->data)) {
                $this->Session->setFlash(__d('Note', 'Your note has been saved.'));
                return $this->redirect(array('action' => 'index'));
            }
            $this->Session->setFlash(__d('Note', 'Unable to add your note.'));
        }
    }
 
    public function edit($id = null) {
        if (!$id) {
            throw new NotFoundException(__d('Note', 'Invalid note'));
        }
        $note = $this->Note->findById($id);
        if (!$note) {
            throw new NotFoundException(__d('Note', 'Invalid note'));
        }
        if ($this->request->is(array('post', 'put'))) {
            $this->Note->id = $id;
            $this->request->data['Note']['user_id'] = $this->Session->read('uid');
            if ($this->Note->save($this->request->data)) {
                $this->Session->setFlash(__d('Note', 'Your note has been updated.'));
                return $this->redirect(array('action' => 'index'));
            }
            $this->Session->setFlash(__d('Note', 'Unable to update your note.'));
        }
        if (!$this->request->data) {
            $this->request->data = $note;
        }
    }
 
    public function delete($id) {
        if (!$id) {
            throw new NotFoundException(__d('Note', 'Invalid note'));
        }
        if ($this->Note->delete($id)) {
            $this->Session->setFlash(
                __('The note with id: %s has been deleted.', h($id))
            );
            return $this->redirect(array('action' => 'index'));
        }
    }
}

The single instruction in the action uses set() to pass data from the controller to the view (which we’ll create next). The line sets the view variable called ‘notes’ equal to the return value of the find('all') method of the Note model. Our Note model is automatically available at $this→Note because we’ve followed CakePHP’s naming conventions.

Creating Views

CakePHP views are just presentation-flavored fragments that fit inside an application’s layout. For most applications, they’re HTML mixed with PHP, but they may end up as XML, CSV, or even binary data.

Note index view

<!-- File: /app/Plugin/Note/View/Notes/index.ctp -->
<!-- In case you want to create multiple themed views,  ex you want to  only
apply this view for default template , you can copy it to the folder: /app/View/Plugin/Note/Notes/index.ctp -->
<div class="col-md-s20">
    <div class="bar-content">
        <div class="content_center">
            <div class="mo_breadcrumb">
                <h1><?=__d('Note', 'Note posts'); ?></h1>
                <?php
                echo $this->Html->link(
                    __d('Note', 'Add Note'), array(
                        'controller' => 'notes',
                        'action' => 'add',
                    ), array('class' => 'button button-action topButton button-mobi-top')
                );
                ?>
            </div>
            <table class="table table-bordered">
                <tr>
                    <th class="col-md-sl1"><?=__d('Note', 'Id'); ?></th>
                    <th><?=__d('Note', 'Title'); ?></th>
                    <th class="col-md-sl2"><?=__d('Note', 'Created'); ?></th>
                    <th class="col-md-sl1"></th>
                </tr>
                <!-- Here is where we loop through our $posts array, printing out post info -->
                <?php foreach ($notes as $note): ?>
                    <tr>
                        <td><?php echo $note['Note']['id']; ?></td>
                        <td>
                            <?php echo $this->Html->link($note['Note']['title'], array(
                                'controller' => 'notes',
                                'action' => 'view',
                                $note['Note']['id']));
                            ?>
                        </td>
                        <td><?php echo $note['Note']['created']; ?></td>
                        <td>
                            <?php echo $this->Html->link(__d('Notes', 'Edit'), array(
                                'controller' => 'notes',
                                'action' => 'edit',
                                $note['Note']['id']
                            ));?> |
                            <?php echo $this->Html->link(__d('Notes', 'Delete'), array(
                                'controller' => 'notes',
                                'action' => 'delete',
                                $note['Note']['id']),
                                array(
                                    'confirm' => __d('Notes', 'Are you sure?')
                            ));?>
                        </td>
                    </tr>
                <?php endforeach; ?>
                <?php unset($note); ?>
            </table>
        </div>
    </div>
</div>

Note view

Now let’s create the view for our new ‘view’ action and place it in /app/Plugin/Note/View/Notes/view.ctp.

<!-- File: /app/Plugin/Note/Notes/view.ctp -->
<!-- In case you want to create multiple themed views,  ex you want to  only
apply this view for default template , you can copy it to the folder: /app/View/Plugin/Note/Notes/view.ctp -->
<div class="create_form">
    <div class="bar-content">
        <div class="content_center">
            <div class="box3">
                <div class="mo_breadcrumb">
                    <h1><?=h($note['Note']['title']);?></h1>
                    <?=$this->Html->link(
                        __d('Note', 'Manage Notes'), array(
                            'controller' => 'notes',
                            'action' => 'index',
                        ), array('class' => 'button button-action topButton button-mobi-top')
                    );
                    ?>
                    <?php echo $this->Html->link(__d('Notes', 'Edit'), array(
                        'controller' => 'notes',
                        'action' => 'edit',
                        $note['Note']['id']
                        ), array('class' => 'button button-action topButton button-mobi-top')
                    );?>
                </div>
                <p><small>Created: <?=$note['Note']['created']; ?></small></p>
                <p><?=h($note['Note']['body']); ?></p>
            </div>
        </div>
    </div>
    <div class="bar-content">
        <div class="content_center">
         <?php echo $this->element('likes', array('item' => $note['Note'], 'type' => $note['Note']['moo_type'])); ?>
        </div>
    </div>
    <div class="bar-content">
        <div class="content_center">
        <h2><?=__d('Note', 'Comments')?> (<span id="comment_count"><?=$comment_count?></span>)</h2>
        <ul class="list6 comment_wrapper" id="comments">
        <?php echo $this->element('comments');?>
        </ul>
        <?php echo $this->element( 'comment_form', array( 'target_id' => $note['Note']['id'], 'type' => $note['Note']['moo_type'] ) ); ?>
        </div>
    </div>
</div>

Verify that this is working by trying the links at http://yourdomainname/note/notes/index or manually requesting a post by accessing http://yourdomainname/note/notes/view/1

Add view

Create add view file in /app/Plugin/Note/View/Notes/add.ctp. Here’s our add view:

<!-- File: /app/Plugin/Note/View/Notes/add.ctp -->
<!-- In case you want to create multiple themed views,  ex you want to  only
apply this view for default template , you can copy it to the file : /app/View/Themed/Plugin/Note/Notes/add.ctp -->
<div class="create_form">
    <div class="bar-content">
        <div class="content_center">
            <div class="box3">
                <?=$this->Form->create('Note');?>
                <div class="mo_breadcrumb">
                    <h1><?=__d('Note', 'Add Note'); ?></h1>
                    <?php
                    echo $this->Html->link(
                        __d('Note', 'Manage Notes'), array(
                            'controller' => 'notes',
                            'action' => 'index',
                        ), array('class' => 'button button-action topButton button-mobi-top')
                    );
                    ?>
                </div>
                <div class="full_content p_m_10">
                    <div class="form_content">
                        <ul>
                            <li>
                                <div class="col-md-2">
                                    <label><?=__d('Note', 'Title');?></label>
                                </div>
                                <div class="col-md-10">
                                    <?=$this->Form->input('title', array(
                                        'label' => false,
                                        'div' => false
                                    ));?>
                                </div>
                                <div class="clear"></div>
                            </li>
                            <li>
                                <div class="col-md-2">
                                     <label><?=__d('Note', 'Body');?></label>
                                </div>
                                <div class="col-md-10">
                                    <?=$this->Form->input('body', array(
                                        'rows' => '3',
                                        'label' => false,
                                        'div' => false
                                    ));?>
                                </div>
                                <div class="clear"></div>
                            </li>
                            <li>
                                <div class="col-md-2">
                                     <label><?=__d('Note', 'Reminder');?></label>
                                </div>
                                <div class="col-md-10">
                                    <?=$this->Form->input('reminder', array(
                                        'label' => false,
                                        'div' => false
                                    ));?> <?php echo __d('Note','hours');?>
                                </div>
                                <div class="clear"></div>
                            </li>
                        </ul>
                        <div class="col-md-2"> </div>
                        <div class="col-md-10">
                            <?=$this->Form->end(array(
                                'label' => __d('Note', 'Save'),
                                'div' => false,
                                'class' => 'btn btn-action'
                            ));?>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

Editing view:

Create edit view file in /app/Plugin/Note/View/Notes/edit.ctp. Here’s what the edit view of the NotesController would look like:

<!-- File: /app/Plugin/Note/View/Notes/edit.ctp -->
<!-- In case you want to create multiple themed views,  ex you want to  only
apply this view for default template , you can copy it to the file : /app/View/Themed/Plugin/Note/Notes/edit.ctp -->
<div class="create_form">
    <div class="bar-content">
        <div class="content_center">
            <div class="box3">
                <?=$this->Form->create('Note');?>
                <?=$this->Form->input('id', array('type' => 'hidden'));?>
                <div class="mo_breadcrumb">
                    <h1><?=__d('Note', 'Edit Note'); ?></h1>
                    <?php
                    echo $this->Html->link(
                        __d('Note', 'Manage Notes'), array(
                            'controller' => 'notes',
                            'action' => 'index',
                        ), array('class' => 'button button-action topButton button-mobi-top')
                    );
                    ?>
                </div>
                <div class="full_content p_m_10">
                    <div class="form_content">
                        <ul>
                            <li>
                                <div class="col-md-2">
                                    <label><?=__d('Note', 'Title');?></label>
                                </div>
                                <div class="col-md-10">
                                    <?=$this->Form->input('title', array(
                                        'label' => false,
                                        'div' => false
                                    ));?>
                                </div>
                                <div class="clear"></div>
                            </li>
                            <li>
                                <div class="col-md-2">
                                     <label><?=__d('Note', 'Body');?></label>
                                </div>
                                <div class="col-md-10">
                                    <?=$this->Form->input('body', array(
                                        'rows' => '3',
                                        'label' => false,
                                        'div' => false
                                    ));?>
                                </div>
                                <div class="clear"></div>
                            </li>
                        </ul>
                        <div class="col-md-2"> </div>
                        <div class="col-md-10">
                            <?=$this->Form->end(array(
                                'label' => __d('Note', 'Save'),
                                'div' => false,
                                'class' => 'btn btn-action'
                            ));?>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

To see result, go to url http://domainname/notes

Creating a widget

Widgets were originally designed to provide a simple and easy-to-use way of giving design and structure control of the mooSocial Theme to the user, which is now available on properly “widgetized” mooSocial Themes to include the content in the mooSocial design and structure. Widgets require no code experience or expertise. They can be added, removed, and rearranged on the mooSocial Administration Site Manager> Themes Manager> Layout Editor panel.

Create an action

Controller actions are responsible for converting the request parameters into a response for the browser/user making the request. MooSocial uses conventions to automate this process and remove some boilerplate code you would otherwise need to write.

Update /app/Plugin/Note/Controller/noteController.php like this

<?php
class NotesController extends NoteAppController {
    /**
    * Scaffold
    *
    * @var mixed
    */
    public $scaffold;
    public function admin_index(){
 
    }
 
    public function admin_infos(){
        // get plugin info
        $xmlPath = sprintf(PLUGIN_INFO_PATH, 'Note');
        if(file_exists($xmlPath))
        {
            $content = file_get_contents($xmlPath);
            $info = new SimpleXMLElement($content);
            $this->set('info', $info);
        }
        else
        {
            $this->set('info', null);
        }
    }
 
    public function index() {
        $this->set('notes', $this->Note->find('all'));
    }
 
    public function view($id = null) {
        if (!$id) {
            throw new NotFoundException(__d('Note', 'Invalid note'));
        }
        $note = $this->Note->findById($id);
        if (!$note) {
            throw new NotFoundException(__d('Note', 'Invalid note'));
        }
        $this->set('note', $note);
 
        $this->likesComments($id);
    }
 
    private function likesComments($id) {
        //comment
        $this->Comment = ClassRegistry::init('Comment');
        $comments = $this->Comment->getComments($id, 'Note_Note');
        $comment_count = $this->Comment->getCommentsCount($id, 'Note_Note');
        $page = 1;
 
        $data['bIsCommentloadMore'] = $comment_count - $page * RESULTS_LIMIT;
        $data['comments'] = $comments;
        $this->set('data', $data);
        $this->set('comment_count', $comment_count);
 
        //like
        $this->Like = ClassRegistry::init('Like');
        $likes = $this->Like->getLikes($id, 'Note_Note');
        $dislikes = $this->Like->getDisLikes($id, 'Note_Note');
 
        $this->set('likes', $likes);
        $this->set('dislikes', $dislikes);
    }
 
    public function add() {
        if ($this->request->is('post')) {
            $this->Note->create();
            $this->request->data['Note']['user_id'] = $this->Session->read('uid');
            if ($this->Note->save($this->request->data)) {
                $this->Session->setFlash(__d('Note', 'Your note has been saved.'));
                return $this->redirect(array('action' => 'index'));
            }
            $this->Session->setFlash(__d('Note', 'Unable to add your note.'));
        }
    }
 
    public function edit($id = null) {
        if (!$id) {
            throw new NotFoundException(__d('Note', 'Invalid note'));
        }
        $note = $this->Note->findById($id);
        if (!$note) {
            throw new NotFoundException(__d('Note', 'Invalid note'));
        }
        if ($this->request->is(array('post', 'put'))) {
            $this->Note->id = $id;
            $this->request->data['Note']['user_id'] = $this->Session->read('uid');
            if ($this->Note->save($this->request->data)) {
                $this->Session->setFlash(__d('Note', 'Your note has been updated.'));
                return $this->redirect(array('action' => 'index'));
            }
            $this->Session->setFlash(__d('Note', 'Unable to update your note.'));
        }
        if (!$this->request->data) {
            $this->request->data = $note;
        }
    }
 
    public function delete($id) {
        if (!$id) {
            throw new NotFoundException(__d('Note', 'Invalid note'));
        }
        if ($this->Note->delete($id)) {
            $this->Session->setFlash(
                __('The note with id: %s has been deleted.', h($id))
            );
            return $this->redirect(array('action' => 'index'));
        }
    }
 
    public function myNotes(){
        $notes = $this->Note->find('all', array(
            'conditions' => array('uri' => $this->request->uri),
            'limit' => 1,
            'order' => array('Note.id' => 'DESC')
        ));
        return $notes;
    }
 
    public function ajax_add(){
 
        if ($this->request->is('post')) {
            $this->Note->create();
            $this->request->data['Note']['user_id'] = $this->Session->read('uid');
            if ($this->Note->save($this->request->data)) {
                $note = $this->Note->findById($this->Note->getLastInsertId());
                echo json_encode(array('result' => $note));
                exit;
            }
            echo json_encode(array('error' => _d("Note", "Something went wrong! Please try again.")));
            exit;
        }
    }
}

Create an element

Many applications have small blocks of presentation code that need to be repeated from page to page, sometimes in different places in the layout. MooSocial can help you repeat parts of your website that need to be reused. These reusable parts are called Elements. Ads, help boxes, navigational controls, extra menus, login forms, and callouts are often implemented in MooSocial as elements. An element is basically a mini-view that can be included in other views, in layouts, and even within other elements. Elements can be used to make a view more readable, placing the rendering of repeating elements in its own file. They can also help you re-use content fragments in your application.

Create new ctp file in /app/Plugin/Note/View/Elements/myNotes.ctp

New in version 2.2.1> Your ctp file must be place at /app/Plugin/{plugin_name}/View/Widgets/ instead of /app/Plugin/{plugin}/View/Elements/
myNotes.ctp
<?php $notes = $this->requestAction(array('plugin' => 'Note', 'controller' => 'notes', 'action' => 'myNotes'), array('uri' => $this->here));?>
<div class="box2 search-friend">
    <h3><?=__d('Note', 'My Note');?></h3>
    <div class="box_content">
        <div id="newNote">
            <?php if($notes != null): ?>
                <?=$notes[0]['Note']['body'];?>
            <?php else:?>
                <?=__d('Note', 'No notes found');?>
            <?php endif;?>
        </div>
    </div>
    <h3><?=__d('Note', 'Add Note');?></h3>
    <div class="box_content">
        <?=$this->Form->create('Note');?>
        <?=$this->Form->input('uri', array(
            'value' => $this->here,
            'label' => false,
            'div' => false,
            'type' => 'hidden'
        ));?>
        <ul class="list6">
            <li>
                <label><?=__d('Note', 'Title');?></label>
                <?=$this->Form->input('title', array(
                    'label' => false,
                    'div' => false
                ));?>
            </li>
            <li>
                <label><?=__d('Note', 'Body');?></label>
                <?=$this->Form->input('body', array(
                    'rows' => '3',
                    'label' => false,
                    'div' => false,
                    'style' => 'overflow: hidden;width: 100%;'
                ));?>
            </li>
        </ul>
        <?=$this->Form->end(array(
            'label' => __d('Note', 'Add'),
            'div' => false,
            'class' => 'btn btn-action',
            'id' => 'btnAddNote'
        ));?>
        <div class="clear"></div>
    </div>
</div>
<?php $this->Html->scriptStart(array('inline' => false)); ?>
//<![CDATA[
$(document).ready(function()
{
    $(window).load(function(){
        $("#NoteIndexForm")[0].reset();
    })
 
    $("#NoteIndexForm").submit(function(e){
        e.preventDefault();
        $.post('/notes/ajax_add/', $("#NoteIndexForm").serialize(), function(data){
            data = jQuery.parseJSON(data);
            if(data.result)
            {
                $("#newNote").empty().append(data.result.Note.body);
            }
            else
            {
                $("#newNote").empty().append(data.error);
            }
            $("#NoteIndexForm")[0].reset();
        });
    })
});
//]]>
<?php $this->Html->scriptEnd(); ?>
New in version 2.2.1> You don't have to use $this→requestAction() method to get the need variables anymore e.g: <?php $notes = $this→requestAction(array('plugin' ⇒ 'Note', 'controller' ⇒ 'notes', 'action' ⇒ 'myNotes'), array('uri' ⇒ $this→here));?>. Instead, create a file in app/Plugin/{plugin_name}/Controller/Widgets/{your_element_name}Widget.php, for example: app/Plugin/Note/Controller/Widgets/myNotesWidget.php with the content like the below code:
myNotesWidget.ctp
<?php
App::uses('Widget','Controller/Widgets');
class MyNotesWidget extends Widget {
    public function beforeRender(Controller $controller) {
        $this->Note = MooCore::getInstance()->getModel('Note');
        $notes = $this->Note->find('all', array(
            'conditions' => array('uri' => $controller->request->here),
            'limit' => 1,
            'order' => array('Note.id' => 'DESC')
        ));
        $controller->set('notes',$notes);
    }

Create widget database

INSERT INTO {PREFIX}core_blocks(name, path_view,params,is_active)
VALUES('My Notes', 'myNotes','[{"label":"Title","input":"text","value":"My Notes","name":"title"},{"label":"plugin","input":"hidden","value":"Note","name":"plugin"}]',1)

How to use widget

Backend

How to create plugin tabs

NotesController.php
<?php
class NotesController extends NoteAppController {
    /**
    * Scaffold
    *
    * @var mixed
    */
    public $scaffold;
    public function admin_index(){
 
    }
 
    public function admin_infos(){
        // get plugin info
        $xmlPath = sprintf(PLUGIN_INFO_PATH, 'Note');
        if(file_exists($xmlPath))
        {
            $content = file_get_contents($xmlPath);
            $info = new SimpleXMLElement($content);
            $this->set('info', $info);
        }
        else
        {
            $this->set('info', null);
        }
    }
 
    public function index() {
        $this->set('notes', $this->Note->find('all'));
    }
 
    public function view($id = null) {
        if (!$id) {
            throw new NotFoundException(__d('Note', 'Invalid note'));
        }
        $note = $this->Note->findById($id);
        if (!$note) {
            throw new NotFoundException(__d('Note', 'Invalid note'));
        }
        $this->set('note', $note);
 
        $this->likesComments($id);
    }
 
    private function likesComments($id) {
        //comment
        $this->Comment = ClassRegistry::init('Comment');
        $comments = $this->Comment->getComments($id, 'Note_Note');
        $comment_count = $this->Comment->getCommentsCount($id, 'Note_Note');
        $page = 1;
 
        $data['bIsCommentloadMore'] = $comment_count - $page * RESULTS_LIMIT;
        $data['comments'] = $comments;
        $this->set('data', $data);
        $this->set('comment_count', $comment_count);
 
        //like
        $this->Like = ClassRegistry::init('Like');
        $likes = $this->Like->getLikes($id, 'Note_Note');
        $dislikes = $this->Like->getDisLikes($id, 'Note_Note');
 
        $this->set('likes', $likes);
        $this->set('dislikes', $dislikes);
    }
 
    public function add() {
        if ($this->request->is('post')) {
            $this->Note->create();
            $this->request->data['Note']['user_id'] = $this->Session->read('uid');
            if ($this->Note->save($this->request->data)) {
                $this->Session->setFlash(__d('Note', 'Your note has been saved.'));
                return $this->redirect(array('action' => 'index'));
            }
            $this->Session->setFlash(__d('Note', 'Unable to add your note.'));
        }
    }
 
    public function edit($id = null) {
        if (!$id) {
            throw new NotFoundException(__d('Note', 'Invalid note'));
        }
        $note = $this->Note->findById($id);
        if (!$note) {
            throw new NotFoundException(__d('Note', 'Invalid note'));
        }
        if ($this->request->is(array('post', 'put'))) {
            $this->Note->id = $id;
            $this->request->data['Note']['user_id'] = $this->Session->read('uid');
            if ($this->Note->save($this->request->data)) {
                $this->Session->setFlash(__d('Note', 'Your note has been updated.'));
                return $this->redirect(array('action' => 'index'));
            }
            $this->Session->setFlash(__d('Note', 'Unable to update your note.'));
        }
        if (!$this->request->data) {
            $this->request->data = $note;
        }
    }
 
    public function delete($id) {
        if (!$id) {
            throw new NotFoundException(__d('Note', 'Invalid note'));
        }
        if ($this->Note->delete($id)) {
            $this->Session->setFlash(
                __('The note with id: %s has been deleted.', h($id))
            );
            return $this->redirect(array('action' => 'index'));
        }
    }
 
    public function myNotes(){
        $notes = $this->Note->find('all', array(
            'conditions' => array('uri' => $this->request->uri),
            'limit' => 1,
            'order' => array('Note.id' => 'DESC')
        ));
        return $notes;
    }
 
    public function ajax_add(){
 
        if ($this->request->is('post')) {
            $this->Note->create();
            $this->request->data['Note']['user_id'] = $this->Session->read('uid');
            if ($this->Note->save($this->request->data)) {
                $note = $this->Note->findById($this->Note->getLastInsertId());
                echo json_encode(array('result' => $note));
                exit;
            }
            echo json_encode(array('error' => _d("Note", "Something went wrong! Please try again.")));
            exit;
        }
    }
}

Create admin_infos.ctp in /app/Plugin/Note/View/Notes/

admininfos.ctp
<?php
echo $this->Html->css(array('jquery-ui', 'footable.core.min'), null, array('inline' => false));
echo $this->Html->script(array('jquery-ui', 'footable'), array('inline' => false));
$this->startIfEmpty('sidebar-menu');
echo $this->element('admin/adminnav', array('cmenu' => 'Note'));
$this->end();
?>
<?= $this->Moo->renderMenu('Note', 'Infos'); ?>
<?php if(isset($info) && $info != null):?>
<div class="form-group">
    <label class="control-label col-md-3">Name:</label>
    <div class="col-md-9">
        <p class="form-control-static">
            <?=$info->name;?>
        </p>
    </div>
</div>
<div class="form-group">
    <label class="control-label col-md-3">Key:</label>
    <div class="col-md-9">
        <p class="form-control-static">
            <?=$info->name;?>
        </p>
    </div>
</div>
<div class="form-group">
    <label class="control-label col-md-3">Version:</label>
    <div class="col-md-9">
        <p class="form-control-static">
            <?=$info->version;?>
        </p>
    </div>
</div>
<div class="form-group">
    <label class="control-label col-md-3">Author:</label>
    <div class="col-md-9">
        <p class="form-control-static">
            <?=$info->author;?>
        </p>
    </div>
</div>
<div class="form-group">
    <label class="control-label col-md-3">Website:</label>
    <div class="col-md-9">
        <p class="form-control-static">
            <?=$info->website;?>
        </p>
    </div>
</div>
<div class="form-group">
    <label class="control-label col-md-3">Description:</label>
    <div class="col-md-9">
        <p class="form-control-static">
            <?=$info->description;?>
        </p>
    </div>
</div>
<?php endif;?>
NotePlugin.php
<?php
App::uses('MooPlugin','Lib');
class NotePlugin implements MooPlugin{
    public function install(){}
    public function uninstall(){}
    public function settingGuide(){}
    public function menu()
    {
        return array(
            'General' => array('plugin' => 'note', 'controller' => 'notes', 'action' => 'admin_index'),
            'Settings' => array('plugin' => 'note', 'controller' => 'note_settings', 'action' => 'admin_index'),
            'Infos' => array('plugin' => 'note', 'controller' => 'notes', 'action' => 'admin_infos'),
        );
    }
    /*
    Example for version 1.0: This function will be executed when plugin is upgraded (Optional)
    public function callback_1_0(){}
    */
}

To see the result go to Home> Plugins Manager> Note, select table Infos.

How to add and display plugin settings

NoteSettingsController.php
<?php
class NoteSettingsController extends NoteAppController{
    public $components = array('QuickSettings');
    public function admin_index($id = null)
    {
        $this->QuickSettings->run($this, array("Note"), $id);
    }
}
NoteSettings/admin_index.php
<?php
    echo $this->Html->css(array('jquery-ui', 'footable.core.min'), null, array('inline' => false));
    echo $this->Html->script(array('jquery-ui', 'footable'), array('inline' => false));
    $this->startIfEmpty('sidebar-menu');
    echo $this->element('admin/adminnav', array('cmenu' => 'Note'));
    $this->end();
?>
<div class="portlet-body form">
    <div class=" portlet-tabs">
        <div class="tabbable tabbable-custom boxless tabbable-reversed">
            <?=$this->Moo->renderMenu('Note', 'Settings');?>
            <div class="row" style="padding-top: 10px;">
                <div class="col-md-12">
                    <div class="tab-content">
                        <div class="tab-pane active" id="portlet_tab1">
                            <?=$this->element('admin/setting');?>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

What is boot setting?

In mooSocial, settings will be loaded 2 times: App load and plugin load. So, boot settings are loaded in the first.

Why do we distinguish it? Because each plugin can have so many settings and if we always load all settings, performance becomes slow but not really necessary.

How to create a boot setting? After we have created a setting, it was saved in 'settings' table. We just set '1' value for 'is_boot' field.

Which case do we need? In common, almost plugin settings needn't a boot setting, but some still have one such as 'enabled' setting which makes us know whether user can access that plugin or not. Why do we need a boot setting? Because when we want to block access, we need to check enable or not in 'routes.php' file of plugin; And importantly, 'routes.php' file is loaded before the system loads unboot settings, so if we don't make 'enabled' setting by boot, we can't check it (because that setting doesn't exist at that time).

New in version 2.2 > In version 2.2, the “{plugin}_enabled” setting have “is_boot” field is '1' by default when you created a new plugin

Create boot setting

To create a boot setting, we have 5 steps:

  1. Create a setting in system settings page.
  2. Open 'settings' table in your database, find the last setting.
  3. Set '1' value for 'is_boot' field.
  4. Go to plugin settings page and save (because after save, 'settings.php' file will be created again).
  5. Check 'app/Config/settings.php' file in your project, if that setting existed in, you would succeed.

How to add setting guide

NotePlugin.php
<?php
App::uses('MooPlugin','Lib');
class NotePlugin implements MooPlugin{
    public function install(){}
    public function uninstall(){}
    public function settingGuide(){
        return "This is an example for settingGuide";
    }
    public function menu()
    {
        return array(
            'General' => array('plugin' => 'note', 'controller' => 'notes', 'action' => 'admin_index'),
            'Settings' => array('plugin' => 'note', 'controller' => 'note_settings', 'action' => 'admin_index'),
            'Infos' => array('plugin' => 'note', 'controller' => 'notes', 'action' => 'admin_infos'),
        );
    }
    /*
    Example for version 1.0: This function will be executed when plugin is upgraded (Optional)
    public function callback_1_0(){}
    */
}

Intergration

Events system

Create listener

NoteListener.php
<?php
App::uses('CakeEventListener', 'Event');
class NoteListener implements CakeEventListener
{
    public function implementedEvents()
    {
        return array(
            'Controller.Search.search' => 'search',
            'Controller.Search.suggestion' => 'suggestion',
    );
    }
    public function search($event)
    {
        $e = $event->subject();
        App::import('Model', 'Note.Note');
        $this->Note = new Note();
        $results = $this->Note->search($e->keyword);
        if(isset($e->plugin) && $e->plugin == 'Note')
        {
            $e->set('notes', $results);
            $e->render("Note.Elements/lists/notes_list");
        }
        else
        {
            $event->result['Note']['header'] = "Notes";
            $event->result['Note']['icon_class'] = "icon-group";
            $event->result['Note']['view'] = "lists/notes_list";
            $e->set('notes', $results);
        }
    }
 
    public function suggestion($event)
    {
        $e = $event->subject();
        App::import('Model', 'Note.Note');
        $this->Note = new Note();
        //search with filter
        if(isset($event->data['type']) && $event->data['type'] == 'note')
        {
            $notes = $this->Note->search($e->keyword);
 
            $e->set('notes', $notes);
            $e->set('result',1);
            $e->set('element_list_path',"lists/notes_list");
        }
        //search all
        if(isset($event->data['type']) && $event->data['type'] == 'all')
        {
            $event->result['note'] = null;
            $notes = $this->Note->search($e->keyword);
            if(!empty($notes)){
                foreach($notes as $index=>&$detail){
                    $event->result['note'][$index]['id'] = $detail['Note']['id'];//required
                    if(!empty($detail['Note']['thumb']))
                        $event->result['note'][$index]['img'] = 'notes/'.$detail['Note']['thumb'];//the path to the thumbnail in 'uploads' folder
                    $event->result['note'][$index]['title'] = $detail['Note']['title']; //(required)
                    $event->result['note'][$index]['find_name'] = 'Find Notes'; //(required)
                    $event->result['note'][$index]['icon_class'] = 'icon-edit'; // icon of the note(required)
                    $event->result['note'][$index]['view_link'] = 'videos/view/';// link to controller action when users click on suggestion results(required)
                }
            }
        }
    }
 }

Note: the event name must be “Controller.Search.search” and “Controller.Search.suggestion”.

notes_list.ctp
<ul class="list6 comment_wrapper">
<?php if($notes != null):?>
    <?php foreach ($notes as $note):?>
        <li class="full_content p_m_10">
            <div>
                <a class="title" href="<?= $this->request->base ?>/notes/view/<?= $note['Note']['id'] ?>/<?= seoUrl($note['Note']['title']) ?>"><b><?= h($note['Note']['title']) ?></b></a>
                <div class="comment_message">
                    <div>
                        <?php
                        echo $this->Text->truncate(strip_tags(str_replace(array('<br>', ' '), array(' ', ''), $note['Note']['body'])), 150, array('exact' => false));
                        ?>
                    </div>
                </div>
                <div class="date date-small">
                    <?= __d('Note', 'Posted by') ?> <?= $this->Moo->getName($note['User'], false) ?>
                    <?= $this->Moo->getTime($note['Note']['created'], Configure::read('core.date_format'), $utz) ?> . <a href="<?= $this->request->base ?>/notes/view/<?= $note['Note']['id'] ?>/<?= seoUrl($note['Note']['title']) ?>"><?= __d('Note', 'Read more') ?></a>
                </div>
            </div>
        </li>
    <?php endforeach;?>
<?php else:?>
    <div align="center"><?=__d('Note', 'No more results found');?></div>
<?php endif;?>
</ul>

Note.php

<?php
App::uses('NoteAppModel', 'Note.Model');
/**
 * Note Model
 *
 */
class Note extends NoteAppModel {
    public $validate = array(
        'title' => array(
            'rule' => 'notEmpty'
        ),
        'body' => array(
            'rule' => 'notEmpty'
        )
    );
 
    public $belongsTo = array( 'User'  => array('counterCache' => true ));
    public $mooFields = array('title','href','plugin','type');
    public function getHref($row)
    {
        if(isset($row['id']))
        {
            $request = Router::getRequest();
            return $request->base.'/notes/view/'.$row['id'];
        }
        return '';
    }
 
    public function search($keyword)
    {
        $cond = array( 'MATCH(Note.title, Note.body) AGAINST(? IN BOOLEAN MODE)' => urldecode($keyword));
        $notes = $this->find( 'all', array( 'conditions' => $cond, 'limit' => RESULTS_LIMIT, 'page' => 1 ) );
        return $notes;
    }
}
bootstrap.php
<?php
App::uses('NoteListener', 'Note.Lib');
CakeEventManager::instance()->attach(new NoteListener());

How to integrate the Note plugin in mooSocial activity feed

/app/Plugin/Note/Model/Note.php
<?php
App::uses('NoteAppModel', 'Note.Model');
/**
 * Note Model
 *
 */
class Note extends NoteAppModel {
    public $validate = array(
        'title' => array(
            'rule' => 'notEmpty'
        ),
        'body' => array(
            'rule' => 'notEmpty'
        )
    );
 
    public $belongsTo = array( 'User'  => array('counterCache' => true ));
    public $mooFields = array('title','href','plugin','type');
    public function getHref($row)
    {
        if(isset($row['id']))
        {
            $request = Router::getRequest();
            return $request->base.'/notes/view/'.$row['id'];
        }
        return '';
    }
 
    public function search($keyword)
    {
        $cond = array( 'MATCH(Note.title, Note.body) AGAINST(? IN BOOLEAN MODE)' => urldecode($keyword));
        $notes = $this->find( 'all', array( 'conditions' => $cond, 'limit' => RESULTS_LIMIT, 'page' => 1 ) );
        return $notes;
    }
 
    public $actsAs = array(
        'Activity' => array(
            'type' => APP_USER,
            'action_afterCreated'=>'note_feed',
            'item_type'=>'Note_Note',
            'query'=>1,
            'params' => 'item'
        ),
    );
}

content/note_feed.ctp
<div class="">
    <!-- end blog thumbnail -->
    <div class="activity_right ">
        <div class="activity_header">
            <a href="<?=$activity['Content']['Note']['moo_href']?>">
                <b><?=h($activity['Content']['Note']['moo_title'])?></b>
            </a>
        </div>
    <?=$this->Text->truncate( strip_tags( str_replace( array('<br>',' '), array(' ',''), $activity['Content']['Note']['body'] ) ), 160 , array('exact' => false))?>
    </div>
    <div class="clear"></div>
</div>
text/note_feed
<?php
echo __('created a new note');

How to export plugin

/app/Plugin/Note/Config/install/install.sql
CREATE TABLE IF NOT EXISTS {PREFIX}notes (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    user_id INT(11) NOT NULL,
    title VARCHAR(50),
    body TEXT,
    uri  VARCHAR(150),
    created DATETIME DEFAULT NULL,
    modified DATETIME DEFAULT NULL,
    like_count INT(11) DEFAULT '0',
    dislike_count INT(11) DEFAULT '0',
    comment_count INT(11) DEFAULT '0',
    FULLTEXT KEY title (title,body)
)ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
 
INSERT INTO {PREFIX}notes (user_id,title,body,created,modified,uri)
VALUES ('1', 'The title', 'This is the post body.', NOW(), NOW(),'uri_1'),
       ('1', 'A title once again', 'And the post body follows.', NOW(), NOW(),'uri_2'),
       ('1', 'Title strikes back', 'This is really exciting! Not.', NOW(), NOW(),'uri_3');
 
INSERT INTO core_blocks(name, path_view,params,is_active)
VALUES('My Notes', 'myNotes','[{"label":"Title","input":"text","value":"MyNotes","name":"title"},{"label":"plugin","input":"hidden","value":"Note","name":"plugin"}]',1);
Copy SQL to /app/Plugin/Note/Config/install/uninstall.sql
DROP TABLE IF EXISTS {PREFIX}notes;
DELETE FROM {PREFIX}core_blocks WHERE path_view = 'myNotes';
DELETE FROM {PREFIX}core_contents WHERE name = 'myNotes';
DELETE FROM {PREFIX}activities WHERE action = 'note_feed';

How to uninstall plugin

Create plugin informations: Read plugin informations from YourPlugin/info.xml and store into database.

Create plugin settings (Optional): Read setting informations from YourPlugin/info.xml and store into database.

Install database (Optional): execute sql query in YourPlugin/Config/install/install.txt (sql query maybe: create new table, insert new widget etc).

Execute install function (Optional): execute install function from YourPlugin/plugin.php

How to install plugin

Create plugin informations: Read plugin informations from YourPlugin/info.xml and store into database.

Create plugin settings (Optional): Read setting informations from YourPlugin/info.xml and store into database.

Install database (Optional): execute sql query in YourPlugin/Config/install/install.txt (sql query maybe: create new table, insert new widget etc).

Execute install function (Optional): execute install function from YourPlugin/plugin.php

How to upgrade plugin

Create upgrade version

info.xml
<?xml version="1.0" encoding="utf-8"?>
<info>
    <name>Note</name>
    <key>Note</key>
    <version>2.0</version>
    <description>Let's begin to a Note plugin</description>
    <author>MooTechnicalTeam</author>
    <website>http://community.socialloft.com/users/view/133</website>
    <bootstrap>1</bootstrap>
    <routes>1</routes>
</info>
/app/Plugin/Note/Config/install/upgrade.xml
<?xml version="1.0" encoding="utf-8"?>
<versions>
    <version>
        <number>2.0</number>
        <queries>
        <query>
            INSERT INTO {PREFIX}notes (user_id,title,body,created,modified,uri)
            VALUES ('1', 'The title 2.0', 'This is the post body.', NOW(), NOW(),'uri_4');
        </query>
            <query>
            INSERT INTO {PREFIX}notes (user_id,title,body,created,modified,uri)
            VALUES ('1', 'The title 2.0', 'This is the post body.', NOW(), NOW(),'uri_5');
        </query>
        </queries>
    </version>
</versions>

Note: You must implement new sql query into /app/Plugin/Note/Config/install/install.sql

Upgrade plugin

Install database (Optional): execute sql query in YourPlugin/Config/install/upgrade.xml (sql query maybe: create new table, insert new widget etc).

Execute extended functions (Optional): base on version number, process will execute function named like callback_1_0 in YourPlugin/plugin.php.

Internationalizing Your Plugin

How to create a task

Insert to install.sql

INSERT INTO `{PREFIX}tasks` (`title`, `plugin`, `timeout`, `processes`, `semaphore`, `started_last`, `started_count`, `completed_last`, `completed_count`, `failure_last`, `failure_count`, `success_last`, `success_count`, `enable`, `class`) VALUES\\
('Reminder', 'note', 300, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 'Note_Task_Reminder');

Insert to uninstall.sql

DELETE FROM {PREFIX}tasks\\
WHERE `class` = 'Note_Task_Reminder';

Create NoteTaskReminder.php in /app/Plugin/Note/Task/

<?php
App::import('Cron.Task','CronTaskAbstract');
class NoteTaskReminder extends CronTaskAbstract
{
    public function execute()
    {
        $noteModel = MooCore::getInstance()->getModel('Note_Note');
        $notes = $noteModel->find('all',array('conditions'=>array(
            'check_reminder' => false,
            'reminder>' => 0,
            '(UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(Note.created)> Note.reminder * 3600)'
        )));
 
        if (count($notes))
        {
            $mailComponent = MooCore::getInstance()->getComponent('Mail.MooMail');
            $ssl_mode = Configure::read('core.ssl_mode');
            $http = (!empty($ssl_mode)) ? 'https' :  'http';
            foreach ($notes as $note)
            {
                $mailComponent->send($note['Note']['user_id'],'note_reminder',
                    array(
                        'note_name' => $note['Note']['moo_title'],
                        'note_link' => $http.'://'.$_SERVER['SERVER_NAME'].$note['Note']['moo_href'],
                    )
                );
 
                $noteModel->id = $note['Note']['id'];
                $noteModel->save(array('check_reminder'=>true));
            }
        }
    }
}

How to using mailsystem

Insert to NotePlugin.php on function install and uninstall

public function install(){
        $mailModel = MooCore::getInstance()->getModel('Mail_Mailtemplate');
        $languageModel = MooCore::getInstance()->getModel('Language');
        $langs = $languageModel->find('all');
        $data['Mailtemplate'] = array(
            'type' => 'note_reminder',
            'plugin' => 'Note',
            'vars' => '[note_name],[note_link]'
        );
        $mailModel->save($data);
        $id = $mailModel->id;
        foreach ($langs as $lang)
        {
            $language = $lang['Language']['key'];
            $mailModel->locale = $language;
            $data_translate['subject'] = 'Note reminder';
            $content = <<<EOF
    <p>[header]</p>
    <p>This is mail reminder : <a href="[note_link]">[note_name]</a></p>
    <p>[footer]</p>
EOF;
            $data_translate['content'] = $content;
            $mailModel->save($data_translate);
        }
    }
    public function uninstall(){
        $mailModel = MooCore::getInstance()->getModel('Mail_Mailtemplate');
        $mailModel->deleteAll(array('Mailtemplate.type'=>'note_reminder'),true,true);
    }

How to using it $mailComponent→send($mix,$type,$params) $mix: email or $user_id or model user, $type: type of email, $params: param for mail type.

$noteModel = MooCore::getInstance()->getModel('Note_Note');
        $notes = $noteModel->find('all',array('conditions'=>array(
            'check_reminder' => false,
            'reminder>' => 0,
            '(UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(Note.created)> Note.reminder * 3600)'
        )));
 
        if (count($notes))
        {
            $mailComponent = MooCore::getInstance()->getComponent('Mail.MooMail');
            $ssl_mode = Configure::read('core.ssl_mode');
            $http = (!empty($ssl_mode)) ? 'https' :  'http';
            foreach ($notes as $note)
            {
                $mailComponent->send($note['Note']['user_id'],'note_reminder',
                    array(
                        'note_name' => $note['Note']['moo_title'],
                        'note_link' => $http.'://'.$_SERVER['SERVER_NAME'].$note['Note']['moo_href'],
                    )
                );
 
                $noteModel->id = $note['Note']['id'];
                $noteModel->save(array('check_reminder'=>true));
            }
        }

How to using tag system

When create a note:

NotesController.php
if ($this->Note->save($this->request->data)) {
        //Tag system
    $this->loadModel('Tag');
    $this->Tag->saveTags($this->request->data['Note']['tags'], $this->Note->id, 'Note_Note');
    //
 
    $this->Session->setFlash(__d('Note', 'Your note has been saved.'));
    return $this->redirect(array('action' => 'index'));
}
add.ctp
//Tag system
<div class="col-md-2">
        <label><?=__d('Note', 'Tags')?></label>
    </div>
    <div class="col-md-10">
        <?php echo $this->Form->text('tags'); ?> <a href="javascript:void(0)" class="tip profile-tip" title="<?=__d('Note', 'Separated by commas')?>">(?)</a>
    </div>
    <div class="clear"></div>
</li>
//

When edit a note: NotesController.php

if ($this->request->is(array('post', 'put'))) {
    $this->Note->id = $id;
    $this->request->data['Note']['user_id'] = $this->Session->read('uid');
    if ($this->Note->save($this->request->data)) {
                //Tag system
        $this->Tag->saveTags($this->request->data['Note']['tags'], $id, 'Note_Note');
        //
 
        $this->Session->setFlash(__d('Note', 'Your note has been updated.'));
        return $this->redirect(array('action' => 'index'));
    }
    $this->Session->setFlash(__d('Note', 'Unable to update your note.'));
}
//Tag system
$tags = $this->Tag->getContentTags($id, 'Note_Note');
$this->set('tags', $tags);
//
edit.ctp
//Tag system
<li>
    <div class="col-md-2">
        <label><?=__d('Blog', 'Tags')?></label>
    </div>
    <?php
    $tags_value = '';
        if (!empty($tags)) $tags_value = implode(', ', $tags);
    ?>
    <div class="col-md-10">
        <?php echo $this->Form->text('tags', array('value' => $tags_value)); ?> <a href="javascript:void(0)" class="tip profile-tip" title="<?=__d('Blog', 'Separated by commas')?>">(?)</a>
    </div>
    <div class="clear"></div>
</li>
//

Helper hook

NoteHelper.php
//Tag system
public function getTagUnionsNote($noteids)
{
    return "SELECT i.id, i.title, i.body, i.like_count, i.created, 'Note_Note' as moo_type
                     FROM " . Configure::read('core.prefix') . "notes i
                     WHERE i.id IN (" . implode(',', $noteids) . ") AND i.privacy = ".PRIVACY_EVERYONE;
}
public function getImage($item,$options)
{
    return $this->assetUrl('Note.noimage/note.png',$options + array('pathPrefix' => Configure::read('App.imageBaseUrl')));
 
    return $url;
}
//

When view note

NotesController.php
//Tag system
$this->loadModel('Tag');
$tags = $this->Tag->getContentTags($id, 'Note_Note');
$this->set('tags', $tags);
//
view.ctp
//Tag system
<div class="box_content">
    <?php echo $this->element( 'blocks/tags_item_block' ); ?>
</div>
//

How to using like system

View note

NotesController.php
//Like system
MooCore::getInstance()->setSubject($note);
//
view.ctp
//Like system
<div class="content_center">
    <div class="bar-content full_content p_m_10">
        <div class="content_center">
            <?php echo $this->renderLike();?>
        </div>
    </div>
</div>
//

How to using comment system

View note

notescontroller.php
//Comment system
MooCore::getInstance()->setSubject($note);
//
view.ctp
//Comment system
<div class="content_center">
    <div class="bar-content full_content p_m_10">
        <?php echo $this->renderComment();?>
    </div>
</div>
//
NoteHelper.php
//Comment system
public function checkPostStatus($note,$uid)
{
    if (!$uid)
        return false;
 
    $friendModel = MooCore::getInstance()->getModel('Friend');
    if ($uid == $note['Note']['user_id'])
        return true;
 
    if ($note['Note']['privacy'] == PRIVACY_EVERYONE)
    {
        return true;
    }
 
    if ($note['Note']['privacy'] == PRIVACY_FRIENDS)
    {
        $areFriends = $friendModel->areFriends( $uid, $note['Blog']['user_id'] );
        if ($areFriends)
            return true;
    }
 
    return false;
}
public function checkSeeActivity($note,$uid)
{
    return $this->checkPostStatus($note,$uid);
}
//

How to using report system

View note:

view.tcp
//Report system
<?=$this->Html->link(
    __d('Note', 'Report Note'), array(
        'controller' => 'reports',
        'action' => 'ajax_create',
        'plugin' => '',
        $note['Note']['moo_type'],
        $note['Note']['id']
    ), array('data-target'=>'#themeModal','class'=>'button button-action topButton button-mobi-top','data-toggle'=>'modal')
);
//

Plugin Development Suggestions

Themed Plugin

path app/View/Themed/[ThemeName]/Plugin/[PluginName]/

23fb6cd688d81fcb558c8984a443b870.jpg