View file mooSocial v2.3.0 - PHP Social Network/upload/app/Controller/PluginsController.php

File size: 48.61Kb
<?php

/**
 * mooSocial - The Web 2.0 Social Network Software
 * @website: http://www.moosocial.com
 */

class PluginsController extends AppController 
{
    public function beforeFilter()
    {
        parent::beforeFilter();
        $this->_checkPermission( array('super_admin' => true) ); 
        $this->loadModel('Setting');
        $this->loadModel('SettingGroup');
        $this->loadModel('Menu.CoreMenuItem');
    } 
        
    public function admin_index()
    {
        // get all installed plugins
        $plugins = $this->Plugin->find( 'all', array(
            'order' => 'id DESC'
        ));
        
        //check new version
        $plugins = $this->checkNewVersion($plugins);
        
        $installed_plugins_key = array();
        $plugin_setting_url = array();
        foreach ( $plugins as $plugin )
        {
            $installed_plugins_key[] = $plugin['Plugin']['key'];
            $plugin_setting_url[] = $this->splitAtUpperCase($plugin['Plugin']['key']);
        }
        
        // get all plugins in folder
        $all_plugins  = scandir(APP  . 'Plugin');   
        $not_installed_plugins = array();                    
        foreach ( $all_plugins as $key => $plugin )
        {
            if ($plugin != '.' && $plugin != '..' && 
                array_search( $plugin, $installed_plugins_key ) === false && 
                !empty( $plugin ) &&
                is_dir(APP  . 'Plugin'. DS .$plugin))
            {
                $not_installed_plugins[$key]['name'] = $plugin;
                $xmlPath = sprintf(PLUGIN_INFO_PATH, $plugin);
                if(file_exists($xmlPath))
                {
                    $content = file_get_contents($xmlPath);
                    $xml = new SimpleXMLElement($content);
                    $not_installed_plugins[$key]['version'] =   $xml->version;
                    $not_installed_plugins[$key]['author'] =   $xml->author;
                }
            }
        }        
   
        $this->set('plugins', $plugins);
        $this->set('plugin_setting_url',$plugin_setting_url);
        $this->set('not_installed_plugins', $not_installed_plugins);
    } 

    public function admin_ajax_view( $id = null )
    {
        if(!$this->Plugin->isIdExist($id))
        {
            $this->set('error', __("This plugin does not exist."));
        }
        else 
        {
            $plugin = $this->Plugin->findById( $id );
            

            // get plugin info
            $xmlPath = sprintf(PLUGIN_INFO_PATH, $plugin['Plugin']['key']);
            if(file_exists($xmlPath))
            {
                $content = file_get_contents($xmlPath);
                $info = new SimpleXMLElement($content);

                

                // get all roles
                $this->loadModel('Role');
                $roles = $this->Role->find('all');

                $this->set('roles', $roles);        
                $this->set('info', $info);      
                $this->set('plugin', $plugin['Plugin']);     
                //$this->set('settings', $settings);   
            }
            else 
            { 
                $this->set('error', __("This plugin does not exist.")); 
            }
        }
    }
    
    public function admin_do_download( $key )
    {
        if(!$this->Plugin->isKeyExist($key))
        {
            $this->Session->setFlash(__('This plugin does not exist'), 'default', array('class' => 'Metronic-alerts alert alert-success fade in' ));
            $this->redirect($this->referer());
        }
        else 
        {
            $plugin = $this->Plugin->findByKey( $key );
            
            $file_name = '';
            if(!empty($plugin['Plugin']['version'])) {
                $file_name = 'moo-' . $key . '-' . $plugin['Plugin']['version'] . '.zip';
            } else {
                $file_name = 'moo-' . $key  . '.zip';
            }

            $zip = new ZipArchive;

            if ( $zip->open( WWW_ROOT . DS . 'uploads' . DS . 'tmp' . DS . $file_name, ZipArchive::CREATE ) === TRUE ) 
            {
                // add plugin folder
                addDir( APP . 'Plugin' . DS . $key, $zip, 'Plugin' . DS . $key );

                if ( !$zip->close() )
                    $this->_showError(__('Cannot create zip file'));

                $this->redirect( '/uploads/tmp/' . $file_name ); 
            }
            else
                $this->_showError(__('Cannot create zip file'));
        }
    }
    
