SlideShare ist ein Scribd-Unternehmen logo
1 von 115
Chamiluda Madrid
2013
Chamilo Plugin
Creation

By:
Giuliano Mandotti
Chamilo LMS Association Member
Summary
Introduction

➔

Part A

➔

1) Presenting 2 Plugin's Example
➔
2) Deeper Analysis of the 2 plugins
➔

Part B

➔

1) General Plugin Pattern-Model
➔
2) Simple Plugin Creation example
➔

Conclusion

➔
Introduction

Myself
➔
Chamilo LMS 1.9.x
➔
Introduction

Myself

➔
Introduction

Chamilo LMS 1.9.x

➔
Where does Chamilo
come from?

Claroline

Dokeos

Dokeos
Latinoamérica

2001

2004

2007

1.0

Chamilo LMS
1.8
2010

Chamilo LMS
1.9
2012
Chamilo 1.9.6 still is...
A Learning Management System
➔
A system to help manage learning.
➔
A system to help to manage
knowledge
➔
Improves informal learning eficiency
➔
Improves learning monitoring
➔
Improves the way documents are kept
➔
Improves availability of courses
➔
Reduces costs and training times
➔
Part A

1) Presenting 2 Plugin's Example

➔

Show user information Plugin
➔
RSS Plugin
➔

2) Deeper Analysis of the 2 plugins

➔
Part A / 1
Plugin Examples

Show user information Plugin
➔
RSS Plugin
➔
Part A / 1
Plugin Examples
Administration Panel
Part A / 1
Plugin Examples
Administration Panel / Plugin SubPanel
Part A / 1
Plugin Examples
Plugin List
Part A / 1
Plugin Examples

Show User Info

➔
Part A / 1
Plugin Examples
Plugin List
Part A / 1
Plugin Show User Info
Part A / 1
Plugin Show User Info
Part A / 1
Plugin Show User Info
Part A / 1
Plugin Examples

RSS

➔
Part A / 1
Plugin RSS
Plugin List
Part A / 1
Plugin RSS
Part A / 1
Plugin RSS
Part A / 1
Plugin RSS
Part A / 2
Deeper Analysis

Show user information Plugin
➔
RSS Plugin
➔
Part A / 2
Plugin Deeper Analysis

Show User Info

➔
Part A / 2 Deeper Analysis
Plugin Show User Info
Chamilo Directory

Plugin Directory
Part A / 2 Deeper Analysis
Plugin Show User Info
Part A / 2 Deeper Analysis
Plugin Show User Info
Part A / 2 Deeper Analysis
Plugin Show User Info
Part A / 2 Deeper Analysis
Plugin Show User Info
Part A / 2 Deeper Analysis
Plugin Show User Info
Part A / 2 Deeper Analysis
Plugin Show User Info
Part A / 2
Plugin Deeper Analysis

Rss

➔
Part A / 2 Deeper Analysis
RSS
Chamilo Directory

Plugin Directory
Part A / 2 Deeper Analysis
RSS
Part A / 2 Deeper Analysis
RSS
Part A / 2 Deeper Analysis
RSS
Part A / 2 Deeper Analysis
RSS
Part A / 2 Deeper Analysis
RSS
Part A / 2 Deeper Analysis
RSS
Part A / 2 Deeper Analysis
RSS
Part A / 2 Deeper Analysis
RSS
Part A / 2 Deeper Analysis
RSS
Part B

1) General Plugin Pattern-Model

➔

2) Simple Plugin Creation example

➔
Part B / 1
General Plugin Pattern-Model

Important Files
➔
Roles
➔
Part B / 1
General Plugin Pattern-Model

Important Files

➔
Part B / 1 Important Files

Which are the most important
files that Chamilo use to
include Plugins?
Part B / 1 Important Files

Global.inc.php
Settings.lib.php

Settings.php

Configure_plugin.php
Plugin.class.php

Plugin.lib.php
Part B / 1 Important Files

Where can we find them?
Part B / 1 Important Files
Part B / 1 Important Files
Part B / 1 Important Files
Part B / 1 Important Files
Part B / 1
General Plugin Pattern-Model

Roles

➔
Part B / 1 Their Roles

Which are their roles?
Part B / 1
Roles

Global.inc.php (part of)

➔
Part B / 1 Global.inc.php

…....

…....
Catch all the plugin's settings info
Part B / 1
Roles

Settings.lib.php

➔
Part B / 1 Settings.lib.php
<?php
/* For licensing terms, see /license.txt */
….....
/**
* This function allows easy activating and inactivating of regions
* @author Julio Montoya <gugli100@gmail.com> Beeznest 2012
*/
function handle_regions() {
…........
}
$plugin_obj = new AppPlugin();
$possible_plugins = $plugin_obj->read_plugins_from_path();
$installed_plugins = $plugin_obj->get_installed_plugins();
if (!empty($installed_plugins)) {
$not_installed = array_diff($possible_plugins, $installed_plugins);
} else {
$not_installed = $possible_plugins;
}
echo '<form name="plugins" method="post" action="'.api_get_self().'?category='.Security::remove_XSS($_GET['category']).'">';
echo '<table class="data_table">';
echo '<tr>';
echo '<th width="400px">';
echo get_lang('Plugin');
echo '</th><th>';
echo get_lang('Regions');
…......
Part B / 1 Settings.lib.php
…...
/* We display all the possible plugins and the checkboxes */
$plugin_region_list = array();
$my_plugin_list = $plugin_obj->get_plugin_regions();
foreach ($my_plugin_list as $plugin_item) {
$plugin_region_list[$plugin_item] = $plugin_item;
}
….....
Part B / 1 Settings.lib.php
…......
/**
* This function allows easy activating and inactivating of plugins
….....
function handle_plugins() {
$plugin_obj = new AppPlugin();
if (isset($_POST['submit_plugins'])) {
store_plugins();
// Add event to the system log.
$user_id = api_get_user_id();
$category = $_GET['category'];
event_system(LOG_CONFIGURATION_SETTINGS_CHANGE,
LOG_CONFIGURATION_SETTINGS_CATEGORY, $category, api_get_utc_datetime(),
$user_id);
Display :: display_confirmation_message(get_lang('SettingsStored'));
}
$all_plugins = $plugin_obj->read_plugins_from_path();
$installed_plugins = $plugin_obj->get_installed_plugins();
…......
$plugin_list = array();
$my_plugin_list = $plugin_obj->get_plugin_regions();
foreach($my_plugin_list as $plugin_item) {
$plugin_list[$plugin_item] = $plugin_item;
}
Part B / 1 Settings.lib.php
foreach ($all_plugins as $plugin) {
$plugin_info_file = api_get_path(SYS_PLUGIN_PATH).$plugin.'/plugin.php';
if (file_exists($plugin_info_file)) {
$plugin_info = array();
require $plugin_info_file;
if (in_array($plugin, $installed_plugins)) {
echo '<tr class="row_selected">';
} else {
echo '<tr>';
}
echo '<td>';
//Checkbox
if (in_array($plugin, $installed_plugins)) {
echo '<input type="checkbox" name="plugin_'.$plugin.'[]" checked="checked">';
…......
echo '<h4>'.$plugin_info['title'].' <small>v '.$plugin_info['version'].'</small></h4>';
echo '<p>'.$plugin_info['comment'].'</p>';
echo '<p>'.get_lang('Author').': '.$plugin_info['author'].'</p>';
echo '<div class="btn-group">';
if (in_array($plugin, $installed_plugins)) {
echo Display::url(get_lang('Configure'), 'configure_plugin.php?name='.$plugin, array('class' => 'btn'));
echo Display::url(get_lang('Regions'), 'settings.php?category=Regions&name='.$plugin, array('class' => 'btn'));
}
if (file_exists(api_get_path(SYS_PLUGIN_PATH).$plugin.'/readme.txt')) {
echo Display::url("readme.txt", api_get_path(WEB_PLUGIN_PATH).$plugin."/readme.txt", array('class' => 'btn
ajax', '_target' => '_blank'));
}
….....
echo '</table>';
echo '<div class="form-actions bottom_actions">';
echo '<button class="save" type="submit" name="submit_plugins">'.get_lang('EnablePlugins').'</button>';
Part B / 1 Settings.lib.php
…..
function store_regions() {
$plugin_obj = new AppPlugin();
// Get a list of all current 'Plugins' settings
$installed_plugins = $plugin_obj->get_installed_plugins();
$shortlist_installed = array();
if (!empty($installed_plugins)) {
foreach ($installed_plugins as $plugin) {
if (isset($plugin['subkey'])) {
$shortlist_installed[] = $plugin['subkey'];
}
}
}
$shortlist_installed = array_flip(array_flip($shortlist_installed));
$plugin_list = $plugin_obj->read_plugins_from_path();
foreach ($plugin_list as $plugin) {
if (isset($_POST['plugin_'.$plugin])) {
$areas_to_installed = $_POST['plugin_'.$plugin];
if (!empty($areas_to_installed)) {
$plugin_obj->remove_all_regions($plugin);
foreach ($areas_to_installed as $region) {
if (!empty($region) && $region != '-1' ) {
$plugin_obj->add_to_region($plugin, $region);
}
}
….......
Part B / 1 Settings.lib.php
…..
/**
* This function allows easy activating and inactivating of plugins
* @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
*/
function store_plugins() {
$plugin_obj = new AppPlugin();
// Get a list of all current 'Plugins' settings
$plugin_list = $plugin_obj->read_plugins_from_path();
$installed_plugins = array();
foreach ($plugin_list as $plugin) {
if (isset($_POST['plugin_'.$plugin])) {
$plugin_obj->install($plugin);
$installed_plugins[] = $plugin;
}
}
if (!empty($installed_plugins)) {
$remove_plugins = array_diff($plugin_list, $installed_plugins);
} else {
$remove_plugins = $plugin_list;
}
foreach ($remove_plugins as $plugin) {
$plugin_obj->uninstall($plugin);
}
}
/**

….......
Part B / 1 Settings.lib.php

…..
function generate_settings_form($settings, $settings_by_access_list) {
global $_configuration, $settings_to_avoid, $convert_byte_to_mega_list;
$table_settings_current = Database :: get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
$form = new FormValidator('settings', 'post', 'settings.php?category='.Security::remove_XSS($_GET['category']));
$form->addElement('hidden', 'search_field', (!empty($_GET['search_field'])?
Security::remove_XSS($_GET['search_field']):null));
$url_id = api_get_current_access_url_id();
if (!empty($_configuration['multiple_access_urls']) && api_is_global_platform_admin() && $url_id == 1) {
$group = array();
$group[] = $form->createElement('button', 'mark_all', get_lang('MarkAll'));
$group[] = $form->createElement('button', 'unmark_all', get_lang('UnmarkAll'));
$form->addGroup($group, 'buttons_in_action_right');
…...
Part B / 1
Roles

Settings.php

➔
Part B / 1 Settings.php
<?php
/* For licensing terms, see /license.txt */
/**
* With this tool you can easily adjust non critical configuration settings.
* Non critical means that changing them will not result in a broken campus.
*
* @author Patrick Cool
* @author Julio Montoya - Multiple URL site
* @package chamilo.admin
*/
…........