    public function admin_do_enable( $key )
    {
        $this->loadModel('SettingGroup');
        $setting_group = $this->SettingGroup->findByModuleId($key);
        $plugin_info = $this->Plugin->findByKey($key,array('name','id'));
        $original_name = $plugin_info['Plugin']['name'];
        if(!empty($setting_group))
        {
            $this->loadModel('Setting');
            $settings = $this->Setting->findAllByGroupId($setting_group['SettingGroup']['id']);
            $pattern = '/^[\w]+_enabled$/';
            foreach($settings as &$setting)
            {
                //find enabled setting
                if(preg_match($pattern,$setting['Setting']['name']))
                {
                    $values = json_decode($setting['Setting']['value_actual'],true);
                    foreach($values as &$value)
                    {
                        $value['select'] = ($value['name'] == 'Enable') ? 1 : 0;
                    }
                    $new_values = json_encode($values);
                    $this->Setting->id = $setting['Setting']['id'];
                    $this->Setting->save(array('value_actual' => $new_values));

                    //update info.xml in plugin
                    App::uses('SystemSettingsController','Controller');
                    $sys = new SystemSettingsController();
                    $sys->update_plugin_info_xml($setting['Setting']['group_id']);

                    //update core menu
                    $this->loadModel('Menu.CoreMenuItem');
                    if(in_array($key,array('Blog','Group','Topic','Event','Photo','Video')))
                    {
                        $original_name.='s';
                    }
                    $keys_menu = $this->CoreMenuItem->find('first',array(
                        'conditions'=>array('original_name'=> $original_name ,'type'=>'plugin')
                    ));
                    if(!empty($keys_menu)){
                        if ($keys_menu['CoreMenuItem']['id']) {
                            $this->CoreMenuItem->id = $keys_menu['CoreMenuItem']['id'];
                            $this->CoreMenuItem->save(array('is_active' => 1));
                        } else {
                            $this->CoreMenuItem->set(array(
                                'name' => $original_name,
                                'original_name' => $original_name,
                                'url' => '/'.strtolower($key).'s',
                                'is_active' => 1,
                                'menu_id' => 1,
                                'type' => 'plugin',
                                'menu_order' => 999
                            ));
                            $this->CoreMenuItem->save();
                        }
                        Cache::clearGroup('menu');
                    }

                    //update plugin enable status
                    $this->Plugin->id = $plugin_info['Plugin']['id'];
                    $this->Plugin->save( array( 'enabled' => 1 ) );

                    $this->Session->setFlash(__('Plugin has been successfully enabled'), 'default', array('class' => 'Metronic-alerts alert alert-success fade in' ));
                    break;
                }
            }
        }
        $this->redirect($this->referer());
    }
    
    public function admin_do_disable( $key )
    {
        $this->loadModel('SettingGroup');
        $setting_group = $this->SettingGroup->findByModuleId($key);
        $plugin_info = $this->Plugin->findByKey($key,array('name','id'));
        $original_name = $plugin_info['Plugin']['name'];
        if(!empty($setting_group))
        {
            $this->loadModel('Setting');
            $settings = $this->Setting->findAllByGroupId($setting_group['SettingGroup']['id']);
            $pattern = '/^[\w]+_enabled$/';
            foreach($settings as &$setting)
            {
                //find enabled setting
                if(preg_match($pattern,$setting['Setting']['name']))
                {
                    $values = json_decode($setting['Setting']['value_actual'],true);
                    foreach($values as &$value)
                    {
                        $value['select'] = ($value['name'] == 'Disable') ? 1 : 0;
                    }
                    $new_values = json_encode($values);
                    $this->Setting->id = $setting['Setting']['id'];
                    $this->Setting->save(array('value_actual' => $new_values));

                    //update info.xml in plugin
                    App::uses('SystemSettingsController','Controller');
                    $sys = new SystemSettingsController();
                    $sys->update_plugin_info_xml($setting['Setting']['group_id']);

                    //update core menu
                    $this->loadModel('Menu.CoreMenuItem');
                    if(in_array($key,array('Blog','Group','Topic','Event','Photo','Video')))
                    {
                        $original_name.='s';
                    }
                    $keys_menu = $this->CoreMenuItem->find('first',array(
                        'conditions'=>array('original_name'=> $original_name ,'type'=>'plugin')
                    ));
                    if(!empty($keys_menu)){
                        if ($keys_menu['CoreMenuItem']['id']) {
                            $this->CoreMenuItem->id = $keys_menu['CoreMenuItem']['id'];
                            $this->CoreMenuItem->save(array('is_active' => 0));
                        } else {
                            $this->CoreMenuItem->set(array(
                                'name' => $original_name,
                                'original_name' => $original_name,
                                'url' => '/'.strtolower($key).'s',
                                'is_active' => 0,
                                'menu_id' => 1,
                                'type' => 'plugin',
                                'menu_order' => 999
                            ));
                            $this->CoreMenuItem->save();
                        }
                        Cache::clearGroup('menu');
                    }

                    //update plugin enable status
                    $this->Plugin->id = $plugin_info['Plugin']['id'];
                    $this->Plugin->save( array( 'enabled' => 0 ) );

                    $this->Session->setFlash(__('Plugin has been successfully disabled'), 'default', array('class' => 'Metronic-alerts alert alert-success fade in' ));
                    break;
                }
            }
        }
        $this->redirect($this->referer());
    }
    
    public function admin_routes_on( $id )
    {
        if($this->Plugin->hasAny(array('id' => $id, 'core' => 1)))
        {
            $this->Session->setFlash(__('You can not modify core plugin'), 'default', array('class' => 'Metronic-alerts alert alert-danger fade in' ));
        }
        else if(!$this->Plugin->isIdExist($id))
        {
            $this->Session->setFlash(__('This plugin does not exist'), 'default', array('class' => 'Metronic-alerts alert alert-danger fade in' ));
        }
        else 
        {
            $plugin = $this->Plugin->findById( $id );
            //$this->_checkExistence( $plugin );

            $this->Plugin->id = $id;
            $this->Plugin->save( array( 'routes' => 1 ) );
            
            //update plugin info xml
            $xmlPath = sprintf(PLUGIN_INFO_PATH, $plugin['Plugin']['key']);
            if ( file_exists( $xmlPath) )
            {
                $content = file_get_contents($xmlPath);
                $info = new SimpleXMLElement($content);            
                $info->routes = 1;
                $info->saveXML($xmlPath);
            }

            //update plugins xml
            $this->init_plugins_xml();

            
            Cache::clearGroup('cache_group', '_cache_group_');

            $this->Session->setFlash(__('Routes has been successfully enabled'), 'default', array('class' => 'Metronic-alerts alert alert-success fade in' ));
        }
        $this->redirect( $this->referer() );
    }
    
    public function admin_routes_off( $id )
    {
        if($this->Plugin->hasAny(array('id' => $id, 'core' => 1)))
        {
            $this->Session->setFlash(__('You can not modify core plugin'), 'default', array('class' => 'Metronic-alerts alert alert-danger fade in' ));
        }
        else if(!$this->Plugin->isIdExist($id))
        {
            $this->Session->setFlash(__('This plugin does not exist'), 'default', array('class' => 'Metronic-alerts alert alert-danger fade in' ));
        }
        else 
        {
            $plugin = $this->Plugin->findById( $id );
            //$this->_checkExistence( $plugin );

            $this->Plugin->id = $id;
            $this->Plugin->save( array( 'routes' => 0 ) );
            
            //update plugin info xml
            $xmlPath = sprintf(PLUGIN_INFO_PATH, $plugin['Plugin']['key']);
            if ( file_exists( $xmlPath) )
            {
                $content = file_get_contents($xmlPath);
                $info = new SimpleXMLElement($content);            
                $info->routes = 0;
                $info->saveXML($xmlPath);
            }

            //update plugins xml
            $this->init_plugins_xml();

            
            Cache::clearGroup('cache_group', '_cache_group_');

            $this->Session->setFlash(__('Routes has been successfully disabled'), 'default', array('class' => 'Metronic-alerts alert alert-success fade in' ));
        }
        $this->redirect( $this->referer() );
    }
    
    public function admin_bootstrap_on( $id )
    {
        if($this->Plugin->hasAny(array('id' => $id, 'core' => 1)))
        {
            $this->Session->setFlash(__('You can not modify core plugin'), 'default', array('class' => 'Metronic-alerts alert alert-danger fade in' ));
        }
        else if(!$this->Plugin->isIdExist($id))
        {
            $this->Session->setFlash(__('This plugin does not exist'), 'default', array('class' => 'Metronic-alerts alert alert-danger fade in' ));
        }
        else 
        {
            $plugin = $this->Plugin->findById( $id );
            

            $this->Plugin->id = $id;
            $this->Plugin->save( array( 'bootstrap' => 1 ) );
            
            //update plugin info xml
            $xmlPath = sprintf(PLUGIN_INFO_PATH, $plugin['Plugin']['key']);
            if ( file_exists( $xmlPath) )
            {
                $content = file_get_contents($xmlPath);
                $info = new SimpleXMLElement($content);            
                $info->bootstrap = 1;
                $info->saveXML($xmlPath);
            }

            //update plugins xml
            $this->init_plugins_xml();

            
            Cache::clearGroup('cache_group', '_cache_group_');

            $this->Session->setFlash(__('Bootstrap has been successfully enabled'), 'default', array('class' => 'Metronic-alerts alert alert-success fade in' ));
        }
        $this->redirect( $this->referer() );
    }
    
    public function admin_bootstrap_off( $id )
    {
        if($this->Plugin->hasAny(array('id' => $id, 'core' => 1)))
        {
            $this->Session->setFlash(__('You can not modify core plugin'), 'default', array('class' => 'Metronic-alerts alert alert-danger fade in' ));
        }
        else if(!$this->Plugin->isIdExist($id))
        {
            $this->Session->setFlash(__('This plugin does not exist'), 'default', array('class' => 'Metronic-alerts alert alert-danger fade in' ));
        }
        else 
        {
            $plugin = $this->Plugin->findById( $id );
            

            $this->Plugin->id = $id;
            $this->Plugin->save( array( 'bootstrap' => 0 ) );
            
            //update plugin info xml
            $xmlPath = sprintf(PLUGIN_INFO_PATH, $plugin['Plugin']['key']);
            if ( file_exists( $xmlPath) )
            {
                $content = file_get_contents($xmlPath);
                $info = new SimpleXMLElement($content);            
                $info->bootstrap = 0;
                $info->saveXML($xmlPath);
            }

            //update plugins xml
            $this->init_plugins_xml();

            
            Cache::clearGroup('cache_group', '_cache_group_');

            $this->Session->setFlash(__('Bootstrap has been successfully disabled'), 'default', array('class' => 'Metronic-alerts alert alert-success fade in' ));
        }
        $this->redirect( $this->referer() );
    }
    
    public function admin_ajax_reorder()
    {
        $this->autoRender = false;
        
        $i = 1;
        foreach ($this->request->data['plugins'] as $plugin_id)
        {
            $this->Plugin->updateAll( array( 'weight' => $i ), array( 'id' => $plugin_id ) );
            $i++;
        }
        
        
        Cache::clearGroup('cache_group', '_cache_group_');
    }
    