…....
// Database table definitions.
$table_settings_current = Database :: get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
// Setting breadcrumbs.
$interbreadcrumb[] = array('url' => 'index.php', 'name' => get_lang('PlatformAdmin'));
// Setting the name of the tool.
$tool_name = get_lang('PlatformConfigSettings');
if (empty($_GET['category'])) {
$_GET['category'] = 'Platform';
}
…....
Part B / 1 Settings.php
…..
$url_id = api_get_current_access_url_id();
$settings = null;
function get_settings($category = null) {
$url_id = api_get_current_access_url_id();
$settings_by_access_list = array();
if ($url_id == 1) {
$settings = api_get_settings($category, 'group', $url_id);
} else {
$url_info = api_get_access_url($url_id);
…......
// One more validation if is changeable.
if ($row['access_url_changeable'] == 1)
$settings_by_access_list[ $row['variable'] ] [ $row['subkey'] ] [ $row['category'] ] = $row;
else
$settings_by_access_list[ $row['variable'] ] [ $row['subkey'] ] [ $row['category'] ] = array();
}
}
}
if (isset($category) && $category== 'search_setting') {
if (!empty($_REQUEST['search_field'])) {
$settings = search_setting($_REQUEST['search_field']);
}
}
return array('settings' => $settings, 'settings_by_access_list' => $settings_by_access_list);
}
// Build the form.
….....
Part B / 1 Settings.php
….
// Including the header (banner).
Display :: display_header($tool_name);
// The action images.
$action_images['platform']
= 'platform.png';
$action_images['course']
= 'course.png';
$action_images['session']
= 'session.png';
$action_images['tools']
= 'tools.png';
$action_images['user']
= 'user.png';
$action_images['gradebook'] = 'gradebook.png';
$action_images['ldap']
= 'ldap.png';
$action_images['cas']
= 'user_access.png';
$action_images['security']
= 'security.png';
$action_images['languages'] = 'languages.png';
$action_images['tuning']
= 'tuning.png';
$action_images['templates'] = 'template.png';
$action_images['search']
= 'search.png';
$action_images['editor']
= 'html_editor.png';
$action_images['timezones'] = 'timezone.png';
$action_images['extra']
= 'wizard.png';
$action_images['tracking']
= 'statistics.png';
$action_images['gradebook'] = 'gradebook.png';
$action_images['search']
= 'search.png';
$action_images['stylesheets'] = 'stylesheets.png';
$action_images['templates'] = 'template.png';
$action_images['plugins']
= 'plugins.png';
$action_images['shibboleth'] = 'shibboleth.png';
$action_images['facebook']
= 'facebook.png';
…...
Part B / 1 Settings.php
...
$action_array = array();
$resultcategories = array();
$resultcategories[] = array('category' => 'Platform');
$resultcategories[] = array('category' => 'Course');
$resultcategories[] = array('category' => 'Session');
$resultcategories[] = array('category' => 'Languages');
$resultcategories[] = array('category' => 'User');
$resultcategories[] = array('category' => 'Tools');
$resultcategories[] = array('category' => 'Editor');
$resultcategories[] = array('category' => 'Security');
$resultcategories[] = array('category' => 'Tuning');
$resultcategories[] = array('category' => 'Gradebook');
$resultcategories[] = array('category' => 'Timezones');
$resultcategories[] = array('category' => 'Tracking');
$resultcategories[] = array('category' => 'Search');
$resultcategories[] = array('category' =>
'Stylesheets');
$resultcategories[] = array('category' => 'Templates');
$resultcategories[] = array('category' => 'Plugins');
$resultcategories[] = array('category' => 'LDAP');
$resultcategories[] = array('category' => 'CAS');
$resultcategories[] = array('category' => 'Shibboleth');
$resultcategories[] = array('category' => 'Facebook');
….
Part B / 1 Settings.php
…
if (!empty($_GET['category'])) {
switch ($_GET['category']) {
case 'Regions':
handle_regions();
break;
case 'Plugins':
// Displaying the extensions: Plugins.
// This will be available to all the sites (access_urls).
if (isset($_POST['submit_dashboard_plugins'])) {
$affected_rows = DashboardManager::store_dashboard_plugins($_POST);
if ($affected_rows) {
// add event to system log
$user_id = api_get_user_id();
$category = $_GET['category'];
event_system(LOG_CONFIGURATION_SETTINGS_CHANGE, LOG_CONFIGURATION_SETTINGS_CATEGORY,
$category, api_get_utc_datetime(), $user_id);
Display :: display_confirmation_message(get_lang('DashboardPluginsHaveBeenUpdatedSucesslly'));
}
…....
echo '<div id="tabs">';
echo '<ul>';
echo '<li><a href="#tabs-1">'.get_lang('Plugins').'</a></li>';
echo '<li><a href="#tabs-2">'.get_lang('DashboardPlugins').'</a></li>';
echo '<li><a href="#tabs-3">'.get_lang('ConfigureExtensions').'</a></li>';
echo '</ul>';
echo '<div id="tabs-1">';
handle_plugins();
echo '</div>';
echo '<div id="tabs-2">';
DashboardManager::handle_dashboard_plugins();
echo '</div>';
echo '<div id="tabs-3">';
handle_extensions();
echo '</div>';
…....
Part B / 1
Roles

Config_plugin.php

➔
Part B / 1 Config_plugin.php
<?php
/* For licensing terms, see /license.txt */
/............
// name of the language file that needs to be included
$language_file = array ('registration','admin');
$cidReset = true;
require_once '../inc/global.inc.php';
// Access restrictions
api_protect_admin_script();
$plugin_name = $_GET['name'];
$plugin_obj = new AppPlugin();
$plugin_info = $plugin_obj->get_plugin_info($plugin_name, true);
if (empty($plugin_info)) {
api_not_allowed();
}
$installed_plugins = $plugin_obj->get_installed_plugins();
if (!in_array($plugin_name, $installed_plugins)) {
api_not_allowed();
}
global $_configuration;
Part B / 1 Config_plugin.php
$content = null;
if (isset($plugin_info['settings_form'])) {
$form = $plugin_info['settings_form'];
if (isset($form)) {
//We override the form attributes
…........
}
} else { $message = Display::return_message(get_lang('NoConfigurationSettingsForThisPlugin'), 'warning');
}
if (isset($form)) {
if ($form->validate()) {
$values = $form->exportValues();
//api_delete_category_settings_by_subkey($plugin_name);
$access_url_id = api_get_current_access_url_id();
api_delete_settings_params(array('category = ? AND access_url = ? AND subkey = ? AND type = ? and variable
<> ?' =>
array('Plugins', $access_url_id, $plugin_name, 'setting', "status")));
foreach ($values as $key => $value) {
$key = Database::escape_string($plugin_name.'_'.$key);
api_add_setting($value, $key, $plugin_name, 'setting', 'Plugins', $plugin_name, null, null, null,
$_configuration['access_url'], 1);
}
$message = Display::return_message(get_lang('Updated'), 'success');
}
}
$tpl = new Template($tool_name, true, true, false, true, false);
$tpl->assign('actions', $actions);
$tpl->assign('message', $message);
$tpl->assign('content', $content);
$tpl->display_one_col_template();
Part B / 1
Roles

Plugin.class.php

➔
Part B / 1 Plugin.class.php
<?php
/* For licensing terms, see /license.txt */
/**
* Base class for plugins
*
* This class has to be extended by every plugin. It defines basic methods
…....
*/
class Plugin {
protected $version = '';
protected $author = '';
protected $fields = array();
private $settings = null;
private $strings = null; //translation strings
public $is_course_plugin = false;
/**
* When creating a new course, these settings are added to the course, in
* the course_info/infocours.php
* To show the plugin course icons you need to add these icons:
* main/img/icons/22/plugin_name.png
* main/img/icons/64/plugin_name.png
* main/img/icons/64/plugin_name_na.png
* @example
* $course_settings = array(
array('name' => 'big_blue_button_welcome_message', 'type' => 'text'),
array('name' => 'big_blue_button_record_and_store', 'type' => 'checkbox')
);
*/
….....
Part B / 1 Plugin.class.php
….
public $course_settings = array();
/**
* This indicates whether changing the setting should execute the callback
* function.
*/
public $course_settings_callback = false;
/**
* Default constructor for the plugin class. By default, it only sets
* a few attributes of the object
* @param string Version of this plugin
* @param string Author of this plugin
* @param array Array of global settings to be proposed to configure the
plugin
* @return void
*/
protected function __construct($version, $author, $settings = array()) {
$this->version = $version;
$this->author = $author;
$this->fields = $settings;
global $language_files;
$language_files[] = 'plugin_' . $this->get_name();
}
/**
…..
Part B / 1 Plugin.class.php
…
/**

* Gets an array of information about this plugin (name, version, ...)
* @return array Array of information elements about this plugin
*/
function get_info() {
$result = array();
$result['title']
= $this->get_title();
$result['comment']
= $this->get_comment();
$result['version']
= $this->get_version();
$result['author']
= $this->get_author();
$result['plugin_class'] = get_class($this);
$result['is_course_plugin'] = $this->is_course_plugin;
if ($form = $this->get_settings_form()) {
$result['settings_form'] = $form;
foreach ($this->fields as $name => $type) {
$value = $this->get($name);
$result[$name] = $value;
}
}
return $result;

}
/**
* Returns the "system" name of the plugin in lowercase letters
* @param string Name of the plugin
*/
function get_name() {
$result = get_class($this);
$result = str_replace('Plugin', '', $result);
$result = strtolower($result);
return $result;
}
/**
….
Part B / 1 Plugin.class.php
…
/**
* Returns the title of the plugin
* @param string Title of the plugin
*/
function get_title() {
return $this->get_lang('plugin_title');
}
/**
* Returns the description of the plugin
* @param string Description of the plugin
*/
function get_comment() {
return $this->get_lang('plugin_comment');
}
/**
* Returns the version of the plugin
* @param string Version of the plugin
*/
function get_version() {
return $this->version;
}
/**
* Returns the author of the plugin
* @param string Author(s) of the plugin
*/
function get_author() {
return $this->author;
}
….
Part B / 1 Plugin.class.php
…
/**
* Returns the contents of the CSS defined by the plugin
* @param string The CSS string
*/
function get_css() {
$name = $this->get_name();
$path = api_get_path(SYS_PLUGIN_PATH)."$name/resources/$name.css";
if (!is_readable($path)) {
return '';
}
$css = array();
$css[] = file_get_contents($path);
$result = implode($css);
return $result;
}
/**
* Returns an HTML form (generated by FormValidator) of the plugin settings
* @return string FormValidator-generated form
*/
function get_settings_form() {
$result = new FormValidator($this->get_name());
$defaults = array();
foreach ($this->fields as $name => $type) {
$value = $this->get($name);
$defaults[$name] = $value;
$type = isset($type) ? $type : 'text';
$help = null;
if ($this->get_lang_plugin_exists($name.'_help')) {
$help = $this->get_lang($name.'_help');
}
switch ($type) {
….
Part B / 1 Plugin.class.php
…
/**
* Returns the value of a given plugin global setting
* @param string Name of the plugin
* @return string Value of the plugin
*/
function get($name) {
$settings = $this->get_settings();
foreach ($settings as $setting) {
if ($setting['variable'] == ($this->get_name() . '_' . $name)) {
return $setting['selected_value'];
}
}
return false;
}
/**
* Returns an array with the global settings for this plugin
* @return array Plugin settings as an array
*/
public function get_settings() {
if (is_null($this->settings)) {
$settings = api_get_settings_params(array("subkey = ? AND category = ? AND type = ? " =>
array($this->get_name(), 'Plugins', 'setting')));
$this->settings = $settings;
}
return $this->settings;
}
….
Part B / 1 Plugin.class.php
…
/**
* Tells whether language variables are defined for this plugin or not
* @param string System name of the plugin
* @return boolean True if the plugin has languag variables defined, false otherwise
*/
public function get_lang_plugin_exists($name) {
return isset($this->strings[$name]);
}
/**
* Hook for the get_lang() function to check for plugin-defined language terms
* @param string Name of the language variable we are looking for
* @return string The translated language term of the plugin
*/
public function get_lang($name) {
// Check whether the language strings for the plugin have already been
// loaded. If so, no need to load them again.
if (is_null($this->strings)) {
global $language_interface;
$root = api_get_path(SYS_PLUGIN_PATH);
$plugin_name = $this->get_name();
//1. Loading english if exists
$english_path = $root.$plugin_name."/lang/english.php";
if (is_readable($english_path)) {
include $english_path;
$this->strings = $strings;
}
….
Part B / 1 Plugin.class.php
…
/**
* Caller for the install_course_fields() function
* @param int The course's integer ID
* @param boolean Whether to add a tool link on the course homepage
* @return void
*/
function course_install($course_id, $add_tool_link = true) {
$this->install_course_fields($course_id, $add_tool_link);
}
/**
* Add course settings and, if not asked otherwise, add a tool link on the course homepage
* @param int Course integer ID
* @param boolean Whether to add a tool link or not (some tools might just offer a configuration
section and act on the backend)
* @return boolean False on error, null otherwise
*/
public function install_course_fields($course_id, $add_tool_link = true) {
$plugin_name = $this->get_name();
$t_course = Database::get_course_table(TABLE_COURSE_SETTING);
….
Part B / 1
Roles

Plugin.lib.php

➔
Part B / 1 Plugin.lib.php
<?php
/* See license terms in /license.txt */
class AppPlugin {
var $plugin_regions = array (
//
'loginpage_main',
'login_top',
'login_bottom',
'menu_top',
'menu_bottom',
/*
'campushomepage_main',
'campushomepage_menu',
'mycourses_main',
'mycourses_menu',*/
'content_top',
'content_bottom',
'header_main',
'header_center',
'header_left',
'header_right',
//'footer',
'footer_left',
'footer_center',
'footer_right',
'course_tool_plugin'
);
…...
Part B / 1 Plugin.lib.php
…...
function __construct() {
}

{

function read_plugins_from_path() {
/* We scan the plugin directory. Each folder is a potential plugin. */
$pluginpath = api_get_path(SYS_PLUGIN_PATH);
$possible_plugins = array();
$handle = @opendir($pluginpath);
while (false !== ($file = readdir($handle))) {
if ($file != '.' && $file != '..' && is_dir(api_get_path(SYS_PLUGIN_PATH).$file))
$possible_plugins[] = $file;

}

}
}
@closedir($handle);
sort($possible_plugins);
return $possible_plugins;

function get_installed_plugins_by_region(){
$used_plugins = array();
/* We retrieve all the active plugins. */
$result = api_get_settings('Plugins');
foreach ($result as $row) {
$used_plugins[$row['variable']][] = $row['selected_value'];
}
return $used_plugins;
}
….
Part B / 1 Plugin.lib.php
…...
function get_installed_plugins() {
$installed_plugins = array();
$plugin_array = api_get_settings_params(array("variable = ? AND selected_value = ? AND category = ? " =>
array('status', 'installed', 'Plugins')));

}

if (!empty($plugin_array)) {
foreach ($plugin_array as $row) {
$installed_plugins[$row['subkey']] = true;
}
$installed_plugins = array_keys($installed_plugins);
}
return $installed_plugins;

function install($plugin_name, $access_url_id = null) {
if (empty($access_url_id)) {
$access_url_id = api_get_current_access_url_id();
} else {
$access_url_id = intval($access_url_id);
}
api_add_setting('installed', 'status', $plugin_name, 'setting', 'Plugins', $plugin_name, null, null, null, $access_url_id, 1);
//api_add_setting($plugin, $area, $plugin, null, 'Plugins', $plugin, null, null, null, $_configuration['access_url'], 1);
$pluginpath = api_get_path(SYS_PLUGIN_PATH).$plugin_name.'/install.php';

}
….

if (is_file($pluginpath) && is_readable($pluginpath)) {
//execute the install procedure
require $pluginpath;
}
Part B / 1 Plugin.lib.php
…...
function uninstall($plugin_name, $access_url_id = null) {
if (empty($access_url_id)) {
$access_url_id = api_get_current_access_url_id();
} else {
$access_url_id = intval($access_url_id);
}
api_delete_settings_params(array('category = ? AND access_url = ? AND subkey = ? ' =>
array('Plugins', $access_url_id, $plugin_name)));
$pluginpath = api_get_path(SYS_PLUGIN_PATH).$plugin_name.'/uninstall.php';
if (is_file($pluginpath) && is_readable($pluginpath)) {
//execute the uninstall procedure
require $pluginpath;
}
}
function get_areas_by_plugin($plugin_name) {
$result = api_get_settings('Plugins');
$areas = array();
foreach ($result as $row) {
if ($plugin_name == $row['selected_value']) {
$areas[] = $row['variable'];
}
}
return $areas;
}
function is_valid_plugin_location($location) {
return in_array($location, $this->plugin_list);
}
function is_valid_plugin($plugin_name) {
if (is_dir(api_get_path(SYS_PLUGIN_PATH).$plugin_name)) {
if (is_file(api_get_path(SYS_PLUGIN_PATH).$plugin_name.'/index.php')) {
return true;
}
}
return false;
}
….
Part B / 1 Plugin.lib.php
…...
function load_region($region, $main_template, $forced = false) {
if ($region == 'course_tool_plugin') {
return null;
}
ob_start();
$this->get_all_plugin_contents_by_region($region, $main_template, $forced);
$content = ob_get_contents();
ob_end_clean();
return $content;
}
/**
* Loads the translation files inside a plugin if exists. It loads by default english see the hello world plugin
*
* @todo add caching
* @param string $plugin_name
*/
function load_plugin_lang_variables($plugin_name) {
global $language_interface;
$root = api_get_path(SYS_PLUGIN_PATH);
//1. Loading english if exists
$english_path = $root.$plugin_name."/lang/english.php";
….
Part B / 1 Plugin.lib.php
…...
*/
function get_all_plugin_contents_by_region($region, $template, $forced = false) {
global $_plugins;
if (isset($_plugins[$region]) && is_array($_plugins[$region])) {
//if (1) {
//Load the plugin information
foreach ($_plugins[$region] as $plugin_name) {
//The plugin_info variable is available inside the plugin index
$plugin_info = $this->get_plugin_info($plugin_name, $forced);
//We also know where the plugin is
$plugin_info['current_region'] = $region;
// Loading the plugin/XXX/index.php file
$plugin_file = api_get_path(SYS_PLUGIN_PATH)."$plugin_name/index.php";
….
Part B / 1 Plugin.lib.php
…...
/**
* Loads plugin info
* @staticvar array $plugin_data
* @param string plugin name
* @param bool load from DB or from the static array
* @todo filter setting_form
* @return array
*/
function get_plugin_info($plugin_name, $forced = false) {
static $plugin_data = array();
if (isset($plugin_data[$plugin_name]) && $forced == false) {
return $plugin_data[$plugin_name];
} else {
$plugin_file = api_get_path(SYS_PLUGIN_PATH)."$plugin_name/plugin.php";
$plugin_info = array();
if (file_exists($plugin_file)) {
require $plugin_file;
}
//extra options
$plugin_settings = api_get_settings_params(array("subkey = ? AND category = ? AND type = ? " =>
array($plugin_name, 'Plugins','setting')));
$settings_filtered = array();
foreach ($plugin_settings as $item) {
$settings_filtered[$item['variable']] = $item['selected_value'];
}
$plugin_info['settings'] = $settings_filtered;
$plugin_data[$plugin_name] = $plugin_info;
return $plugin_info;
}
….

}
Part B / 1 Plugin.lib.php
…...
/*
* Get the template list
*/
function get_templates_list($plugin_name) {
$plugin_info = $this->get_plugin_info($plugin_name);
if (isset($plugin_info) && isset($plugin_info['templates'])) {
return $plugin_info['templates'];
} else {
return false;
}
}
….
/*
* Add a plugin to a region
*/
function add_to_region($plugin, $region) {
$access_url_id = api_get_current_access_url_id();
api_add_setting($plugin, $region, $plugin, 'region', 'Plugins', $plugin, null, null, null, $access_url_id, 1);
}
function install_course_plugins($course_id) {
$plugin_list = $this->get_installed_plugins();

…...

if (!empty($plugin_list)) {
foreach ($plugin_list as $plugin_name) {
$plugin_path = api_get_path(SYS_PLUGIN_PATH).$plugin_name.'/plugin.php';
if (file_exists($plugin_path)) {
require_once $plugin_path;
if (isset($plugin_info) && isset($plugin_info['plugin_class'])) {
$plugin_info['plugin_class']::create()->course_install($course_id);
}
}
}
}
Part B / 1 Plugin.lib.php

…...
function add_course_settings_form($form)
…....
function set_course_settings_defaults(& $values) {
…..
function save_course_settings($values) {
…...
/**
* Gets a nice array of keys for just the plugin's course settings
* @param string The plugin ID
* @return array Nice array of keys for course settings
*/
public function get_plugin_course_settings($plugin_name) {
…...
Part B / 1
General Plugin Pattern-Model

Development Pattern

➔
Part B / 1
Foundamental Files

Plugin.php
Index.php

Readme.txt
Part B / 1
Optional Files

Uninstall.php
Template.tpl

*.css and other
resources
Part B / 1
Plugin Develop Pattern
Create the foundamental and optional files
Put this files in a directory named
“MyPluginName”
Copy this directory in chamilo plugin
directory
Activate plugin in Plugin List Panel as
Admin
Part B / 2

Simple Plugin Creation Example

➔

Teacher List Plugin
Part B / 2 Teacher Plugin
Part B / 2 Teacher Plugin
Part B / 2 Teacher Plugin
Part B / 2 Teacher Plugin
Part B / 2 Teacher Plugin
Part B / 2 Teacher Plugin
Admin Panel / Plugin SubPanel
Part B / 2 Teacher Plugin
Plugin List
Part B / 2 Teacher Plugin
Part B / 2 Teacher Plugin
Part B / 2 Teacher Plugin
Part B / 2 Teacher Plugin
User list
Part B / 2 Teacher Plugin
Conclusion

Pattern Model
➔
Improvements
➔
Conclusion / Pattern Model
Create a plugin is very simple
There are necessary steps and
optional steps
Plugin creation is now a question of
planning what to do and knowing
chamilo functions and DB
Conclusion / Improvements
Create a Plugin Management System
Improve php files
Complete Uninstall.php role
Give more simple Api Package
plugin-oriented
Contact

Giuliano Mandotti

Member of Chamilo
Association

info@giulianomandotti.com
Thank you!

¡Muchas Gracias!

Weitere ähnliche Inhalte

Was ist angesagt?

PHP traits, treat or threat?
PHP traits, treat or threat?PHP traits, treat or threat?
PHP traits, treat or threat?Nick Belhomme
 
Rapid application development using Akeeba FOF and Joomla 3.2
Rapid application development using Akeeba FOF and Joomla 3.2Rapid application development using Akeeba FOF and Joomla 3.2
Rapid application development using Akeeba FOF and Joomla 3.2Tim Plummer
 
Python Flask Tutorial For Beginners | Flask Web Development Tutorial | Python...
Python Flask Tutorial For Beginners | Flask Web Development Tutorial | Python...Python Flask Tutorial For Beginners | Flask Web Development Tutorial | Python...
Python Flask Tutorial For Beginners | Flask Web Development Tutorial | Python...Edureka!
 
Django - Python MVC Framework
Django - Python MVC FrameworkDjango - Python MVC Framework
Django - Python MVC FrameworkBala Kumar
 
Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8Michelangelo van Dam
 
Rails vs Web2py
Rails vs Web2pyRails vs Web2py
Rails vs Web2pyjonromero
 
A new way to develop with WordPress!
A new way to develop with WordPress!A new way to develop with WordPress!
A new way to develop with WordPress!David Sanchez
 
Developing a Joomla 3.x Component using RAD FOF- Part 1: Back-end - Joomladay...
Developing a Joomla 3.x Component using RAD FOF- Part 1: Back-end - Joomladay...Developing a Joomla 3.x Component using RAD FOF- Part 1: Back-end - Joomladay...
Developing a Joomla 3.x Component using RAD FOF- Part 1: Back-end - Joomladay...Peter Martin
 
Lean Php Presentation
Lean Php PresentationLean Php Presentation
Lean Php PresentationAlan Pinstein
 
Introduction to PHP
Introduction to PHPIntroduction to PHP
Introduction to PHPBradley Holt
 
Beginners PHP Tutorial
Beginners PHP TutorialBeginners PHP Tutorial
Beginners PHP Tutorialalexjones89
 
Flask Introduction - Python Meetup
Flask Introduction - Python MeetupFlask Introduction - Python Meetup
Flask Introduction - Python MeetupAreski Belaid
 

Was ist angesagt? (20)

PHP traits, treat or threat?
PHP traits, treat or threat?PHP traits, treat or threat?
PHP traits, treat or threat?
 
PHP7 Presentation
PHP7 PresentationPHP7 Presentation
PHP7 Presentation
 
Flask Basics
Flask BasicsFlask Basics
Flask Basics
 
Rapid application development using Akeeba FOF and Joomla 3.2
Rapid application development using Akeeba FOF and Joomla 3.2Rapid application development using Akeeba FOF and Joomla 3.2
Rapid application development using Akeeba FOF and Joomla 3.2
 
Python Flask Tutorial For Beginners | Flask Web Development Tutorial | Python...
Python Flask Tutorial For Beginners | Flask Web Development Tutorial | Python...Python Flask Tutorial For Beginners | Flask Web Development Tutorial | Python...
Python Flask Tutorial For Beginners | Flask Web Development Tutorial | Python...
 
Php Presentation
Php PresentationPhp Presentation
Php Presentation
 
Overview of PHP and MYSQL
Overview of PHP and MYSQLOverview of PHP and MYSQL
Overview of PHP and MYSQL
 
Django - Python MVC Framework
Django - Python MVC FrameworkDjango - Python MVC Framework
Django - Python MVC Framework
 
Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8
 
The new features of PHP 7
The new features of PHP 7The new features of PHP 7
The new features of PHP 7
 
Php mysql ppt
Php mysql pptPhp mysql ppt
Php mysql ppt
 
Introduction to PHP
Introduction to PHPIntroduction to PHP
Introduction to PHP
 
Rails vs Web2py
Rails vs Web2pyRails vs Web2py
Rails vs Web2py
 
A new way to develop with WordPress!
A new way to develop with WordPress!A new way to develop with WordPress!
A new way to develop with WordPress!
 
Php ppt
Php pptPhp ppt
Php ppt
 
Developing a Joomla 3.x Component using RAD FOF- Part 1: Back-end - Joomladay...
Developing a Joomla 3.x Component using RAD FOF- Part 1: Back-end - Joomladay...Developing a Joomla 3.x Component using RAD FOF- Part 1: Back-end - Joomladay...
Developing a Joomla 3.x Component using RAD FOF- Part 1: Back-end - Joomladay...
 
Lean Php Presentation
Lean Php PresentationLean Php Presentation
Lean Php Presentation
 
Introduction to PHP
Introduction to PHPIntroduction to PHP
Introduction to PHP
 
Beginners PHP Tutorial
Beginners PHP TutorialBeginners PHP Tutorial
Beginners PHP Tutorial
 
Flask Introduction - Python Meetup
Flask Introduction - Python MeetupFlask Introduction - Python Meetup
Flask Introduction - Python Meetup
 

Andere mochten auch

Desarrollo del plugin Chamilo-Wordpress
Desarrollo del plugin Chamilo-WordpressDesarrollo del plugin Chamilo-Wordpress
Desarrollo del plugin Chamilo-WordpressYannick Warnier
 
Chamilo advantages against other LMSes
Chamilo advantages against other LMSesChamilo advantages against other LMSes
Chamilo advantages against other LMSesYannick Warnier
 
Chamilo para-desarrolladores-1.9
Chamilo para-desarrolladores-1.9Chamilo para-desarrolladores-1.9
Chamilo para-desarrolladores-1.9Chamilo Association
 
Modulo de trabajo plataforma virtual chamilo
Modulo de trabajo plataforma virtual chamiloModulo de trabajo plataforma virtual chamilo
Modulo de trabajo plataforma virtual chamiloguillermo rojas
 
Calidad de código en Chamilo: Behat, Travis-CI y Scrutinizer-CI
Calidad de código en Chamilo: Behat, Travis-CI y Scrutinizer-CICalidad de código en Chamilo: Behat, Travis-CI y Scrutinizer-CI
Calidad de código en Chamilo: Behat, Travis-CI y Scrutinizer-CIYannick Warnier
 
Chamilo, c'est pas le Pérou - Jeudis du libre
Chamilo, c'est pas le Pérou - Jeudis du libreChamilo, c'est pas le Pérou - Jeudis du libre
Chamilo, c'est pas le Pérou - Jeudis du libreYannick Warnier
 
Programa Chamilo Conference
Programa Chamilo ConferencePrograma Chamilo Conference
Programa Chamilo ConferenceMichela Mosquera
 
Presentacion sobre Chamilo en OpenExpo
Presentacion sobre Chamilo en OpenExpoPresentacion sobre Chamilo en OpenExpo
Presentacion sobre Chamilo en OpenExpoContidos Dixitais
 
Aprendizaje 2 0: NTIC en la Educación
Aprendizaje 2 0: NTIC en la EducaciónAprendizaje 2 0: NTIC en la Educación
Aprendizaje 2 0: NTIC en la EducaciónCarlos Lizarraga
 
Day 3: LMS Chamilo como caso de éxito en las diferentes unidades de negocio d...
Day 3: LMS Chamilo como caso de éxito en las diferentes unidades de negocio d...Day 3: LMS Chamilo como caso de éxito en las diferentes unidades de negocio d...
Day 3: LMS Chamilo como caso de éxito en las diferentes unidades de negocio d...Chamilo Association
 

Andere mochten auch (11)

Desarrollo del plugin Chamilo-Wordpress
Desarrollo del plugin Chamilo-WordpressDesarrollo del plugin Chamilo-Wordpress
Desarrollo del plugin Chamilo-Wordpress
 
Chamilo advantages against other LMSes
Chamilo advantages against other LMSesChamilo advantages against other LMSes
Chamilo advantages against other LMSes
 
Chamilo para-desarrolladores-1.9
Chamilo para-desarrolladores-1.9Chamilo para-desarrolladores-1.9
Chamilo para-desarrolladores-1.9
 
Modulo de trabajo plataforma virtual chamilo
Modulo de trabajo plataforma virtual chamiloModulo de trabajo plataforma virtual chamilo
Modulo de trabajo plataforma virtual chamilo
 
Calidad de código en Chamilo: Behat, Travis-CI y Scrutinizer-CI
Calidad de código en Chamilo: Behat, Travis-CI y Scrutinizer-CICalidad de código en Chamilo: Behat, Travis-CI y Scrutinizer-CI
Calidad de código en Chamilo: Behat, Travis-CI y Scrutinizer-CI
 
Chamilo, c'est pas le Pérou - Jeudis du libre
Chamilo, c'est pas le Pérou - Jeudis du libreChamilo, c'est pas le Pérou - Jeudis du libre
Chamilo, c'est pas le Pérou - Jeudis du libre
 
Programa Chamilo Conference
Programa Chamilo ConferencePrograma Chamilo Conference
Programa Chamilo Conference
 
Presentacion sobre Chamilo en OpenExpo
Presentacion sobre Chamilo en OpenExpoPresentacion sobre Chamilo en OpenExpo
Presentacion sobre Chamilo en OpenExpo
 
Aprendizaje 2 0: NTIC en la Educación
Aprendizaje 2 0: NTIC en la EducaciónAprendizaje 2 0: NTIC en la Educación
Aprendizaje 2 0: NTIC en la Educación
 
Day 3: LMS Chamilo como caso de éxito en las diferentes unidades de negocio d...
Day 3: LMS Chamilo como caso de éxito en las diferentes unidades de negocio d...Day 3: LMS Chamilo como caso de éxito en las diferentes unidades de negocio d...
Day 3: LMS Chamilo como caso de éxito en las diferentes unidades de negocio d...
 
Qué es Chamilo - Ventajas y desventajas
Qué es Chamilo - Ventajas y desventajasQué es Chamilo - Ventajas y desventajas
Qué es Chamilo - Ventajas y desventajas
 

Ähnlich wie Chamiluda Madrid 2013 Chamilo Plugin Creation

CICON2010: Adam Griffiths - CodeIgniter 2
CICON2010: Adam Griffiths - CodeIgniter 2CICON2010: Adam Griffiths - CodeIgniter 2
CICON2010: Adam Griffiths - CodeIgniter 2CodeIgniter Conference
 
Using and reusing CakePHP plugins
Using and reusing CakePHP pluginsUsing and reusing CakePHP plugins
Using and reusing CakePHP pluginsPierre MARTIN
 
Zend Framework 1.9 Setup & Using Zend_Tool
Zend Framework 1.9 Setup & Using Zend_ToolZend Framework 1.9 Setup & Using Zend_Tool
Zend Framework 1.9 Setup & Using Zend_ToolGordon Forsythe
 
Quality Use Of Plugin
Quality Use Of PluginQuality Use Of Plugin
Quality Use Of PluginYasuo Harada
 
Magento Live Australia 2016: Request Flow
Magento Live Australia 2016: Request FlowMagento Live Australia 2016: Request Flow
Magento Live Australia 2016: Request FlowVrann Tulika
 
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)arcware
 
Using Geeklog as a Web Application Framework
Using Geeklog as a Web Application FrameworkUsing Geeklog as a Web Application Framework
Using Geeklog as a Web Application FrameworkDirk Haun
 
Create a web-app with Cgi Appplication
Create a web-app with Cgi AppplicationCreate a web-app with Cgi Appplication
Create a web-app with Cgi Appplicationolegmmiller
 
Catalyst patterns-yapc-eu-2016
Catalyst patterns-yapc-eu-2016Catalyst patterns-yapc-eu-2016
Catalyst patterns-yapc-eu-2016John Napiorkowski
 
The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010Fabien Potencier
 
Developing Drizzle Replication Plugins
Developing Drizzle Replication PluginsDeveloping Drizzle Replication Plugins
Developing Drizzle Replication PluginsPadraig O'Sullivan
 
6048618 cloning-procedure-of-r12-single-tier
6048618 cloning-procedure-of-r12-single-tier6048618 cloning-procedure-of-r12-single-tier
6048618 cloning-procedure-of-r12-single-tierbalaji29
 
Perl web frameworks
Perl web frameworksPerl web frameworks
Perl web frameworksdiego_k
 
Curscatalyst
CurscatalystCurscatalyst
CurscatalystKar Juan
 
What's New In Laravel 5
What's New In Laravel 5What's New In Laravel 5
What's New In Laravel 5Darren Craig
 
Best Practices in Plugin Development (WordCamp Seattle)
Best Practices in Plugin Development (WordCamp Seattle)Best Practices in Plugin Development (WordCamp Seattle)
Best Practices in Plugin Development (WordCamp Seattle)andrewnacin
 
"Full Stack frameworks or a story about how to reconcile Front (good) and Bac...
"Full Stack frameworks or a story about how to reconcile Front (good) and Bac..."Full Stack frameworks or a story about how to reconcile Front (good) and Bac...
"Full Stack frameworks or a story about how to reconcile Front (good) and Bac...Fwdays
 

Ähnlich wie Chamiluda Madrid 2013 Chamilo Plugin Creation (20)

CICON2010: Adam Griffiths - CodeIgniter 2
CICON2010: Adam Griffiths - CodeIgniter 2CICON2010: Adam Griffiths - CodeIgniter 2
CICON2010: Adam Griffiths - CodeIgniter 2
 
Using and reusing CakePHP plugins
Using and reusing CakePHP pluginsUsing and reusing CakePHP plugins
Using and reusing CakePHP plugins
 
Zend Framework 1.9 Setup & Using Zend_Tool
Zend Framework 1.9 Setup & Using Zend_ToolZend Framework 1.9 Setup & Using Zend_Tool
Zend Framework 1.9 Setup & Using Zend_Tool
 
Quality Use Of Plugin
Quality Use Of PluginQuality Use Of Plugin
Quality Use Of Plugin
 
Magento Live Australia 2016: Request Flow
Magento Live Australia 2016: Request FlowMagento Live Australia 2016: Request Flow
Magento Live Australia 2016: Request Flow
 
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
 
Mojolicious
MojoliciousMojolicious
Mojolicious
 
Using Geeklog as a Web Application Framework
Using Geeklog as a Web Application FrameworkUsing Geeklog as a Web Application Framework
Using Geeklog as a Web Application Framework
 
Create a web-app with Cgi Appplication
Create a web-app with Cgi AppplicationCreate a web-app with Cgi Appplication
Create a web-app with Cgi Appplication
 
Catalyst patterns-yapc-eu-2016
Catalyst patterns-yapc-eu-2016Catalyst patterns-yapc-eu-2016
Catalyst patterns-yapc-eu-2016
 
The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010
 
Developing Drizzle Replication Plugins
Developing Drizzle Replication PluginsDeveloping Drizzle Replication Plugins
Developing Drizzle Replication Plugins
 
6048618 cloning-procedure-of-r12-single-tier
6048618 cloning-procedure-of-r12-single-tier6048618 cloning-procedure-of-r12-single-tier
6048618 cloning-procedure-of-r12-single-tier
 
Perl web frameworks
Perl web frameworksPerl web frameworks
Perl web frameworks
 
Curscatalyst
CurscatalystCurscatalyst
Curscatalyst
 
What's New In Laravel 5
What's New In Laravel 5What's New In Laravel 5
What's New In Laravel 5
 
Writing Pluggable Software
Writing Pluggable SoftwareWriting Pluggable Software
Writing Pluggable Software
 
Best Practices in Plugin Development (WordCamp Seattle)
Best Practices in Plugin Development (WordCamp Seattle)Best Practices in Plugin Development (WordCamp Seattle)
Best Practices in Plugin Development (WordCamp Seattle)
 
"Full Stack frameworks or a story about how to reconcile Front (good) and Bac...
"Full Stack frameworks or a story about how to reconcile Front (good) and Bac..."Full Stack frameworks or a story about how to reconcile Front (good) and Bac...
"Full Stack frameworks or a story about how to reconcile Front (good) and Bac...
 
Catalyst MVC
Catalyst MVCCatalyst MVC
Catalyst MVC
 

Mehr von Chamilo Association

3er Congreso Internacional E-learning
3er Congreso Internacional E-learning3er Congreso Internacional E-learning
3er Congreso Internacional E-learningChamilo Association
 
Recomendación ¿Cómo seleccionar un LMS?
Recomendación ¿Cómo seleccionar un LMS?Recomendación ¿Cómo seleccionar un LMS?
Recomendación ¿Cómo seleccionar un LMS?Chamilo Association
 
Day 3: Skillms para RRHH: Capacita, Evalúa y Gestiona el talento en tu organi...
Day 3: Skillms para RRHH: Capacita, Evalúa y Gestiona el talento en tu organi...Day 3: Skillms para RRHH: Capacita, Evalúa y Gestiona el talento en tu organi...
Day 3: Skillms para RRHH: Capacita, Evalúa y Gestiona el talento en tu organi...Chamilo Association
 
Day 3: Rompiendo paradigmas: ¡Hay un mundo más allá de Moodle!
Day 3: Rompiendo paradigmas: ¡Hay un mundo más allá de Moodle! Day 3: Rompiendo paradigmas: ¡Hay un mundo más allá de Moodle!
Day 3: Rompiendo paradigmas: ¡Hay un mundo más allá de Moodle! Chamilo Association
 
Day 3: ¿Tu campus virtual es seguro? ¿Cómo ir un paso adelante de los hackers?
Day 3: ¿Tu campus virtual es seguro? ¿Cómo ir un paso adelante de los hackers? Day 3: ¿Tu campus virtual es seguro? ¿Cómo ir un paso adelante de los hackers?
Day 3: ¿Tu campus virtual es seguro? ¿Cómo ir un paso adelante de los hackers? Chamilo Association
 
Day 3: ¿Cómo llevar un curso presencial a B-learning?
Day 3: ¿Cómo llevar un curso presencial a B-learning?Day 3: ¿Cómo llevar un curso presencial a B-learning?
Day 3: ¿Cómo llevar un curso presencial a B-learning?Chamilo Association
 
Day 2: Chamilo en Europa: Programa de formación para alumnos que trabajan
Day 2: Chamilo en Europa: Programa de formación para alumnos que trabajanDay 2: Chamilo en Europa: Programa de formación para alumnos que trabajan
Day 2: Chamilo en Europa: Programa de formación para alumnos que trabajanChamilo Association
 
Day 2: ¿Cómo personalizar mi Campus Virtual?
Day 2: ¿Cómo personalizar mi Campus Virtual?Day 2: ¿Cómo personalizar mi Campus Virtual?
Day 2: ¿Cómo personalizar mi Campus Virtual?Chamilo Association
 
Day 2: Mobile learning “Aplicación nativa Chamilo”
Day 2: Mobile learning “Aplicación nativa Chamilo”Day 2: Mobile learning “Aplicación nativa Chamilo”
Day 2: Mobile learning “Aplicación nativa Chamilo”Chamilo Association
 
Day 3: ¿Cómo transformar su portal Chamilo LMS en tienda on-line colaborativa?
Day 3: ¿Cómo transformar su portal Chamilo LMS en tienda on-line colaborativa? Day 3: ¿Cómo transformar su portal Chamilo LMS en tienda on-line colaborativa?
Day 3: ¿Cómo transformar su portal Chamilo LMS en tienda on-line colaborativa? Chamilo Association
 
Day 3: MOOCs de Salud en Chamilo LMS
Day 3: MOOCs de Salud en Chamilo LMS Day 3: MOOCs de Salud en Chamilo LMS
Day 3: MOOCs de Salud en Chamilo LMS Chamilo Association
 
Day 3: Aplicaciones de software libre integradas al eLearning: uso de mapas c...
Day 3: Aplicaciones de software libre integradas al eLearning: uso de mapas c...Day 3: Aplicaciones de software libre integradas al eLearning: uso de mapas c...
Day 3: Aplicaciones de software libre integradas al eLearning: uso de mapas c...Chamilo Association
 
Day 2: ¿Es posible impartir educación de calidad sin acceso a Internet?
 Day 2: ¿Es posible impartir educación de calidad sin acceso a Internet? Day 2: ¿Es posible impartir educación de calidad sin acceso a Internet?
Day 2: ¿Es posible impartir educación de calidad sin acceso a Internet?Chamilo Association
 
Day 2: Herramienta de evaluaciones aplicado al sistema nacional de bachillera...
Day 2: Herramienta de evaluaciones aplicado al sistema nacional de bachillera...Day 2: Herramienta de evaluaciones aplicado al sistema nacional de bachillera...
Day 2: Herramienta de evaluaciones aplicado al sistema nacional de bachillera...Chamilo Association
 
Day 2: ¿Cómo realizar un guión instruccional para crear contenidos multimedia...
Day 2: ¿Cómo realizar un guión instruccional para crear contenidos multimedia...Day 2: ¿Cómo realizar un guión instruccional para crear contenidos multimedia...
Day 2: ¿Cómo realizar un guión instruccional para crear contenidos multimedia...Chamilo Association
 
Day 2: Creación de crucigramas en Chamilo LMS con HotPotatoes
Day 2: Creación de crucigramas en Chamilo LMS con HotPotatoes Day 2: Creación de crucigramas en Chamilo LMS con HotPotatoes
Day 2: Creación de crucigramas en Chamilo LMS con HotPotatoes Chamilo Association
 
Day 2: Explicación Actividades Chamilo Conference 2016
Day 2: Explicación Actividades Chamilo Conference 2016Day 2: Explicación Actividades Chamilo Conference 2016
Day 2: Explicación Actividades Chamilo Conference 2016Chamilo Association
 
Day 2: Chamilo en Perú: Experiencia de 8 años usando Chamilo LMS
Day 2: Chamilo en Perú: Experiencia de 8 años usando Chamilo LMS Day 2: Chamilo en Perú: Experiencia de 8 años usando Chamilo LMS
Day 2: Chamilo en Perú: Experiencia de 8 años usando Chamilo LMS Chamilo Association
 
Day 2: Conferencia Magistral: Visión de Chamilo al 2020
Day 2: Conferencia Magistral: Visión de Chamilo al 2020 Day 2: Conferencia Magistral: Visión de Chamilo al 2020
Day 2: Conferencia Magistral: Visión de Chamilo al 2020 Chamilo Association
 

Mehr von Chamilo Association (20)

3er Congreso Internacional E-learning
3er Congreso Internacional E-learning3er Congreso Internacional E-learning
3er Congreso Internacional E-learning
 
Recomendación ¿Cómo seleccionar un LMS?
Recomendación ¿Cómo seleccionar un LMS?Recomendación ¿Cómo seleccionar un LMS?
Recomendación ¿Cómo seleccionar un LMS?
 
Chamilo LMS 1.11.4 ¡Novedades!
Chamilo LMS 1.11.4 ¡Novedades!Chamilo LMS 1.11.4 ¡Novedades!
Chamilo LMS 1.11.4 ¡Novedades!
 
Day 3: Skillms para RRHH: Capacita, Evalúa y Gestiona el talento en tu organi...
Day 3: Skillms para RRHH: Capacita, Evalúa y Gestiona el talento en tu organi...Day 3: Skillms para RRHH: Capacita, Evalúa y Gestiona el talento en tu organi...
Day 3: Skillms para RRHH: Capacita, Evalúa y Gestiona el talento en tu organi...
 
Day 3: Rompiendo paradigmas: ¡Hay un mundo más allá de Moodle!
Day 3: Rompiendo paradigmas: ¡Hay un mundo más allá de Moodle! Day 3: Rompiendo paradigmas: ¡Hay un mundo más allá de Moodle!
Day 3: Rompiendo paradigmas: ¡Hay un mundo más allá de Moodle!
 
Day 3: ¿Tu campus virtual es seguro? ¿Cómo ir un paso adelante de los hackers?
Day 3: ¿Tu campus virtual es seguro? ¿Cómo ir un paso adelante de los hackers? Day 3: ¿Tu campus virtual es seguro? ¿Cómo ir un paso adelante de los hackers?
Day 3: ¿Tu campus virtual es seguro? ¿Cómo ir un paso adelante de los hackers?
 
Day 3: ¿Cómo llevar un curso presencial a B-learning?
Day 3: ¿Cómo llevar un curso presencial a B-learning?Day 3: ¿Cómo llevar un curso presencial a B-learning?
Day 3: ¿Cómo llevar un curso presencial a B-learning?
 
Day 2: Chamilo en Europa: Programa de formación para alumnos que trabajan
Day 2: Chamilo en Europa: Programa de formación para alumnos que trabajanDay 2: Chamilo en Europa: Programa de formación para alumnos que trabajan
Day 2: Chamilo en Europa: Programa de formación para alumnos que trabajan
 
Day 2: ¿Cómo personalizar mi Campus Virtual?
Day 2: ¿Cómo personalizar mi Campus Virtual?Day 2: ¿Cómo personalizar mi Campus Virtual?
Day 2: ¿Cómo personalizar mi Campus Virtual?
 
Day 2: Mobile learning “Aplicación nativa Chamilo”
Day 2: Mobile learning “Aplicación nativa Chamilo”Day 2: Mobile learning “Aplicación nativa Chamilo”
Day 2: Mobile learning “Aplicación nativa Chamilo”
 
Day 3: ¿Cómo transformar su portal Chamilo LMS en tienda on-line colaborativa?
Day 3: ¿Cómo transformar su portal Chamilo LMS en tienda on-line colaborativa? Day 3: ¿Cómo transformar su portal Chamilo LMS en tienda on-line colaborativa?
Day 3: ¿Cómo transformar su portal Chamilo LMS en tienda on-line colaborativa?
 
Day 3: MOOCs de Salud en Chamilo LMS
Day 3: MOOCs de Salud en Chamilo LMS Day 3: MOOCs de Salud en Chamilo LMS
Day 3: MOOCs de Salud en Chamilo LMS
 
Day 3: Aplicaciones de software libre integradas al eLearning: uso de mapas c...
Day 3: Aplicaciones de software libre integradas al eLearning: uso de mapas c...Day 3: Aplicaciones de software libre integradas al eLearning: uso de mapas c...
Day 3: Aplicaciones de software libre integradas al eLearning: uso de mapas c...
 
Day 2: ¿Es posible impartir educación de calidad sin acceso a Internet?
 Day 2: ¿Es posible impartir educación de calidad sin acceso a Internet? Day 2: ¿Es posible impartir educación de calidad sin acceso a Internet?
Day 2: ¿Es posible impartir educación de calidad sin acceso a Internet?
 
Day 2: Herramienta de evaluaciones aplicado al sistema nacional de bachillera...
Day 2: Herramienta de evaluaciones aplicado al sistema nacional de bachillera...Day 2: Herramienta de evaluaciones aplicado al sistema nacional de bachillera...
Day 2: Herramienta de evaluaciones aplicado al sistema nacional de bachillera...
 
Day 2: ¿Cómo realizar un guión instruccional para crear contenidos multimedia...
Day 2: ¿Cómo realizar un guión instruccional para crear contenidos multimedia...Day 2: ¿Cómo realizar un guión instruccional para crear contenidos multimedia...
Day 2: ¿Cómo realizar un guión instruccional para crear contenidos multimedia...
 
Day 2: Creación de crucigramas en Chamilo LMS con HotPotatoes
Day 2: Creación de crucigramas en Chamilo LMS con HotPotatoes Day 2: Creación de crucigramas en Chamilo LMS con HotPotatoes
Day 2: Creación de crucigramas en Chamilo LMS con HotPotatoes
 
Day 2: Explicación Actividades Chamilo Conference 2016
Day 2: Explicación Actividades Chamilo Conference 2016Day 2: Explicación Actividades Chamilo Conference 2016
Day 2: Explicación Actividades Chamilo Conference 2016
 
Day 2: Chamilo en Perú: Experiencia de 8 años usando Chamilo LMS
Day 2: Chamilo en Perú: Experiencia de 8 años usando Chamilo LMS Day 2: Chamilo en Perú: Experiencia de 8 años usando Chamilo LMS
Day 2: Chamilo en Perú: Experiencia de 8 años usando Chamilo LMS
 
Day 2: Conferencia Magistral: Visión de Chamilo al 2020
Day 2: Conferencia Magistral: Visión de Chamilo al 2020 Day 2: Conferencia Magistral: Visión de Chamilo al 2020
Day 2: Conferencia Magistral: Visión de Chamilo al 2020
 

Kürzlich hochgeladen

Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGSujit Pal
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 

Kürzlich hochgeladen (20)

Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAG
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 

Chamiluda Madrid 2013 Chamilo Plugin Creation

  • 3. Summary Introduction ➔ Part A ➔ 1) Presenting 2 Plugin's Example ➔ 2) Deeper Analysis of the 2 plugins ➔ Part B ➔ 1) General Plugin Pattern-Model ➔ 2) Simple Plugin Creation example ➔ Conclusion ➔
  • 7. Where does Chamilo come from? Claroline Dokeos Dokeos Latinoamérica 2001 2004 2007 1.0 Chamilo LMS 1.8 2010 Chamilo LMS 1.9 2012
  • 8. Chamilo 1.9.6 still is... A Learning Management System ➔ A system to help manage learning. ➔ A system to help to manage knowledge ➔ Improves informal learning eficiency ➔ Improves learning monitoring ➔ Improves the way documents are kept ➔ Improves availability of courses ➔ Reduces costs and training times ➔
  • 9. Part A 1) Presenting 2 Plugin's Example ➔ Show user information Plugin ➔ RSS Plugin ➔ 2) Deeper Analysis of the 2 plugins ➔
  • 10. Part A / 1 Plugin Examples Show user information Plugin ➔ RSS Plugin ➔
  • 11. Part A / 1 Plugin Examples Administration Panel
  • 12. Part A / 1 Plugin Examples Administration Panel / Plugin SubPanel
  • 13. Part A / 1 Plugin Examples Plugin List
  • 14. Part A / 1 Plugin Examples Show User Info ➔
  • 15. Part A / 1 Plugin Examples Plugin List
  • 16. Part A / 1 Plugin Show User Info
  • 17. Part A / 1 Plugin Show User Info
  • 18. Part A / 1 Plugin Show User Info
  • 19. Part A / 1 Plugin Examples RSS ➔
  • 20. Part A / 1 Plugin RSS Plugin List
  • 21. Part A / 1 Plugin RSS
  • 22. Part A / 1 Plugin RSS
  • 23. Part A / 1 Plugin RSS
  • 24. Part A / 2 Deeper Analysis Show user information Plugin ➔ RSS Plugin ➔
  • 25. Part A / 2 Plugin Deeper Analysis Show User Info ➔
  • 26. Part A / 2 Deeper Analysis Plugin Show User Info Chamilo Directory Plugin Directory
  • 27. Part A / 2 Deeper Analysis Plugin Show User Info
  • 28. Part A / 2 Deeper Analysis Plugin Show User Info
  • 29. Part A / 2 Deeper Analysis Plugin Show User Info
  • 30. Part A / 2 Deeper Analysis Plugin Show User Info
  • 31. Part A / 2 Deeper Analysis Plugin Show User Info
  • 32. Part A / 2 Deeper Analysis Plugin Show User Info
  • 33. Part A / 2 Plugin Deeper Analysis Rss ➔
  • 34. Part A / 2 Deeper Analysis RSS Chamilo Directory Plugin Directory
  • 35. Part A / 2 Deeper Analysis RSS
  • 36. Part A / 2 Deeper Analysis RSS
  • 37. Part A / 2 Deeper Analysis RSS
  • 38. Part A / 2 Deeper Analysis RSS
  • 39. Part A / 2 Deeper Analysis RSS
  • 40. Part A / 2 Deeper Analysis RSS
  • 41. Part A / 2 Deeper Analysis RSS
  • 42. Part A / 2 Deeper Analysis RSS
  • 43. Part A / 2 Deeper Analysis RSS
  • 44. Part B 1) General Plugin Pattern-Model ➔ 2) Simple Plugin Creation example ➔
  • 45. Part B / 1 General Plugin Pattern-Model Important Files ➔ Roles ➔
  • 46. Part B / 1 General Plugin Pattern-Model Important Files ➔
  • 47. Part B / 1 Important Files Which are the most important files that Chamilo use to include Plugins?
  • 48. Part B / 1 Important Files Global.inc.php Settings.lib.php Settings.php Configure_plugin.php Plugin.class.php Plugin.lib.php
  • 49. Part B / 1 Important Files Where can we find them?
  • 50. Part B / 1 Important Files
  • 51. Part B / 1 Important Files
  • 52. Part B / 1 Important Files
  • 53. Part B / 1 Important Files
  • 54. Part B / 1 General Plugin Pattern-Model Roles ➔
  • 55. Part B / 1 Their Roles Which are their roles?
  • 56. Part B / 1 Roles Global.inc.php (part of) ➔
  • 57. Part B / 1 Global.inc.php ….... ….... Catch all the plugin's settings info
  • 58. Part B / 1 Roles Settings.lib.php ➔
  • 59. Part B / 1 Settings.lib.php <?php /* For licensing terms, see /license.txt */ …..... /** * This function allows easy activating and inactivating of regions * @author Julio Montoya <gugli100@gmail.com> Beeznest 2012 */ function handle_regions() { …........ } $plugin_obj = new AppPlugin(); $possible_plugins = $plugin_obj->read_plugins_from_path(); $installed_plugins = $plugin_obj->get_installed_plugins(); if (!empty($installed_plugins)) { $not_installed = array_diff($possible_plugins, $installed_plugins); } else { $not_installed = $possible_plugins; } echo '<form name="plugins" method="post" action="'.api_get_self().'?category='.Security::remove_XSS($_GET['category']).'">'; echo '<table class="data_table">'; echo '<tr>'; echo '<th width="400px">'; echo get_lang('Plugin'); echo '</th><th>'; echo get_lang('Regions'); …......
  • 60. Part B / 1 Settings.lib.php …... /* We display all the possible plugins and the checkboxes */ $plugin_region_list = array(); $my_plugin_list = $plugin_obj->get_plugin_regions(); foreach ($my_plugin_list as $plugin_item) { $plugin_region_list[$plugin_item] = $plugin_item; } ….....
  • 61. Part B / 1 Settings.lib.php …...... /** * This function allows easy activating and inactivating of plugins …..... function handle_plugins() { $plugin_obj = new AppPlugin(); if (isset($_POST['submit_plugins'])) { store_plugins(); // Add event to the system log. $user_id = api_get_user_id(); $category = $_GET['category']; event_system(LOG_CONFIGURATION_SETTINGS_CHANGE, LOG_CONFIGURATION_SETTINGS_CATEGORY, $category, api_get_utc_datetime(), $user_id); Display :: display_confirmation_message(get_lang('SettingsStored')); } $all_plugins = $plugin_obj->read_plugins_from_path(); $installed_plugins = $plugin_obj->get_installed_plugins(); …...... $plugin_list = array(); $my_plugin_list = $plugin_obj->get_plugin_regions(); foreach($my_plugin_list as $plugin_item) { $plugin_list[$plugin_item] = $plugin_item; }
  • 62. Part B / 1 Settings.lib.php foreach ($all_plugins as $plugin) { $plugin_info_file = api_get_path(SYS_PLUGIN_PATH).$plugin.'/plugin.php'; if (file_exists($plugin_info_file)) { $plugin_info = array(); require $plugin_info_file; if (in_array($plugin, $installed_plugins)) { echo '<tr class="row_selected">'; } else { echo '<tr>'; } echo '<td>'; //Checkbox if (in_array($plugin, $installed_plugins)) { echo '<input type="checkbox" name="plugin_'.$plugin.'[]" checked="checked">'; …...... echo '<h4>'.$plugin_info['title'].' <small>v '.$plugin_info['version'].'</small></h4>'; echo '<p>'.$plugin_info['comment'].'</p>'; echo '<p>'.get_lang('Author').': '.$plugin_info['author'].'</p>'; echo '<div class="btn-group">'; if (in_array($plugin, $installed_plugins)) { echo Display::url(get_lang('Configure'), 'configure_plugin.php?name='.$plugin, array('class' => 'btn')); echo Display::url(get_lang('Regions'), 'settings.php?category=Regions&name='.$plugin, array('class' => 'btn')); } if (file_exists(api_get_path(SYS_PLUGIN_PATH).$plugin.'/readme.txt')) { echo Display::url("readme.txt", api_get_path(WEB_PLUGIN_PATH).$plugin."/readme.txt", array('class' => 'btn ajax', '_target' => '_blank')); } …..... echo '</table>'; echo '<div class="form-actions bottom_actions">'; echo '<button class="save" type="submit" name="submit_plugins">'.get_lang('EnablePlugins').'</button>';
  • 63. Part B / 1 Settings.lib.php ….. function store_regions() { $plugin_obj = new AppPlugin(); // Get a list of all current 'Plugins' settings $installed_plugins = $plugin_obj->get_installed_plugins(); $shortlist_installed = array(); if (!empty($installed_plugins)) { foreach ($installed_plugins as $plugin) { if (isset($plugin['subkey'])) { $shortlist_installed[] = $plugin['subkey']; } } } $shortlist_installed = array_flip(array_flip($shortlist_installed)); $plugin_list = $plugin_obj->read_plugins_from_path(); foreach ($plugin_list as $plugin) { if (isset($_POST['plugin_'.$plugin])) { $areas_to_installed = $_POST['plugin_'.$plugin]; if (!empty($areas_to_installed)) { $plugin_obj->remove_all_regions($plugin); foreach ($areas_to_installed as $region) { if (!empty($region) && $region != '-1' ) { $plugin_obj->add_to_region($plugin, $region); } } ….......
  • 64. Part B / 1 Settings.lib.php ….. /** * This function allows easy activating and inactivating of plugins * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University */ function store_plugins() { $plugin_obj = new AppPlugin(); // Get a list of all current 'Plugins' settings $plugin_list = $plugin_obj->read_plugins_from_path(); $installed_plugins = array(); foreach ($plugin_list as $plugin) { if (isset($_POST['plugin_'.$plugin])) { $plugin_obj->install($plugin); $installed_plugins[] = $plugin; } } if (!empty($installed_plugins)) { $remove_plugins = array_diff($plugin_list, $installed_plugins); } else { $remove_plugins = $plugin_list; } foreach ($remove_plugins as $plugin) { $plugin_obj->uninstall($plugin); } } /** ….......
  • 65. Part B / 1 Settings.lib.php ….. function generate_settings_form($settings, $settings_by_access_list) { global $_configuration, $settings_to_avoid, $convert_byte_to_mega_list; $table_settings_current = Database :: get_main_table(TABLE_MAIN_SETTINGS_CURRENT); $form = new FormValidator('settings', 'post', 'settings.php?category='.Security::remove_XSS($_GET['category'])); $form->addElement('hidden', 'search_field', (!empty($_GET['search_field'])? Security::remove_XSS($_GET['search_field']):null)); $url_id = api_get_current_access_url_id(); if (!empty($_configuration['multiple_access_urls']) && api_is_global_platform_admin() && $url_id == 1) { $group = array(); $group[] = $form->createElement('button', 'mark_all', get_lang('MarkAll')); $group[] = $form->createElement('button', 'unmark_all', get_lang('UnmarkAll')); $form->addGroup($group, 'buttons_in_action_right'); …...
  • 66. Part B / 1 Roles Settings.php ➔
  • 67. Part B / 1 Settings.php <?php /* For licensing terms, see /license.txt */ /** * With this tool you can easily adjust non critical configuration settings. * Non critical means that changing them will not result in a broken campus. * * @author Patrick Cool * @author Julio Montoya - Multiple URL site * @package chamilo.admin */ …........ ….... // Database table definitions. $table_settings_current = Database :: get_main_table(TABLE_MAIN_SETTINGS_CURRENT); // Setting breadcrumbs. $interbreadcrumb[] = array('url' => 'index.php', 'name' => get_lang('PlatformAdmin')); // Setting the name of the tool. $tool_name = get_lang('PlatformConfigSettings'); if (empty($_GET['category'])) { $_GET['category'] = 'Platform'; } …....
  • 68. Part B / 1 Settings.php ….. $url_id = api_get_current_access_url_id(); $settings = null; function get_settings($category = null) { $url_id = api_get_current_access_url_id(); $settings_by_access_list = array(); if ($url_id == 1) { $settings = api_get_settings($category, 'group', $url_id); } else { $url_info = api_get_access_url($url_id); …...... // One more validation if is changeable. if ($row['access_url_changeable'] == 1) $settings_by_access_list[ $row['variable'] ] [ $row['subkey'] ] [ $row['category'] ] = $row; else $settings_by_access_list[ $row['variable'] ] [ $row['subkey'] ] [ $row['category'] ] = array(); } } } if (isset($category) && $category== 'search_setting') { if (!empty($_REQUEST['search_field'])) { $settings = search_setting($_REQUEST['search_field']); } } return array('settings' => $settings, 'settings_by_access_list' => $settings_by_access_list); } // Build the form. ….....
  • 69. Part B / 1 Settings.php …. // Including the header (banner). Display :: display_header($tool_name); // The action images. $action_images['platform'] = 'platform.png'; $action_images['course'] = 'course.png'; $action_images['session'] = 'session.png'; $action_images['tools'] = 'tools.png'; $action_images['user'] = 'user.png'; $action_images['gradebook'] = 'gradebook.png'; $action_images['ldap'] = 'ldap.png'; $action_images['cas'] = 'user_access.png'; $action_images['security'] = 'security.png'; $action_images['languages'] = 'languages.png'; $action_images['tuning'] = 'tuning.png'; $action_images['templates'] = 'template.png'; $action_images['search'] = 'search.png'; $action_images['editor'] = 'html_editor.png'; $action_images['timezones'] = 'timezone.png'; $action_images['extra'] = 'wizard.png'; $action_images['tracking'] = 'statistics.png'; $action_images['gradebook'] = 'gradebook.png'; $action_images['search'] = 'search.png'; $action_images['stylesheets'] = 'stylesheets.png'; $action_images['templates'] = 'template.png'; $action_images['plugins'] = 'plugins.png'; $action_images['shibboleth'] = 'shibboleth.png'; $action_images['facebook'] = 'facebook.png'; …...
  • 70. Part B / 1 Settings.php ... $action_array = array(); $resultcategories = array(); $resultcategories[] = array('category' => 'Platform'); $resultcategories[] = array('category' => 'Course'); $resultcategories[] = array('category' => 'Session'); $resultcategories[] = array('category' => 'Languages'); $resultcategories[] = array('category' => 'User'); $resultcategories[] = array('category' => 'Tools'); $resultcategories[] = array('category' => 'Editor'); $resultcategories[] = array('category' => 'Security'); $resultcategories[] = array('category' => 'Tuning'); $resultcategories[] = array('category' => 'Gradebook'); $resultcategories[] = array('category' => 'Timezones'); $resultcategories[] = array('category' => 'Tracking'); $resultcategories[] = array('category' => 'Search'); $resultcategories[] = array('category' => 'Stylesheets'); $resultcategories[] = array('category' => 'Templates'); $resultcategories[] = array('category' => 'Plugins'); $resultcategories[] = array('category' => 'LDAP'); $resultcategories[] = array('category' => 'CAS'); $resultcategories[] = array('category' => 'Shibboleth'); $resultcategories[] = array('category' => 'Facebook'); ….
  • 71. Part B / 1 Settings.php … if (!empty($_GET['category'])) { switch ($_GET['category']) { case 'Regions': handle_regions(); break; case 'Plugins': // Displaying the extensions: Plugins. // This will be available to all the sites (access_urls). if (isset($_POST['submit_dashboard_plugins'])) { $affected_rows = DashboardManager::store_dashboard_plugins($_POST); if ($affected_rows) { // add event to system log $user_id = api_get_user_id(); $category = $_GET['category']; event_system(LOG_CONFIGURATION_SETTINGS_CHANGE, LOG_CONFIGURATION_SETTINGS_CATEGORY, $category, api_get_utc_datetime(), $user_id); Display :: display_confirmation_message(get_lang('DashboardPluginsHaveBeenUpdatedSucesslly')); } ….... echo '<div id="tabs">'; echo '<ul>'; echo '<li><a href="#tabs-1">'.get_lang('Plugins').'</a></li>'; echo '<li><a href="#tabs-2">'.get_lang('DashboardPlugins').'</a></li>'; echo '<li><a href="#tabs-3">'.get_lang('ConfigureExtensions').'</a></li>'; echo '</ul>'; echo '<div id="tabs-1">'; handle_plugins(); echo '</div>'; echo '<div id="tabs-2">'; DashboardManager::handle_dashboard_plugins(); echo '</div>'; echo '<div id="tabs-3">'; handle_extensions(); echo '</div>'; …....
  • 72. Part B / 1 Roles Config_plugin.php ➔
  • 73. Part B / 1 Config_plugin.php <?php /* For licensing terms, see /license.txt */ /............ // name of the language file that needs to be included $language_file = array ('registration','admin'); $cidReset = true; require_once '../inc/global.inc.php'; // Access restrictions api_protect_admin_script(); $plugin_name = $_GET['name']; $plugin_obj = new AppPlugin(); $plugin_info = $plugin_obj->get_plugin_info($plugin_name, true); if (empty($plugin_info)) { api_not_allowed(); } $installed_plugins = $plugin_obj->get_installed_plugins(); if (!in_array($plugin_name, $installed_plugins)) { api_not_allowed(); } global $_configuration;
  • 74. Part B / 1 Config_plugin.php $content = null; if (isset($plugin_info['settings_form'])) { $form = $plugin_info['settings_form']; if (isset($form)) { //We override the form attributes …........ } } else { $message = Display::return_message(get_lang('NoConfigurationSettingsForThisPlugin'), 'warning'); } if (isset($form)) { if ($form->validate()) { $values = $form->exportValues(); //api_delete_category_settings_by_subkey($plugin_name); $access_url_id = api_get_current_access_url_id(); api_delete_settings_params(array('category = ? AND access_url = ? AND subkey = ? AND type = ? and variable <> ?' => array('Plugins', $access_url_id, $plugin_name, 'setting', "status"))); foreach ($values as $key => $value) { $key = Database::escape_string($plugin_name.'_'.$key); api_add_setting($value, $key, $plugin_name, 'setting', 'Plugins', $plugin_name, null, null, null, $_configuration['access_url'], 1); } $message = Display::return_message(get_lang('Updated'), 'success'); } } $tpl = new Template($tool_name, true, true, false, true, false); $tpl->assign('actions', $actions); $tpl->assign('message', $message); $tpl->assign('content', $content); $tpl->display_one_col_template();
  • 75. Part B / 1 Roles Plugin.class.php ➔
  • 76. Part B / 1 Plugin.class.php <?php /* For licensing terms, see /license.txt */ /** * Base class for plugins * * This class has to be extended by every plugin. It defines basic methods ….... */ class Plugin { protected $version = ''; protected $author = ''; protected $fields = array(); private $settings = null; private $strings = null; //translation strings public $is_course_plugin = false; /** * When creating a new course, these settings are added to the course, in * the course_info/infocours.php * To show the plugin course icons you need to add these icons: * main/img/icons/22/plugin_name.png * main/img/icons/64/plugin_name.png * main/img/icons/64/plugin_name_na.png * @example * $course_settings = array( array('name' => 'big_blue_button_welcome_message', 'type' => 'text'), array('name' => 'big_blue_button_record_and_store', 'type' => 'checkbox') ); */ ….....
  • 77. Part B / 1 Plugin.class.php …. public $course_settings = array(); /** * This indicates whether changing the setting should execute the callback * function. */ public $course_settings_callback = false; /** * Default constructor for the plugin class. By default, it only sets * a few attributes of the object * @param string Version of this plugin * @param string Author of this plugin * @param array Array of global settings to be proposed to configure the plugin * @return void */ protected function __construct($version, $author, $settings = array()) { $this->version = $version; $this->author = $author; $this->fields = $settings; global $language_files; $language_files[] = 'plugin_' . $this->get_name(); } /** …..
  • 78. Part B / 1 Plugin.class.php … /** * Gets an array of information about this plugin (name, version, ...) * @return array Array of information elements about this plugin */ function get_info() { $result = array(); $result['title'] = $this->get_title(); $result['comment'] = $this->get_comment(); $result['version'] = $this->get_version(); $result['author'] = $this->get_author(); $result['plugin_class'] = get_class($this); $result['is_course_plugin'] = $this->is_course_plugin; if ($form = $this->get_settings_form()) { $result['settings_form'] = $form; foreach ($this->fields as $name => $type) { $value = $this->get($name); $result[$name] = $value; } } return $result; } /** * Returns the "system" name of the plugin in lowercase letters * @param string Name of the plugin */ function get_name() { $result = get_class($this); $result = str_replace('Plugin', '', $result); $result = strtolower($result); return $result; } /** ….
  • 79. Part B / 1 Plugin.class.php … /** * Returns the title of the plugin * @param string Title of the plugin */ function get_title() { return $this->get_lang('plugin_title'); } /** * Returns the description of the plugin * @param string Description of the plugin */ function get_comment() { return $this->get_lang('plugin_comment'); } /** * Returns the version of the plugin * @param string Version of the plugin */ function get_version() { return $this->version; } /** * Returns the author of the plugin * @param string Author(s) of the plugin */ function get_author() { return $this->author; } ….
  • 80. Part B / 1 Plugin.class.php … /** * Returns the contents of the CSS defined by the plugin * @param string The CSS string */ function get_css() { $name = $this->get_name(); $path = api_get_path(SYS_PLUGIN_PATH)."$name/resources/$name.css"; if (!is_readable($path)) { return ''; } $css = array(); $css[] = file_get_contents($path); $result = implode($css); return $result; } /** * Returns an HTML form (generated by FormValidator) of the plugin settings * @return string FormValidator-generated form */ function get_settings_form() { $result = new FormValidator($this->get_name()); $defaults = array(); foreach ($this->fields as $name => $type) { $value = $this->get($name); $defaults[$name] = $value; $type = isset($type) ? $type : 'text'; $help = null; if ($this->get_lang_plugin_exists($name.'_help')) { $help = $this->get_lang($name.'_help'); } switch ($type) { ….
  • 81. Part B / 1 Plugin.class.php … /** * Returns the value of a given plugin global setting * @param string Name of the plugin * @return string Value of the plugin */ function get($name) { $settings = $this->get_settings(); foreach ($settings as $setting) { if ($setting['variable'] == ($this->get_name() . '_' . $name)) { return $setting['selected_value']; } } return false; } /** * Returns an array with the global settings for this plugin * @return array Plugin settings as an array */ public function get_settings() { if (is_null($this->settings)) { $settings = api_get_settings_params(array("subkey = ? AND category = ? AND type = ? " => array($this->get_name(), 'Plugins', 'setting'))); $this->settings = $settings; } return $this->settings; } ….
  • 82. Part B / 1 Plugin.class.php … /** * Tells whether language variables are defined for this plugin or not * @param string System name of the plugin * @return boolean True if the plugin has languag variables defined, false otherwise */ public function get_lang_plugin_exists($name) { return isset($this->strings[$name]); } /** * Hook for the get_lang() function to check for plugin-defined language terms * @param string Name of the language variable we are looking for * @return string The translated language term of the plugin */ public function get_lang($name) { // Check whether the language strings for the plugin have already been // loaded. If so, no need to load them again. if (is_null($this->strings)) { global $language_interface; $root = api_get_path(SYS_PLUGIN_PATH); $plugin_name = $this->get_name(); //1. Loading english if exists $english_path = $root.$plugin_name."/lang/english.php"; if (is_readable($english_path)) { include $english_path; $this->strings = $strings; } ….
  • 83. Part B / 1 Plugin.class.php … /** * Caller for the install_course_fields() function * @param int The course's integer ID * @param boolean Whether to add a tool link on the course homepage * @return void */ function course_install($course_id, $add_tool_link = true) { $this->install_course_fields($course_id, $add_tool_link); } /** * Add course settings and, if not asked otherwise, add a tool link on the course homepage * @param int Course integer ID * @param boolean Whether to add a tool link or not (some tools might just offer a configuration section and act on the backend) * @return boolean False on error, null otherwise */ public function install_course_fields($course_id, $add_tool_link = true) { $plugin_name = $this->get_name(); $t_course = Database::get_course_table(TABLE_COURSE_SETTING); ….
  • 84. Part B / 1 Roles Plugin.lib.php ➔
  • 85. Part B / 1 Plugin.lib.php <?php /* See license terms in /license.txt */ class AppPlugin { var $plugin_regions = array ( // 'loginpage_main', 'login_top', 'login_bottom', 'menu_top', 'menu_bottom', /* 'campushomepage_main', 'campushomepage_menu', 'mycourses_main', 'mycourses_menu',*/ 'content_top', 'content_bottom', 'header_main', 'header_center', 'header_left', 'header_right', //'footer', 'footer_left', 'footer_center', 'footer_right', 'course_tool_plugin' ); …...
  • 86. Part B / 1 Plugin.lib.php …... function __construct() { } { function read_plugins_from_path() { /* We scan the plugin directory. Each folder is a potential plugin. */ $pluginpath = api_get_path(SYS_PLUGIN_PATH); $possible_plugins = array(); $handle = @opendir($pluginpath); while (false !== ($file = readdir($handle))) { if ($file != '.' && $file != '..' && is_dir(api_get_path(SYS_PLUGIN_PATH).$file)) $possible_plugins[] = $file; } } } @closedir($handle); sort($possible_plugins); return $possible_plugins; function get_installed_plugins_by_region(){ $used_plugins = array(); /* We retrieve all the active plugins. */ $result = api_get_settings('Plugins'); foreach ($result as $row) { $used_plugins[$row['variable']][] = $row['selected_value']; } return $used_plugins; } ….
  • 87. Part B / 1 Plugin.lib.php …... function get_installed_plugins() { $installed_plugins = array(); $plugin_array = api_get_settings_params(array("variable = ? AND selected_value = ? AND category = ? " => array('status', 'installed', 'Plugins'))); } if (!empty($plugin_array)) { foreach ($plugin_array as $row) { $installed_plugins[$row['subkey']] = true; } $installed_plugins = array_keys($installed_plugins); } return $installed_plugins; function install($plugin_name, $access_url_id = null) { if (empty($access_url_id)) { $access_url_id = api_get_current_access_url_id(); } else { $access_url_id = intval($access_url_id); } api_add_setting('installed', 'status', $plugin_name, 'setting', 'Plugins', $plugin_name, null, null, null, $access_url_id, 1); //api_add_setting($plugin, $area, $plugin, null, 'Plugins', $plugin, null, null, null, $_configuration['access_url'], 1); $pluginpath = api_get_path(SYS_PLUGIN_PATH).$plugin_name.'/install.php'; } …. if (is_file($pluginpath) && is_readable($pluginpath)) { //execute the install procedure require $pluginpath; }
  • 88. Part B / 1 Plugin.lib.php …... function uninstall($plugin_name, $access_url_id = null) { if (empty($access_url_id)) { $access_url_id = api_get_current_access_url_id(); } else { $access_url_id = intval($access_url_id); } api_delete_settings_params(array('category = ? AND access_url = ? AND subkey = ? ' => array('Plugins', $access_url_id, $plugin_name))); $pluginpath = api_get_path(SYS_PLUGIN_PATH).$plugin_name.'/uninstall.php'; if (is_file($pluginpath) && is_readable($pluginpath)) { //execute the uninstall procedure require $pluginpath; } } function get_areas_by_plugin($plugin_name) { $result = api_get_settings('Plugins'); $areas = array(); foreach ($result as $row) { if ($plugin_name == $row['selected_value']) { $areas[] = $row['variable']; } } return $areas; } function is_valid_plugin_location($location) { return in_array($location, $this->plugin_list); } function is_valid_plugin($plugin_name) { if (is_dir(api_get_path(SYS_PLUGIN_PATH).$plugin_name)) { if (is_file(api_get_path(SYS_PLUGIN_PATH).$plugin_name.'/index.php')) { return true; } } return false; } ….
  • 89. Part B / 1 Plugin.lib.php …... function load_region($region, $main_template, $forced = false) { if ($region == 'course_tool_plugin') { return null; } ob_start(); $this->get_all_plugin_contents_by_region($region, $main_template, $forced); $content = ob_get_contents(); ob_end_clean(); return $content; } /** * Loads the translation files inside a plugin if exists. It loads by default english see the hello world plugin * * @todo add caching * @param string $plugin_name */ function load_plugin_lang_variables($plugin_name) { global $language_interface; $root = api_get_path(SYS_PLUGIN_PATH); //1. Loading english if exists $english_path = $root.$plugin_name."/lang/english.php"; ….
  • 90. Part B / 1 Plugin.lib.php …... */ function get_all_plugin_contents_by_region($region, $template, $forced = false) { global $_plugins; if (isset($_plugins[$region]) && is_array($_plugins[$region])) { //if (1) { //Load the plugin information foreach ($_plugins[$region] as $plugin_name) { //The plugin_info variable is available inside the plugin index $plugin_info = $this->get_plugin_info($plugin_name, $forced); //We also know where the plugin is $plugin_info['current_region'] = $region; // Loading the plugin/XXX/index.php file $plugin_file = api_get_path(SYS_PLUGIN_PATH)."$plugin_name/index.php"; ….
  • 91. Part B / 1 Plugin.lib.php …... /** * Loads plugin info * @staticvar array $plugin_data * @param string plugin name * @param bool load from DB or from the static array * @todo filter setting_form * @return array */ function get_plugin_info($plugin_name, $forced = false) { static $plugin_data = array(); if (isset($plugin_data[$plugin_name]) && $forced == false) { return $plugin_data[$plugin_name]; } else { $plugin_file = api_get_path(SYS_PLUGIN_PATH)."$plugin_name/plugin.php"; $plugin_info = array(); if (file_exists($plugin_file)) { require $plugin_file; } //extra options $plugin_settings = api_get_settings_params(array("subkey = ? AND category = ? AND type = ? " => array($plugin_name, 'Plugins','setting'))); $settings_filtered = array(); foreach ($plugin_settings as $item) { $settings_filtered[$item['variable']] = $item['selected_value']; } $plugin_info['settings'] = $settings_filtered; $plugin_data[$plugin_name] = $plugin_info; return $plugin_info; } …. }
  • 92. Part B / 1 Plugin.lib.php …... /* * Get the template list */ function get_templates_list($plugin_name) { $plugin_info = $this->get_plugin_info($plugin_name); if (isset($plugin_info) && isset($plugin_info['templates'])) { return $plugin_info['templates']; } else { return false; } } …. /* * Add a plugin to a region */ function add_to_region($plugin, $region) { $access_url_id = api_get_current_access_url_id(); api_add_setting($plugin, $region, $plugin, 'region', 'Plugins', $plugin, null, null, null, $access_url_id, 1); } function install_course_plugins($course_id) { $plugin_list = $this->get_installed_plugins(); …... if (!empty($plugin_list)) { foreach ($plugin_list as $plugin_name) { $plugin_path = api_get_path(SYS_PLUGIN_PATH).$plugin_name.'/plugin.php'; if (file_exists($plugin_path)) { require_once $plugin_path; if (isset($plugin_info) && isset($plugin_info['plugin_class'])) { $plugin_info['plugin_class']::create()->course_install($course_id); } } } }
  • 93. Part B / 1 Plugin.lib.php …... function add_course_settings_form($form) ….... function set_course_settings_defaults(& $values) { ….. function save_course_settings($values) { …... /** * Gets a nice array of keys for just the plugin's course settings * @param string The plugin ID * @return array Nice array of keys for course settings */ public function get_plugin_course_settings($plugin_name) { …...
  • 94. Part B / 1 General Plugin Pattern-Model Development Pattern ➔
  • 95. Part B / 1 Foundamental Files Plugin.php Index.php Readme.txt
  • 96. Part B / 1 Optional Files Uninstall.php Template.tpl *.css and other resources
  • 97. Part B / 1 Plugin Develop Pattern Create the foundamental and optional files Put this files in a directory named “MyPluginName” Copy this directory in chamilo plugin directory Activate plugin in Plugin List Panel as Admin
  • 98. Part B / 2 Simple Plugin Creation Example ➔ Teacher List Plugin
  • 99. Part B / 2 Teacher Plugin
  • 100. Part B / 2 Teacher Plugin
  • 101. Part B / 2 Teacher Plugin
  • 102. Part B / 2 Teacher Plugin
  • 103. Part B / 2 Teacher Plugin
  • 104. Part B / 2 Teacher Plugin Admin Panel / Plugin SubPanel
  • 105. Part B / 2 Teacher Plugin Plugin List
  • 106. Part B / 2 Teacher Plugin
  • 107. Part B / 2 Teacher Plugin
  • 108. Part B / 2 Teacher Plugin
  • 109. Part B / 2 Teacher Plugin User list
  • 110. Part B / 2 Teacher Plugin
  • 112. Conclusion / Pattern Model Create a plugin is very simple There are necessary steps and optional steps Plugin creation is now a question of planning what to do and knowing chamilo functions and DB
  • 113. Conclusion / Improvements Create a Plugin Management System Improve php files Complete Uninstall.php role Give more simple Api Package plugin-oriented
  • 114. Contact Giuliano Mandotti Member of Chamilo Association info@giulianomandotti.com