    public function admin_ajax_save()
    {
        $id = $this->request->data['id'];
        if(!$this->Plugin->isIdExist($id))
        {
            $this->Session->setFlash(__('This plugin does not exist'), 'default', array('class' => 'Metronic-alerts alert alert-success fade in' ));
        }
        else 
        {
            $this->autoRender = false;

            $plugin = $this->Plugin->findById($id);
            $this->_checkExistence( $plugin );

            $xmlPath = sprintf(PLUGIN_INFO_PATH, $plugin['Plugin']['key']);
            if ( file_exists( $xmlPath) )
            {
                $content = file_get_contents($xmlPath);
                $info = new SimpleXMLElement($content);            
                $info->bootstrap = $this->request->data['bootstrap'];
                $info->routes = $this->request->data['routes'];
                $info->saveXML($xmlPath);
            }

            $this->request->data['permission'] = (empty( $this->request->data['everyone'] )) ? implode(',', $_POST['permissions']) : '';

            $this->Plugin->id = $this->request->data['id'];
            $this->Plugin->save( $this->request->data );

            
            Cache::clearGroup('cache_group', '_cache_group_');
            $this->Session->setFlash(__('Plugin has been successfully updated'),'default',
                array('class' => 'Metronic-alerts alert alert-success fade in' ));
            
            //update plugins config
            $this->init_plugins_xml();
        }
    }
    
    public function admin_ajax_create()	
    {
        $plugin_folder = (APP . 'Plugin');
        
        $perms = (int) substr(sprintf('%o', fileperms($plugin_folder)), -4);
        if ($perms >= 755) {
            $dir_writable = 1;
        } else {
            $dir_writable = 0;
        }
        
        $this->set('dir_writable', $dir_writable);
        
        // get all roles
        $this->loadModel('Role');
        $roles = $this->Role->find('all');
        
        $this->set('roles', $roles);  
        $this->set('pluginType', $this->Plugin->PluginType());
    }
    
    private function splitAtUpperCase($string)
    {
        $result = preg_split('/(?=[A-Z])/',$string);
        $result = implode('_', $result);
        $result = strtolower($result);
        if(substr($result, 0, 1) == '_')
        {
            $result = substr($result, 1);
        }
        return $result;
    }
    
    public function pluginMenu()
    {
        $plugins = $this->Plugin->find('all', array(
            'conditions' => array('core' => 0, 'enabled' => 1),
            'fields' => array('name', 'key')
        ));
        if($plugins != null)
        {
            foreach($plugins as $k => $plugin)
            {
                $plugin = $plugin['Plugin']; 
                $plugins[$k]['Plugin']['link'] = $this->request->base.'/admin/'.$this->splitAtUpperCase($plugin['key']);
            }
        }
        return $plugins;
    }

    protected function _jsonError( $msg )
    {
        $this->autoRender = false;
        
        $response['result'] = 0;
        $response['message'] = $msg;
        
        echo json_encode($response);
        exit;
    }
    
    private function init_plugins_xml()
    {
        $content = '<?xml version="1.0" encoding="utf-8"?>
                    <info></info>';
        file_put_contents(PLUGIN_CONFIG_PATH, $content);
        $xml = new SimpleXMLElement($content);  

        //add plugins to xml
        $plugins = $plugins = $this->Plugin->find('all');
        if($plugins != null)
        {
            $pluginsXml = $xml->addChild('plugins');
            foreach($plugins as $plugin)
            {
                $pluginXml = $pluginsXml->addChild('plugin');
                $pluginXml->addChild('name', $plugin['Plugin']['key']);
                $pluginXml->addChild('enabled', $plugin['Plugin']['enabled'] == 1 ? 1: 0);
                $pluginXml->addChild('bootstrap', $plugin['Plugin']['bootstrap'] == 1 ? 1: 0);
                $pluginXml->addChild('routes', $plugin['Plugin']['routes'] == 1 ? 1: 0);
            }
        }
        $xml->saveXML(PLUGIN_CONFIG_PATH);
        
        $dom = new DOMDocument('1.0');
        $dom->preserveWhiteSpace = false;
        $dom->formatOutput = true;
        $dom->loadXML($xml->asXML());
        $dom->save(PLUGIN_CONFIG_PATH);
    }
    
    private function init_setting_group($key, $name)
    {
        if(!$this->SettingGroup->hasAny(array('group_type' => $key, 'module_id' => $key)))
        {
            $data = array('group_type' => $key, 'module_id' => $key, 'name' => $name);
            $this->SettingGroup->save($data);
            return $this->SettingGroup->getInsertID();
        }
        else 
        {
            $setting_group = $this->SettingGroup->find('first', array(
                'conditions' => array('group_type' => $key, 'module_id' => $key),
                'fields' => array('id')
            ));
            return $setting_group['SettingGroup']['id'];
        }
    }
    
    private function init_setting($group_id, $name)
    {
        $this->Setting->create();
        $this->Setting->set(array(
            'group_id' => $group_id,
            'label' => $name,
            'name' => strtolower($name) . '_enabled',
            'type_id' => 'radio',
            'value_actual' => '[{"name":"Disable","value":"0","select":0},{"name":"Enable","value":"1","select":1}]',
            'value_default' => '[{"name":"Disable","value":"0","select":0},{"name":"Enable","value":"1","select":1}]',
            'is_boot' => '1'
        ));
        $this->Setting->save();
    }
    
    private function clearCache()
    {
        //clear cache for unbootsetting in app/AppController function loadUnBootSetting
        Cache::delete('site.settings');

        
        Cache::clearGroup('cache_group', '_cache_group_');
    }
    
    ///////////////////////////////////////create///////////////////////////////////////
    public function admin_ajax_structure()
	{
		$this->autoRender = false;	
		$key = $this->request->data['key'] = ucfirst($this->request->data['key']);	
        if($this->Plugin->isKeyExist($key))
        {
            $this->_jsonError(' <b>' . $key . '</b> Duplicate key');
        }
        else 
        {
            $pluginPath = APP . 'Plugin' . DS . $key;

            $this->Plugin->set( $this->request->data );
            $this->_validateData( $this->Plugin );

            if ( file_exists($pluginPath ) )
                $this->_jsonError(' <b>' . $key . '</b> folder already exists');

            if ( $this->Plugin->save() )
            {				
                // create folders
                mkdir($pluginPath, 0755 );	

                mkdir($pluginPath . DS . 'Config', 0755 );
                mkdir($pluginPath . DS . 'Config' . DS . 'install', 0755 );
                file_put_contents($pluginPath . DS . 'Config' . DS . 'bootstrap.php', '');
                file_put_contents($pluginPath . DS . 'Config' . DS . 'install' . DS . 'install.sql', '');
                file_put_contents($pluginPath . DS . 'Config' . DS . 'install' . DS . 'uninstall.sql', '');
                $content = 
'<?xml version="1.0" encoding="utf-8"?>
<versions>
    <version>
        <number>'.$this->request->data['version'].'</number>
        <queries>
            <query></query>
        </queries>
    </version>
</versions>';
                file_put_contents($pluginPath . DS . 'Config' . DS . 'install' . DS . 'upgrade.xml', $content);
                
                mkdir($pluginPath . DS . 'Controller', 0755 );
                mkdir($pluginPath . DS . 'Controller' . DS . 'Component', 0755 );
                
                mkdir($pluginPath . DS . 'Lib', 0755 );

                mkdir($pluginPath . DS . 'Model', 0755 );	
                mkdir($pluginPath . DS . 'Model' . DS . 'Behavior', 0755 );

                mkdir($pluginPath . DS . 'View', 0755 );	
                mkdir($pluginPath . DS . 'View' . DS . 'Elements', 0755 );	
                mkdir($pluginPath . DS . 'View' . DS . 'Helper', 0755 );	
                mkdir($pluginPath . DS . 'View' . DS . 'Layouts', 0755 );	
                
                //create routes.php
                $plugin_url = $this->splitAtUpperCase($key).'s';
                $content = 
"<?php
Router::connect('/$plugin_url/:action/*', array(
    'plugin' => '$key',
    'controller' => '$plugin_url'
));

Router::connect('/$plugin_url/*', array(
    'plugin' => '$key',
    'controller' => '$plugin_url',
    'action' => 'index'
));
";
                file_put_contents($pluginPath . DS . 'Config' . DS . 'routes.php', $content);
                // create xml file
                $content = 
'<?xml version="1.0" encoding="utf-8"?>
<info>
    <name>' . $this->request->data['name'] . '</name>
    <key>' . $this->request->data['key'] . '</key>
    <version>' . $this->request->data['version'] . '</version>
    <description>' . $this->request->data['description'] . '</description>
    <author>' . $this->request->data['author'] . '</author>
    <website>' . $this->request->data['website'] . '</website>
    <bootstrap>' . $this->request->data['bootstrap'] . '</bootstrap>
    <routes>' . $this->request->data['routes'] . '</routes>
    <addtomenu>' . $this->request->data['add_to_menu'] . '</addtomenu>
</info>';
                file_put_contents($pluginPath . DS . 'info.xml', $content);

                //create default file
                $this->createDefaultPluginFiles($key, $this->request->data['name']);
                
                //create file by plugin type
                $this->createFileByPluginType($key, $this->request->data['plugin_type']);

                if ($this->request->data['add_to_menu']) {
                    //add to menu
                    $this->AddMenu($this->request->data['name'], $this->request->data['key']);
                }
                // add setting enable plugin
                
                
                // delete cache file
                Cache::delete('site_plugins');

                $response['result'] = 1;
                $response['id'] = $this->Plugin->id;
                echo json_encode($response);

                $this->init_plugins_xml();
                $group_id = $this->init_setting_group($key, $this->request->data['name']);
                $this->init_setting($group_id, $this->request->data['name']);
            }
        }
	}
    
    private function createDefaultPluginFiles($key, $pluginName)
    {
        $pluginPath = APP . 'Plugin' . DS . $key;
        $defControllerName = $key."sController";
        $defSettingControllerName = $key."SettingsController";
        $defViewName = $key.'s';
        $defSettingViewName = $key."Settings";
        $defSetupName = $key."Plugin";
        
        //create setup file
        $pluginUrl = $this->splitAtUpperCase($key);
        $content = 
"<?php 
App::uses('MooPlugin','Lib');
class $defSetupName implements MooPlugin{
    public function install(){}
    public function uninstall(){}
    public function settingGuide(){}
    public function menu()
    {
        return array(
            'General' => array('plugin' => '$pluginUrl', 'controller' => '".$this->splitAtUpperCase($defViewName)."', 'action' => 'admin_index'),
            'Settings' => array('plugin' => '$pluginUrl', 'controller' => '".$this->splitAtUpperCase($defSettingViewName)."', 'action' => 'admin_index'),
        );
    }
    /*
    Example for version 1.0: This function will be executed when plugin is upgraded (Optional)
    public function callback_1_0(){}
    */
}";
        file_put_contents($pluginPath . DS . $defSetupName.'.php', $content);

        //create plugin app controller
        $content = 
"<?php 
App::uses('AppController', 'Controller');
class ".$key."AppController extends AppController{
    
}";
        file_put_contents($pluginPath . DS . 'Controller' . DS . $key.'AppController.php', $content);

        //create plugin app model
        $content = 
"<?php 
App::uses('AppModel', 'Model');
class ".$key."AppModel extends AppModel{
    
}";
        file_put_contents($pluginPath . DS . 'Model' . DS . $key.'AppModel.php', $content);
        
        //create default controller
        $content = 
"<?php 
class $defControllerName extends ".$key."AppController{
    public function admin_index()
    {
    }
    public function index()
    {
    }
}";
        file_put_contents($pluginPath . DS . 'Controller' . DS . $defControllerName.'.php', $content);
        
        //create default setting controller
        $content = 
"<?php 
class $defSettingControllerName extends ".$key."AppController{
    public function admin_index()
    {
    }
}";
        file_put_contents($pluginPath . DS . 'Controller' . DS .$defSettingControllerName.'.php', $content);
        
        //create default plugin view
        mkdir($pluginPath . DS . 'View' . DS . $defViewName, 0755 );	
        $content = 
"<?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' => '$pluginName'));
    ".'$this'."->end();
?>
<?php echo".'$this'."->Moo->renderMenu('$key', 'General');?>";
        file_put_contents($pluginPath . DS . 'View' . DS . $defViewName . DS .'admin_index.ctp', $content);
        file_put_contents($pluginPath . DS . 'View' . DS . $defViewName . DS .'index.ctp', '');
        
        //create default setting view
        mkdir($pluginPath . DS . 'View' . DS .$defSettingViewName, 0755 );	
        $content = 
"<?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' => '$pluginName'));
    ".'$this'."->end();
?>
<?php echo".'$this'."->Moo->renderMenu('$key', 'Settings');?>";
        file_put_contents($pluginPath . DS . 'View' . DS .$defSettingViewName . DS .'admin_index.ctp', $content);
    }
    
    private function createFileByPluginType($key, $type)
    {
        $pluginPath = APP . 'Plugin' . DS . $key;
        $libPath = $pluginPath . DS . 'Lib';
        switch($type)
        {
            case 'payment':
                $content = 
"<?php 
App::uses('MooGateway','Lib');
class $key implements MooGateway{
    public function renderHtmlForm(".'$params'.", ".'$recurrence'." = false)
    {
    }
    
    public function validateTransaction()
    {
    }
}";
                file_put_contents($libPath . DS . $key.'.php', $content);
                break;
        }
    }
    
    ///////////////////////////////////////install///////////////////////////////////////
    public function admin_do_install( $key )
    {
        if($this->Plugin->isKeyExist($key))
        {
            $this->Session->setFlash(__('Duplicate key'), 'default', array( 'class' => 'Metronic-alerts alert alert-danger fade in') );
        }
        else 
        {
            //xml
            $xmlPath = sprintf(PLUGIN_INFO_PATH, $key);
            if ( file_exists($xmlPath) )
            {
                $content = file_get_contents($xmlPath);
                $info = new SimpleXMLElement($content);      
                $setting_group_id = $this->init_setting_group($key, $info->name);
                $settings = array();
                if ( !empty( $info->settings ) )
                {
                    $datas = json_decode(json_encode($info->settings), true);
                    if(!isset($datas['setting'][0]))
                    {
                        $temp = $datas['setting'];
                        unset($datas['setting']);
                        $datas['setting'][] = $temp;
                    }
                    foreach ($datas['setting'] as $data)
                    {
                        //insert setting to db if not exist
                        if(!$this->Setting->isSettingNameExist($data['name']))
                        {
                            $this->Setting->create();
                            $vals = $data['values'];
                            if($data['type'] == 'radio' || $data['type'] == 'checkbox' || $data['type'] == 'select')
                            {
                            	//Fix install with checkbox one value
                            	if (isset($data['values']['value']['name']))
                            	{
                            		if (!$data['values']['value']['name']);
                            			$data['values']['value']['name'] = '';
                            		$data['values']['value'] = array($data['values']['value']);
                            	}
                                $vals = json_encode($data['values']['value']);
                            }
                            $setting_values = array('group_id' => $setting_group_id,
                                                    'label' => $data['label'],
                                                    'name' => $data['name'],
                                                    'description' => $data['description'],
                                                    'type_id' => $data['type'],
                                                    'value_actual' => $vals,
                                                    'value_default' => $vals,
                                                    'ordering' => $this->Setting->generateOrdering($setting_group_id));

                            $this->Setting->save($setting_values);
                        }
                    }  
                }
                
                $this->Plugin->set( array( 'name' => $info->name, 
                                           'key' => $info->key, 
                                           'menu' => $info->menu, 
                                           'url' => $info->url, 
                                           'version' => $info->version,
                                           'bootstrap' => (int)$info->bootstrap,
                                           'routes' => (int)$info->routes));
                if ( $this->Plugin->save() )
                {
                    $id = $this->Plugin->getLastInsertId();
                    
                    // register plugin in plugins config
                    $this->init_plugins_xml();

                    if (!empty($info->addtomenu)) {
                        //add menu
                        $this->AddMenu($info->name, $info->key);
                    }

                    //install db
                    $this->installDatabase($key);
                    
                    //run install function
                    $this->executeInstall($key);
                    
                    //clear cache
                    $this->clearCache();

                    $this->Session->setFlash(__('Plugin has been successfully installed'), 'default', array('class' => 'Metronic-alerts alert alert-success fade in' ));
                }
                else
                {
                    $this->Session->setFlash(__('An error has occured'), 'default', array( 'class' => 'error-message') );
                }
            }
            else
            {
                $this->Session->setFlash(__('Cannot read plugin info file'), 'default', array( 'class' => 'error-message') );
            }
        }
        $this->redirect( $this->referer() );
    }
    
    private function installDatabase($key)
    {
        $file = sprintf(PLUGIN_INSTALL_PATH, $key);
        if(file_exists($file))
        {
            $content = file_get_contents($file);
            if(!empty($content))
            {
                $query = str_replace('{PREFIX}', $this->Setting->tablePrefix, $content);
                $db = ConnectionManager::getDataSource('default');
                try 
                {
                    $db->rawQuery($query);
                } 
                catch (Exception $ex) 
                {
                    $this->Session->setFlash($ex->getMessage(), 'default', array('class' => 'Metronic-alerts alert alert-success fade in' ));
                }
            }
        }
    }
    
    private function executeInstall($key)
    {
        App::build(array($key.'Plugin' => array(sprintf(PLUGIN_PATH, $key))), App::REGISTER);
        $classname = $key.'Plugin';
        App::uses($classname, $classname);
        if(class_exists($classname))
        {
            $cl = new $classname();
            if(method_exists($classname, 'install'))
            {
                $cl->install();
            }
        }
    }
    
    private function AddMenu($name, $key)
    {
        
        $roleModel = MooCore::getInstance()->getModel('Role');
    	$roles = $roleModel->find('all');
    	$role_ids = array();
    	foreach ($roles as $role)
    	{
            $role_ids[] = $role['Role']['id'];
    	}   
        
        $this->CoreMenuItem->set(array(
            'name' => $name,
            'original_name' => $name,
            'url' => '/'.$this->splitAtUpperCase($key).'s',
            'is_active' => 1,
            'menu_id' => 1,
            'type' => 'plugin',
            'role_access'=>json_encode($role_ids),
            'menu_order' => 999
        ));
        $this->CoreMenuItem->save();
        
        // clear cache
        Cache::clearGroup('menu', 'menu');
    }


    ///////////////////////////////////////uninstall///////////////////////////////////////
    public function admin_do_uninstall( $id )
    {
        if(!$this->Plugin->isIdExist($id))
        {
            $this->Session->setFlash(__('This plugin does not exist'), 'default', array('class' => 'Metronic-alerts alert alert-danger fade in' ));
        }
        else 
        {
            $plugin = $this->Plugin->findById( $id );
            $key = $plugin['Plugin']['key'];
            $this->_checkExistence( $plugin );

            // run plugin uninstall script here

            $this->Plugin->delete( $id ); 

            //remove plugin in plugins config
            $this->init_plugins_xml();
            
            //delete menu
            $this->deleteMenu($key);
            
            //uninstall db
            $this->uninstallDatabase($key);
            
            //run uninstall function
            $this->executeUninstall($key);
            
            //clear cache
            $this->clearCache();

            $this->Session->setFlash(__('Plugin has been successfully uninstalled'), 'default', array('class' => 'Metronic-alerts alert alert-success fade in' ));
        }
        $this->redirect( $this->referer() );
    }
    
    private function uninstallDatabase($key)
    {
        $file = sprintf(PLUGIN_UNINSTALL_PATH, $key);

        if(file_exists($file))
        {
            $content = file_get_contents($file);
            if(!empty($content))
            {
                $query = str_replace('{PREFIX}', Configure::read('core.prefix'), $content);
                $db = ConnectionManager::getDataSource('default');
                try 
                {
                    $db->rawQuery($query);
                } 
                catch (Exception $ex) 
                {
                    $this->Session->setFlash($ex->getMessage(), 'default', array('class' => 'Metronic-alerts alert alert-success fade in' ));
                }
            }
        }
    }
    
    private function executeUninstall($key)
    {
        $classname = $key.'Plugin';
        App::uses($classname, $classname);
        if(class_exists($classname))
        {
            $cl = new $classname();
            if(method_exists($classname, 'uninstall'))
            {
                $cl->uninstall();
            }
        }
    }
    
    private function deleteMenu($key)
    {
        $url = "/".$this->splitAtUpperCase($key).'s';
        $menu = $this->CoreMenuItem->findByUrl($url);
        $this->CoreMenuItem->delete($menu['CoreMenuItem']['id']);
        
        // clear cache
        Cache::clearGroup('menu', 'menu');
    }
    
    ///////////////////////////////////////upgrade///////////////////////////////////////
    private function checkNewVersion($plugins)
    {
        if($plugins != null)
        {
            foreach($plugins as $k => $plugin)
            {
                $plugins[$k]['Plugin']['new_version'] = false;
                $plugins[$k]['Plugin']['new_version_number'] = '';
                
                $plugin = $plugin['Plugin'];
                $file = sprintf(PLUGIN_INFO_PATH, $plugin['key']);
                if(file_exists($file))
                {
                    $xml = simplexml_load_file($file);
                    if($xml != null && isset($xml->version))
                    {
                        if((string)$xml->version > $plugin['version'])
                        {
                            $plugins[$k]['Plugin']['new_version'] = true;
                            $plugins[$k]['Plugin']['new_version_number'] = (string)$xml->version;
                        }
                    }
                }
            }
        }
        return $plugins;
    }
    
    public function totalNewVersion()
    {
        // get all installed plugins
        $plugins = $this->Plugin->find( 'all', array(
            'order' => 'id DESC'
        ));
        
        $totalNewVersion = 0;
        if($plugins != null)
        {
            foreach($plugins as $k => $plugin)
            {
                $plugin = $plugin['Plugin'];
                $file = sprintf(PLUGIN_INFO_PATH, $plugin['key']);
                if(file_exists($file))
                {
                    $xml = simplexml_load_file($file);
                    if($xml != null && isset($xml->version))
                    {
                        if((string)$xml->version > $plugin['version'])
                        {
                            $totalNewVersion += 1;
                        }
                    }
                }
            }
        }
        return $totalNewVersion;
    }
    
    public function admin_do_upgrade( $id )
    {
        if(!$this->Plugin->hasAny(array('id' => $id)))
        {
            $this->Session->setFlash(__('This plugin does not exist'), 'default', array('class' => 'Metronic-alerts alert alert-danger fade in' ));
        }
        else 
        {
            //load plugin
            $plugin = $this->Plugin->findById( $id );
            $plugin = $plugin['Plugin'];
            
            //check new version
            $file = sprintf(PLUGIN_INFO_PATH, $plugin['key']);
            $version = $plugin['version'];
            if(file_exists($file))
            {
                $xml = simplexml_load_file($file);
                if($xml != null && isset($xml->version))
                {
                    if((string)$xml->version <= $plugin['version'])
                    {
                        $this->Session->setFlash(__('There is no new upgrade for this plugin.'), 'default', array('class' => 'Metronic-alerts alert alert-success fade in' ));
                        $this->redirect( $this->referer() );
                    }
                    else 
                    {
                        $version = (string)$xml->version;
                    }
                }
            }
            else 
            {
                $this->Session->setFlash(__('File info.xml not found.'), 'default', array('class' => 'Metronic-alerts alert alert-success fade in' ));
                $this->redirect( $this->referer() );
            }
            
            //update db version number
            $this->Plugin->id = $id;
            $this->Plugin->set(array('version' => $version));
            if(!$this->Plugin->save())
            {
                $this->Session->setFlash(__('Cannot upgrade new version. Please try again.'), 'default', array('class' => 'Metronic-alerts alert alert-success fade in' ));
                $this->redirect( $this->referer() );
            }
            else 
            {
                $this->Session->setFlash(__('Successfully upgrade.'), 'default', array('class' => 'Metronic-alerts alert alert-success fade in' ));
            }
                
            //read upgrade.xml
            $file = sprintf(PLUGIN_UPGRADE_PATH, $plugin['key']);
            if(file_exists($file))
            {
                $xml = simplexml_load_file($file);
                if($xml != null && isset($xml->version))
                {
                    foreach($xml->version as $version)
                    {
                        if((string)$version->number > $plugin['version'])
                        {
                            //update db
                            $this->upgradeDatabase($version->queries);
                            
                            //upgrade callback
                            $this->executeUpgrade($plugin['key'], (string)$version->number);
                        }
                    }
                }
            }
            else
            {
                $this->Session->setFlash(__('Cannot read plugin upgrade file. Please try again.'), 'default', array( 'class' => 'Metronic-alerts alert alert-success fade in') );
            }
        }
        
        //clear cache
        $this->clearCache();
        
        $this->redirect( $this->referer() );
    }
    
    private function upgradeDatabase($xml)
    {
        if($xml != null)
        {
			$db = ConnectionManager::getDataSource('default');
            foreach($xml->query as $query)
            {
				$query = (string)$query;
                if(!empty($query))
                {
                    $query = str_replace('{PREFIX}', Configure::read('core.prefix'), $query);
                    try 
                    {
                        $db->rawQuery($query);
                    } 
                    catch (Exception $ex) 
                    {
                        $this->Session->setFlash($ex->getMessage(), 'default', array('class' => 'Metronic-alerts alert alert-success fade in' ));
                    }
                }
            }
        }
    }
    
    private function executeUpgrade($key, $version)
    {
        if(!empty($key) && !empty($version))
        {
            $version = str_replace('.', '_', $version);
            $classname = $key.'Plugin';
            App::uses($classname, $classname);
            if(class_exists($classname))
            {
                $cl = new $classname();
                $func = "callback_".$version;
                if(method_exists($classname, $func))
                {
                    $cl->$func();
                }
            }
        }
    }
}