diff --git a/main/inc/lib/elfinder/connectorAction.php b/main/inc/lib/elfinder/connectorAction.php
new file mode 100644
index 0000000000..74456e8051
--- /dev/null
+++ b/main/inc/lib/elfinder/connectorAction.php
@@ -0,0 +1,25 @@
+setDriverList($driverList);
+
+$operations = $connector->getOperations();
+
+// Run elFinder
+$finder = new Finder($operations);
+$elFinderConnector = new \elFinderConnector($finder);
+$elFinderConnector->run();
diff --git a/main/inc/lib/elfinder/filemanager.php b/main/inc/lib/elfinder/filemanager.php
new file mode 100644
index 0000000000..f42dc9346e
--- /dev/null
+++ b/main/inc/lib/elfinder/filemanager.php
@@ -0,0 +1,7 @@
+display('default/javascript/editor/ckeditor/elfinder.tpl');
diff --git a/main/inc/lib/elfinder/templates.php b/main/inc/lib/elfinder/templates.php
new file mode 100644
index 0000000000..8e970c0d17
--- /dev/null
+++ b/main/inc/lib/elfinder/templates.php
@@ -0,0 +1,17 @@
+simpleFormatTemplates($templates);
+$template->assign('templates', $templates);
+$template->display('default/javascript/editor/ckeditor/templates.tpl');
diff --git a/main/inc/lib/formvalidator/Element/html_editor.php b/main/inc/lib/formvalidator/Element/html_editor.php
index dfc070c55d..f2bafb59f6 100755
--- a/main/inc/lib/formvalidator/Element/html_editor.php
+++ b/main/inc/lib/formvalidator/Element/html_editor.php
@@ -1,125 +1,98 @@
_persistantFreeze = true;
$this->_type = 'html_editor';
- $this->fullPage = false;
- $name = $this->getAttribute('name');
- $this->fck_editor = new FCKeditor($name);
-
- $this->fck_editor->ToolbarSet = $fck_attribute['ToolbarSet'];
- $this->fck_editor->Width = !empty($fck_attribute['Width']) ? $fck_attribute['Width'] : '990';
- $this->fck_editor->Height = !empty($fck_attribute['Height']) ? $fck_attribute['Height'] : '400';
- //We get the optionnals config parameters in $fck_attribute array
- $this->fck_editor->Config = !empty($fck_attribute['Config']) ? $fck_attribute['Config'] : array();
+ global $fck_attribute;
- // This is an alternative (a better) way to pass configuration data to the editor.
- if (is_array($config)) {
- foreach ($config as $key => $value) {
- $this->fck_editor->Config[$key] = $config[$key];
- }
- if (isset($config['ToolbarSet'])) {
- $this->fck_editor->ToolbarSet = $config['ToolbarSet'];
- }
- if (isset($config['Width'])) {
- $this->fck_editor->Width = $config['Width'];
- }
- if (isset($config['Height'])) {
- $this->fck_editor->Height = $config['Height'];
- }
- if (isset($config['FullPage'])) {
- $this->fullPage = is_bool($config['FullPage']) ? $config['FullPage'] : ($config['FullPage'] === 'true');
- }
+ //$editor = Container::getHtmlEditor();
+ $editor = new CkEditor();
+ if ($editor) {
+ $this->editor = $editor;
+ $this->editor->setName($name);
+ $this->editor->processConfig($fck_attribute);
+ $this->editor->processConfig($config);
}
}
- /**
- * Check if the browser supports FCKeditor
- *
- * @access public
- * @return boolean
- */
- function browserSupported() {
- return FCKeditor :: IsCompatible();
- }
-
/**
* Return the HTML editor in HTML
* @return string
*/
- function toHtml() {
+ public function toHtml()
+ {
$value = $this->getValue();
- if ($this->fullPage) {
- if (strlen(trim($value)) == 0) {
- // TODO: To be considered whether here to be added DOCTYPE, language and character set declarations.
- $value = '
';
- $this->setValue($value);
+ if ($this->editor) {
+ if ($this->editor->getConfigAttribute('fullPage')) {
+ if (strlen(trim($value)) == 0) {
+ // TODO: To be considered whether here to be added DOCTYPE, language and character set declarations.
+ $value = '';
+ $this->setValue($value);
+ }
}
}
- if ($this->_flagFrozen) {
+
+ if ($this->isFrozen()) {
return $this->getFrozenHtml();
} else {
- return $this->build_FCKeditor();
+ return $this->buildEditor();
}
}
/**
- * Returns the htmlarea content in HTML
+ * Returns the html area content in HTML
* @return string
*/
- function getFrozenHtml() {
+ public function getFrozenHtml()
+ {
return $this->getValue();
}
/**
- * Build this element using FCKeditor
+ * @return string
*/
- function build_FCKeditor() {
- if (!FCKeditor :: IsCompatible()) {
- return parent::toHTML();
- }
- $this->fck_editor->Value = $this->getValue();
- $result = $this->fck_editor->CreateHtml();
-
- if (isset($this->fck_editor->Config['LoadAsciiMath'])) {
- if (isset($_SESSION['ascii_math_loaded']) &&
- $_SESSION['ascii_math_loaded'] == false
- ) {
- $result .= $this->fck_editor->Config['LoadAsciiMath'];
- $_SESSION['ascii_math_loaded'] = true;
- }
+ public function buildEditor()
+ {
+ $result = '';
+ if ($this->editor) {
+ $this->editor->value = $this->getValue();
+ $this->editor->setName($this->getName());
+ $result = $this->editor->createHtml();
}
- //Add a link to open the allowed html tags window
- //$result .= 'fullPage ? '1' : '0')."','MyWindow','toolbar=no,location=no,directories=no,status=yes,menubar=no,scrollbars=yes,resizable=yes,width=500,height=600,left=200,top=20'".'); return false;">'.get_lang('AllowedHTMLTags').'';
return $result;
}
}
diff --git a/main/inc/lib/formvalidator/FormValidator.class.php b/main/inc/lib/formvalidator/FormValidator.class.php
index b23df384e8..252b68e0ac 100755
--- a/main/inc/lib/formvalidator/FormValidator.class.php
+++ b/main/inc/lib/formvalidator/FormValidator.class.php
@@ -1,9 +1,6 @@
addElement('html_editor', $name, $label, 'rows="15" cols="80"', $config);
$this->applyFilter($name, 'trim');
- $html_type = STUDENT_HTML;
- if (!empty($_SESSION['status'])) {
- $html_type = $_SESSION['status'] == COURSEMANAGER ? TEACHER_HTML : STUDENT_HTML;
- }
- if (is_array($config)) {
- if (isset($config['FullPage'])) {
- $full_page = is_bool($config['FullPage']) ? $config['FullPage'] : ($config['FullPage'] === 'true');
- } else {
- $config['FullPage'] = $full_page;
- }
- } else {
- $config = array('FullPage' => (bool) $full_page);
- }
- if ($full_page) {
- $html_type = isset($_SESSION['status']) && $_SESSION['status'] == COURSEMANAGER ? TEACHER_HTML_FULLPAGE : STUDENT_HTML_FULLPAGE;
- //First *filter* the HTML (markup, indenting, ...)
- //$this->applyFilter($name,'html_filter_teacher_fullpage');
- } else {
- //First *filter* the HTML (markup, indenting, ...)
- //$this->applyFilter($name,'html_filter_teacher');
- }
if ($required) {
$this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
}
- if ($full_page) {
- $el = $this->getElement($name);
- $el->fullPage = true;
+
+ /** @var HTML_QuickForm_html_editor $element */
+ $element = $this->getElement($name);
+
+ if ($element->editor) {
+ $element->editor->processConfig($config);
}
- // Add rule to check not-allowed HTML
- //$this->addRule($name, get_lang('SomeHTMLNotAllowed'), 'html', $html_type);
}
/**
diff --git a/main/inc/lib/template.lib.php b/main/inc/lib/template.lib.php
index 8ab7e14191..65f6f23511 100755
--- a/main/inc/lib/template.lib.php
+++ b/main/inc/lib/template.lib.php
@@ -1,9 +1,6 @@
hide_global_chat = $hide_global_chat;
$this->load_plugins = $load_plugins;
- // Twig settings
- Twig_Autoloader::register();
-
$template_paths = array(
api_get_path(SYS_CODE_PATH).'template', //template folder
api_get_path(SYS_PLUGIN_PATH) //plugin folder
@@ -437,6 +431,7 @@ class Template
//Setting app paths/URLs
$_p = array(
'web' => api_get_path(WEB_PATH),
+ 'web_relative' => api_get_path(REL_PATH),
'web_course' => api_get_path(WEB_COURSE_PATH),
'web_main' => api_get_path(WEB_CODE_PATH),
'web_css' => api_get_path(WEB_CSS_PATH),
@@ -475,13 +470,12 @@ class Template
$this->theme = $this->preview_theme;
}
- //Base CSS
+ // Base CSS
$css[] = api_get_cdn_path(api_get_path(WEB_CSS_PATH).'base.css');
- //Default CSS responsive design
+ // Default CSS responsive design
$css[] = api_get_cdn_path(api_get_path(WEB_CSS_PATH).'bootstrap-responsive.css');
-
//Extra CSS files
$css[] = api_get_path(WEB_LIBRARY_PATH).'javascript/thickbox.css';
$css[] = api_get_path(WEB_LIBRARY_PATH).'javascript/chosen/chosen.css';
@@ -582,6 +576,8 @@ class Template
foreach ($js_files as $js_file) {
$js_file_to_string .= api_get_js($js_file);
}
+ // @todo fix this path
+ $js_file_to_string .= '';
//Loading email_editor js
if (!api_is_anonymous() && api_get_setting('allow_email_editor') == 'true') {
diff --git a/main/newscorm/lp_add_item.php b/main/newscorm/lp_add_item.php
index c184063e8e..3ff2394fac 100755
--- a/main/newscorm/lp_add_item.php
+++ b/main/newscorm/lp_add_item.php
@@ -125,6 +125,12 @@ $(function() {
window.location.href = $(\'a\', this).attr(\'href\');
});
});
+
+$(document).on("ready", function() {
+ CKEDITOR.on("instanceReady", function (e) {
+ showTemplates();
+ });
+});
';
/* Constants and variables */
@@ -250,7 +256,7 @@ $message = isset($_REQUEST['message']) ? $_REQUEST['message'] : null;
// Show the template list.
if ($type == 'document' && !isset($_GET['file'])) {
// Show the template list.
- echo '';
+ echo '';
}
echo '';
diff --git a/main/newscorm/lp_edit_item.php b/main/newscorm/lp_edit_item.php
index 0b53ec6c42..3e62e93cd5 100755
--- a/main/newscorm/lp_edit_item.php
+++ b/main/newscorm/lp_edit_item.php
@@ -12,7 +12,7 @@
* @package chamilo.learnpath
*/
/**
- * INIT SECTION
+ * INIT SECTION
*/
$this_section = SECTION_COURSES;
@@ -47,6 +47,11 @@ function InnerDialogLoaded() {
return B.ClickFrame();
$};'.$_SESSION['oLP']->get_js_dropdown_array().'
+$(document).on("ready", function() {
+ CKEDITOR.on("instanceReady", function (e) {
+ showTemplates();
+ });
+});
';
/* Constants and variables */
@@ -144,15 +149,15 @@ $path_parts = pathinfo($path_file);
if (Database::num_rows($res_doc) > 0 && $path_parts['extension'] == 'html') {
echo $_SESSION['oLP']->return_new_tree();
-
+
// Show the template list
echo '';
echo '
';
echo '';
} else {
- echo $_SESSION['oLP']->return_new_tree();
+ echo $_SESSION['oLP']->return_new_tree();
}
-
+
echo '';
echo '';
@@ -169,4 +174,4 @@ echo '
';
echo '';
/* FOOTER */
-Display::display_footer();
\ No newline at end of file
+Display::display_footer();
diff --git a/main/template/default/javascript/editor/ckeditor/config_js.tpl b/main/template/default/javascript/editor/ckeditor/config_js.tpl
new file mode 100644
index 0000000000..52d6cd8b84
--- /dev/null
+++ b/main/template/default/javascript/editor/ckeditor/config_js.tpl
@@ -0,0 +1,21 @@
+CKEDITOR.editorConfig = function( config ) {
+ // Define changes to default configuration here.
+ // For complete reference see:
+ // http://docs.ckeditor.com/#!/api/CKEDITOR.config
+
+ // Remove some buttons provided by the standard plugins, which are
+ // not needed in the Standard(s) toolbar.
+ config.removeButtons = 'Underline,Subscript,Superscript';
+
+ // Set the most common block elements.
+ config.format_tags = 'p;h1;h2;h3;pre';
+
+ // Simplify the dialog windows.
+ config.removeDialogTabs = 'image:advanced;link:advanced';
+
+ config.templates_files = [
+ '{{ _p.web_main ~ 'inc/lib/elfinder/templates.php'}}'
+ ];
+
+ config.customConfig = '{{ _p.web_main ~ 'inc/lib/javascript/ckeditor/config_js.php'}}';
+};
diff --git a/main/template/default/javascript/editor/ckeditor/elfinder.tpl b/main/template/default/javascript/editor/ckeditor/elfinder.tpl
new file mode 100644
index 0000000000..17137103c8
--- /dev/null
+++ b/main/template/default/javascript/editor/ckeditor/elfinder.tpl
@@ -0,0 +1,35 @@
+{% extends "default/layout/no_layout.tpl" %}
+
+{% block body %}
+ {% set finderFolder = _p.web ~ 'vendor/barryvdh/elfinder-builds/' %}
+
+
+
+
+
+
+
+
+
+
+
+{% endblock %}
diff --git a/main/template/default/javascript/editor/ckeditor/templates.tpl b/main/template/default/javascript/editor/ckeditor/templates.tpl
new file mode 100644
index 0000000000..5bbf1df89d
--- /dev/null
+++ b/main/template/default/javascript/editor/ckeditor/templates.tpl
@@ -0,0 +1,6 @@
+CKEDITOR.addTemplates("default",
+{
+ imagesPath: ' ',
+ templates:
+ {{ templates }}
+});
\ No newline at end of file
diff --git a/main/template/default/layout/footer.tpl b/main/template/default/layout/footer.tpl
index d3fdb29c11..6898883e29 100755
--- a/main/template/default/layout/footer.tpl
+++ b/main/template/default/layout/footer.tpl
@@ -59,7 +59,6 @@
{# Extra footer configured in admin section, only shown to non-admins #}
{{ footer_extra_content }}
-{% raw %}
{{ execution_stats }}
diff --git a/main/template/default/layout/head.tpl b/main/template/default/layout/head.tpl
index 0ff71c5678..28b572656b 100755
--- a/main/template/default/layout/head.tpl
+++ b/main/template/default/layout/head.tpl
@@ -15,11 +15,76 @@
{{ css_file_to_string }}
{{ css_style_print }}
{{ js_file_to_string }}
+
{{ extra_headers }}
";
+
+ return $html;
+ }
+
+ /**
+ * @param array $templates
+ *
+ * @return null
+ */
+ public function formatTemplates($templates)
+ {
+ if (empty($templates)) {
+ return null;
+ }
+ /** @var \Chamilo\CoreBundle\Entity\SystemTemplate $template */
+ $templateList = array();
+
+ $search = array('{CSS}', '{IMG_DIR}', '{REL_PATH}', '{COURSE_DIR}');
+ $replace = array(
+ '',
+ api_get_path(REL_CODE_PATH).'img/',
+ api_get_path(REL_PATH),
+ //api_get_path(REL_DEFAULT_COURSE_DOCUMENT_PATH),
+ //api_get_path(REL_DEFAULT_COURSE_DOCUMENT_PATH)
+ );
+
+ foreach ($templates as $template) {
+ $image = $template->getImage();
+ $image = !empty($image) ? $image : 'empty.gif';
+
+ $image = $this->urlGenerator->generate(
+ 'get_document_template_action',
+ array('file' => $image),
+ UrlGenerator::ABSOLUTE_URL
+ );
+
+ $content = str_replace($search, $replace, $template->getContent());
+
+ $templateList[] = array(
+ 'title' => $this->translator->trans($template->getTitle()),
+ 'description' => $this->translator->trans($template->getComment()),
+ 'image' => $image,
+ 'html' => $content
+ );
+ }
+
+ return json_encode($templateList);
+ }
+
+ /**
+ * @param array $templates
+ * @return null|string
+ */
+ public function simpleFormatTemplates($templates)
+ {
+ if (empty($templates)) {
+ return null;
+ }
+
+ $search = array('{CSS}', '{IMG_DIR}', '{REL_PATH}', '{COURSE_DIR}');
+ $replace = array(
+ '',
+ api_get_path(REL_CODE_PATH).'img/',
+ api_get_path(REL_PATH),
+ api_get_path(REL_DEFAULT_COURSE_DOCUMENT_PATH),
+ api_get_path(REL_DEFAULT_COURSE_DOCUMENT_PATH)
+ );
+
+ $templateList = array();
+
+ foreach ($templates as $template) {
+ $image = $template['image'];
+ $image = !empty($image) ? $image : 'empty.gif';
+ $image = api_get_path(WEB_PATH).'home/default_platform_document/template_thumb/'.$image;
+
+ /*$image = $this->urlGenerator->generate(
+ 'get_document_template_action',
+ array('file' => $image),
+ UrlGenerator::ABSOLUTE_URL
+ );*/
+
+ $content = str_replace($search, $replace, $template['content']);
+
+ $templateList[] = array(
+ 'title' => get_lang($template['title']),
+ 'description' => get_lang($template['comment']),
+ 'image' => $image,
+ 'html' => $content
+ );
+ }
+ //var_dump($templateList);
+ return json_encode($templateList);
+ }
+}
diff --git a/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/Basic.php b/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/Basic.php
new file mode 100644
index 0000000000..5ca5881898
--- /dev/null
+++ b/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/Basic.php
@@ -0,0 +1,106 @@
+ 'document', 'groups' =>array('mode', 'document', 'doctools')),
+ array('name' => 'clipboard', 'groups' =>array('clipboard', 'undo', )),
+ array('name' => 'editing', 'groups' =>array('clipboard', 'undo', )),
+ array('name' => 'forms', 'groups' =>array('clipboard', 'undo', )),
+ '/',
+ array('name' => 'basicstyles', 'groups' =>array('basicstyles', 'cleanup', )),
+ array('name' => 'paragraph', 'groups' =>array('list', 'indent', 'blocks', 'align' )),
+ array('name' => 'links'),
+ array('name' => 'insert'),
+ '/',
+ array('name' => 'styles'),
+ array('name' => 'colors'),
+ array('name' => 'tools'),
+ array('name' => 'others'),
+ array('name' => 'about')
+ );*/
+
+ $config['toolbarGroups'] = array(
+ //{ name: 'document', groups: [ 'mode', 'document', 'doctools' ] },
+ array('name' => 'document', 'groups' =>array('mode', 'document', 'doctools')),
+ array('name' => 'clipboard', 'groups' =>array('clipboard', 'undo', )),
+ array('name' => 'editing', 'groups' =>array('clipboard', 'undo', )),
+ //array('name' => 'forms', 'groups' =>array('clipboard', 'undo', )),
+ '/',
+ array('name' => 'basicstyles', 'groups' =>array('basicstyles', 'cleanup', )),
+ array('name' => 'paragraph', 'groups' =>array('list', 'indent', 'blocks', 'align')),
+ array('name' => 'links'),
+ array('name' => 'insert'),
+ '/',
+ array('name' => 'styles'),
+ array('name' => 'colors'),
+ array('name' => 'tools'),
+ array('name' => 'others'),
+ array('name' => 'allMedias'),
+ array('name' => 'mode')
+ );
+
+ // file manager (elfinder)
+
+ // http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.config.html
+ $config['filebrowserBrowseUrl'] = api_get_path(WEB_LIBRARY_PATH).'elfinder/filemanager.php';
+
+ $config['customConfig'] = api_get_path(WEB_LIBRARY_PATH).'javascript/ckeditor/config_js.php';
+
+ /*filebrowserFlashBrowseUrl
+ filebrowserFlashUploadUrl
+ filebrowserImageBrowseLinkUrl
+ filebrowserImageBrowseUrl
+ filebrowserImageUploadUrl
+ filebrowserUploadUrl*/
+
+ $config['extraPlugins'] = $this->getPluginsToString();
+
+ //$config['oembed_maxWidth'] = '560';
+ //$config['oembed_maxHeight'] = '315';
+
+ //$config['allowedContent'] = true;
+
+ /*$config['wordcount'] = array(
+ // Whether or not you want to show the Word Count
+ 'showWordCount' => true,
+ // Whether or not you want to show the Char Count
+ 'showCharCount' => true,
+ // Option to limit the characters in the Editor
+ 'charLimit' => 'unlimited',
+ // Option to limit the words in the Editor
+ 'wordLimit' => 'unlimited'
+ );*/
+
+ //$config['skins'] = 'moono';
+
+ if (isset($this->config)) {
+ $this->config = array_merge($config, $this->config);
+ } else {
+ $this->config = $config;
+ }
+
+ //$config['width'] = '100';
+ //$config['height'] = '200';
+ return $this->config;
+ }
+}
diff --git a/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/Documents.php b/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/Documents.php
new file mode 100644
index 0000000000..b6e9db4788
--- /dev/null
+++ b/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/Documents.php
@@ -0,0 +1,58 @@
+ 'document', 'groups' => array('document', 'doctools')),
+ array('name' => 'clipboard', 'groups' => array('clipboard', 'undo')),
+ array('name' => 'editing', 'groups' => array( 'find', 'selection', 'spellchecker')),
+ //array('name' => 'forms'),
+ '/',
+ array('name' => 'basicstyles', 'groups' => array('basicstyles', 'cleanup')),
+ array('name' => 'paragraph', 'groups' => array('list', 'indent', 'blocks', 'align', 'bidi')),
+ array('name' => 'links'),
+ array('name' => 'insert'),
+ '/',
+ array('name' => 'styles'),
+ array('name' => 'colors'),
+ //array('name' => 'tools'),
+ array('name' => 'others'),
+ array('name' => 'mode')
+ );
+ $config['extraPlugins'] = $this->getPluginsToString();
+ //$config['mathJaxLib'] = $this->urlGenerator->generate('javascript').'/math_jax/MathJax.js?config=default';
+ //$config['mathJaxLib'] = api_get_path(WEB_LIBRARY_JS_PATH).'/math_jax/MathJax.js?config=default';
+ $config['fullPage'] = true;
+
+ return $config;
+ }
+
+}
diff --git a/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/IntroductionTool.php b/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/IntroductionTool.php
new file mode 100644
index 0000000000..480034deb4
--- /dev/null
+++ b/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/IntroductionTool.php
@@ -0,0 +1,40 @@
+ 'document', 'groups' =>array('mode', 'document', 'doctools')),
+// array('name' => 'clipboard', 'groups' =>array('clipboard', 'undo', )),
+ //array('name' => 'editing', 'groups' =>array('clipboard', 'undo', )),
+ //array('name' => 'forms', 'groups' =>array('clipboard', 'undo', )),
+ '/',
+ array('name' => 'basicstyles', 'groups' =>array('basicstyles', 'cleanup', )),
+ array('name' => 'paragraph', 'groups' =>array('list', 'indent', 'blocks', 'align' )),
+ array('name' => 'links'),
+ array('name' => 'insert'),
+ '/',
+ array('name' => 'styles'),
+ array('name' => 'colors'),
+ array('name' => 'tools'),
+ array('name' => 'others'),
+ array('name' => 'mode')
+ );
+
+ $config['fullPage'] = true;
+ //$config['height'] = '200';
+
+ return $config;
+ }
+}
diff --git a/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/LearningPathDocuments.php b/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/LearningPathDocuments.php
new file mode 100644
index 0000000000..778df65554
--- /dev/null
+++ b/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/LearningPathDocuments.php
@@ -0,0 +1,39 @@
+ 'document', 'groups' =>array('document', 'doctools')),
+ array('name' => 'clipboard', 'groups' =>array('clipboard', 'undo', )),
+ array('name' => 'editing', 'groups' =>array('clipboard', 'undo', )),
+ array('name' => 'forms', 'groups' =>array('clipboard', 'undo', )),
+ '/',
+ array('name' => 'basicstyles', 'groups' =>array('basicstyles', 'cleanup', )),
+ array('name' => 'paragraph', 'groups' =>array('list', 'indent', 'blocks', 'align' )),
+ array('name' => 'links'),
+ array('name' => 'insert'),
+ '/',
+ array('name' => 'styles'),
+ array('name' => 'colors'),
+ array('name' => 'tools'),
+ array('name' => 'others'),
+ array('name' => 'others')
+ );
+
+ $config['fullPage'] = true;
+
+ return $config;
+ }
+}
diff --git a/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/Message.php b/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/Message.php
new file mode 100644
index 0000000000..a1dd48a399
--- /dev/null
+++ b/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/Message.php
@@ -0,0 +1,35 @@
+ 'basicstyles', 'groups' =>array('basicstyles', 'cleanup')),
+ array('name' => 'paragraph', 'groups' =>array('list', 'indent', 'blocks', 'align')),
+ array('name' => 'links'),
+ array('name' => 'insert'),
+ '/',
+ array('name' => 'styles'),
+ array('name' => 'colors'),
+ array('name' => 'tools'),
+ array('name' => 'others')
+ );
+
+ $config['fullPage'] = true;
+ //$config['height'] = '200';
+
+ return $config;
+ }
+}
diff --git a/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/Notebook.php b/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/Notebook.php
new file mode 100644
index 0000000000..5409ff8f6a
--- /dev/null
+++ b/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/Notebook.php
@@ -0,0 +1,13 @@
+ 'basicstyles', 'groups' =>array('basicstyles', 'cleanup', )),
+ array('name' => 'paragraph', 'groups' =>array('list', 'indent', 'blocks', 'align' )),
+ array('name' => 'links'),
+ array('name' => 'insert'),
+ '/',
+ array('name' => 'styles'),
+ array('name' => 'colors'),
+ array('name' => 'tools'),
+ array('name' => 'others'),
+ array('name' => 'mode')
+ );
+
+ $config['fullPage'] = false;
+
+ $config['extraPlugins'] = 'wordcount';
+
+ $config['wordcount'] = array(
+ // Whether or not you want to show the Word Count
+ 'showWordCount' => true,
+ // Whether or not you want to show the Char Count
+ 'showCharCount' => true,
+ // Option to limit the characters in the Editor
+ 'charLimit' => 'unlimited',
+ // Option to limit the words in the Editor
+ 'wordLimit' => 'unlimited'
+ );
+
+ //$config['height'] = '200';
+
+ return $config;
+ }
+}
diff --git a/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/TestFreeAnswerStrict.php b/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/TestFreeAnswerStrict.php
new file mode 100644
index 0000000000..363993671b
--- /dev/null
+++ b/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/TestFreeAnswerStrict.php
@@ -0,0 +1,54 @@
+ 'document', 'groups' =>array('mode', 'document', 'doctools')),
+// array('name' => 'clipboard', 'groups' =>array('clipboard', 'undo', )),
+ //array('name' => 'editing', 'groups' =>array('clipboard', 'undo', )),
+ //array('name' => 'forms', 'groups' =>array('clipboard', 'undo', )),
+ /*'/',
+ array('name' => 'basicstyles', 'groups' =>array('basicstyles', 'cleanup', )),
+ array('name' => 'paragraph', 'groups' =>array('list', 'indent', 'blocks', 'align' )),
+ array('name' => 'links'),
+ array('name' => 'insert'),
+ '/',
+ array('name' => 'styles'),
+ array('name' => 'colors'),
+ array('name' => 'tools'),
+ array('name' => 'others'),
+ array('name' => 'mode')*/
+ );
+
+ $config['fullPage'] = false;
+
+ $config['extraPlugins'] = 'wordcount';
+
+ $config['wordcount'] = array(
+ // Whether or not you want to show the Word Count
+ 'showWordCount' => true,
+ // Whether or not you want to show the Char Count
+ 'showCharCount' => true,
+ // Option to limit the characters in the Editor
+ 'charLimit' => 'unlimited',
+ // Option to limit the words in the Editor
+ 'wordLimit' => 'unlimited'
+ );
+
+ $config['removePlugins'] = 'elementspath';
+ //$config['height'] = '200';
+ return $config;
+ }
+}
diff --git a/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/TestProposedAnswer.php b/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/TestProposedAnswer.php
new file mode 100644
index 0000000000..cd7475380e
--- /dev/null
+++ b/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/TestProposedAnswer.php
@@ -0,0 +1,36 @@
+ 'document'),
+ array('name' => 'clipboard', 'groups' =>array('clipboard', 'undo', )),
+ array('name' => 'basicstyles', 'groups' =>array('basicstyles', 'cleanup', )),
+ array('name' => 'paragraph', 'groups' =>array('list', 'indent', 'blocks', 'align' )),
+ array('name' => 'links'),
+ array('name' => 'insert'),
+ '/',
+ array('name' => 'styles'),
+ array('name' => 'colors'),
+ array('name' => 'mode')
+ );
+
+ $config['toolbarCanCollapse'] = true;
+ $config['toolbarStartupExpanded'] = false;
+ //$config['width'] = '100';
+ //$config['height'] = '200';
+ return $config;
+ }
+}
diff --git a/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/TestQuestionDescription.php b/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/TestQuestionDescription.php
new file mode 100644
index 0000000000..13829f2e0f
--- /dev/null
+++ b/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/TestQuestionDescription.php
@@ -0,0 +1,40 @@
+ 'document', 'groups' =>array('document', 'doctools')),
+ array('name' => 'clipboard', 'groups' =>array('clipboard', 'undo', )),
+ array('name' => 'editing', 'groups' =>array('clipboard', 'undo', )),
+ //array('name' => 'forms', 'groups' =>array('clipboard', 'undo', )),
+ '/',
+ array('name' => 'basicstyles', 'groups' =>array('basicstyles', 'cleanup', )),
+ array('name' => 'paragraph', 'groups' =>array('list', 'indent', 'blocks', 'align' )),
+ array('name' => 'links'),
+ array('name' => 'insert'),
+ '/',
+ array('name' => 'styles'),
+ array('name' => 'colors'),
+ array('name' => 'tools'),
+ array('name' => 'others'),
+ array('name' => 'mode')
+ //array('name' => 'about')
+ );
+
+ //$config['width'] = '100';
+ //$config['height'] = '200';
+ return $config;
+ }
+}
diff --git a/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/ToolbarStartExpanded.php b/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/ToolbarStartExpanded.php
new file mode 100644
index 0000000000..cf6d858527
--- /dev/null
+++ b/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/ToolbarStartExpanded.php
@@ -0,0 +1,14 @@
+ 'basicstyles', 'groups' =>array('basicstyles', 'cleanup', )),
+ array('name' => 'paragraph', 'groups' =>array('list', 'indent', 'blocks', 'align' )),
+ array('name' => 'links'),
+ array('name' => 'insert'),
+ '/',
+ array('name' => 'styles'),
+ array('name' => 'colors'),
+ array('name' => 'tools'),
+ array('name' => 'others'),
+ array('name' => 'mode')
+ );
+
+ $config['fullPage'] = true;
+ //$config['height'] = '200';
+
+ return $config;
+ }
+}
diff --git a/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/WikiStudent.php b/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/WikiStudent.php
new file mode 100644
index 0000000000..3ad45c3a17
--- /dev/null
+++ b/src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/WikiStudent.php
@@ -0,0 +1,13 @@
+paths = array(
+ 'root_sys' => api_get_path(SYS_PATH),
+ 'sys_root' => api_get_path(SYS_PATH), // just an alias
+ 'sys_data_path' => api_get_path(SYS_COURSE_PATH),
+ // 'sys_config_path' => $app['path.config'],
+ 'path.temp' => api_get_path(SYS_ARCHIVE_PATH),
+ //'sys_log_path' => $app['path.logs']
+ );
+ /*$this->entityManager = $entityManager;
+ $this->paths = $paths;
+ $this->urlGenerator = $urlGenerator;
+ $this->translator = $translator;
+ $this->security = $security;*/
+ $this->user = api_get_user_info();
+ $this->course = api_get_course_info();
+ $this->driverList = $this->getDefaultDriverList();
+ }
+
+ /**
+ * @return array
+ */
+ public function getDriverList()
+ {
+ return $this->driverList;
+ }
+
+ /**
+ * Available driver list.
+ * @param array
+ */
+ public function setDriverList($list)
+ {
+ $this->driverList = $list;
+ }
+
+ /**
+ * Available driver list.
+ * @return array
+ */
+ private function getDefaultDriverList()
+ {
+ return array(
+ 'CourseDriver',
+ 'CourseUserDriver',
+ 'DropBoxDriver',
+ 'HomeDriver',
+ 'PersonalDriver'
+ );
+ }
+
+ /**
+ * @param Driver $driver
+ */
+ public function addDriver($driver)
+ {
+ if (!empty($driver)) {
+ $this->drivers[$driver->getName()] = $driver;
+ }
+ }
+
+ /**
+ * @return array
+ */
+ public function getDrivers()
+ {
+ return $this->drivers;
+ }
+
+ /**
+ * @param string $driverName
+ * @return Driver $driver
+ */
+ public function getDriver($driverName)
+ {
+ if (isset($this->drivers[$driverName])) {
+ return $this->drivers[$driverName];
+ }
+
+ return null;
+ }
+
+ /**
+ * @param bool $processDefaultValues
+ * @return array
+ */
+ public function getRoots($processDefaultValues = true)
+ {
+ $roots = array();
+ /** @var Driver $driver */
+ $drivers = $this->getDrivers();
+
+ foreach ($drivers as $driver) {
+ if ($processDefaultValues) {
+ $plugin = array(
+ 'chamilo' => array(
+ 'driverName' => $driver->getName(),
+ 'connector' => $this,
+ )
+ );
+ $configuration = $driver->getConfiguration();
+ $configuration['plugin'] = $plugin;
+ $root = $this->updateWithDefaultValues($configuration);
+ }
+ $roots[] = $root;
+ }
+
+ return $roots;
+ }
+
+ /**
+ * Merges the default driver settings.
+ * @param array $driver
+ * @return array
+ */
+ public function updateWithDefaultValues($driver)
+ {
+ if (empty($driver) || !isset($driver['driver'])) {
+ return array();
+ }
+
+ $defaultDriver = $this->getDefaultDriverSettings();
+
+ if (isset($driver['attributes'])) {
+ $attributes = array_merge($defaultDriver['attributes'], $driver['attributes']);
+ } else {
+ $attributes = $defaultDriver['attributes'];
+ }
+
+ $driverUpdated = array_merge($defaultDriver, $driver);
+ $driverUpdated['driver'] = 'Chamilo\CoreBundle\Component\Editor\Driver\\'.$driver['driver'];
+ $driverUpdated['attributes'] = $attributes;
+
+ return $driverUpdated;
+ }
+
+ /**
+ * Get default driver settings.
+ * @return array
+ */
+ private function getDefaultDriverSettings()
+ {
+ // for more options: https://github.com/Studio-42/elFinder/wiki/Connector-configuration-options
+ return array(
+ 'uploadOverwrite' => false, // Replace files on upload or give them new name if the same file was uploaded
+ //'acceptedName' =>
+ 'uploadAllow' => array(
+ 'image',
+ 'audio',
+ 'video',
+ 'text/html',
+ 'text/csv',
+ 'application/pdf',
+ 'application/postscript',
+ 'application/vnd.ms-word',
+ 'application/vnd.ms-excel',
+ 'application/vnd.ms-powerpoint',
+ 'application/pdf',
+ 'application/xml',
+ 'application/vnd.oasis.opendocument.text',
+ 'application/x-shockwave-flash'
+ ), # allow files
+ //'uploadDeny' => array('text/x-php'),
+ 'uploadOrder' => array('allow'), // only executes allow
+ 'disabled' => array(
+ 'duplicate',
+ 'rename',
+ 'mkdir',
+ 'mkfile',
+ 'copy',
+ 'cut',
+ 'paste',
+ 'edit',
+ 'extract',
+ 'archive',
+ 'help',
+ 'resize'
+ ),
+ 'attributes' => array(
+ // Hiding dangerous files
+ array(
+ 'pattern' => '/\.(php|py|pl|sh|xml)$/i',
+ 'read' => false,
+ 'write' => false,
+ 'hidden' => true,
+ 'locked' => false
+ ),
+ // Hiding _DELETED_ files
+ array(
+ 'pattern' => '/_DELETED_/',
+ 'read' => false,
+ 'write' => false,
+ 'hidden' => true,
+ 'locked' => false
+ ),
+ // Hiding thumbnails
+ array(
+ 'pattern' => '/.tmb/',
+ 'read' => false,
+ 'write' => false,
+ 'hidden' => true,
+ 'locked' => false
+ ),
+ array(
+ 'pattern' => '/.thumbs/',
+ 'read' => false,
+ 'write' => false,
+ 'hidden' => true,
+ 'locked' => false
+ ),
+ array(
+ 'pattern' => '/.quarantine/',
+ 'read' => false,
+ 'write' => false,
+ 'hidden' => true,
+ 'locked' => false
+ )
+ )
+ );
+ }
+
+ /**
+ * @return array
+ */
+ public function getOperations()
+ {
+ //https://github.com/Studio-42/elFinder/wiki/Connector-configuration-options-2.1
+ $opts = array(
+ //'debug' => true,
+ 'bind' => array(
+ 'upload rm' => array($this, 'manageCommands')
+ )
+ );
+
+ $this->setDrivers();
+
+ $opts['roots'] = $this->getRoots();
+
+ return $opts;
+ }
+
+ /**
+ * Set drivers from list
+ */
+ public function setDrivers()
+ {
+ foreach ($this->getDriverList() as $driverName) {
+ $this->setDriver($driverName);
+ }
+ }
+
+ /**
+ * Sets a driver.
+ * @param string $driverName
+ */
+ public function setDriver($driverName)
+ {
+ $driverClass = $this->getDriverClass($driverName);
+
+ /** @var Driver $driver */
+ $driver = new $driverClass();
+ $driver->setName($driverName);
+ $driver->setConnector($this);
+ $this->addDriver($driver);
+ }
+
+ /**
+ * Simple function to demonstrate how to control file access using "accessControl" callback.
+ * This method will disable accessing files/folders starting from '.' (dot)
+ *
+ * @param string $attr attribute name (read|write|locked|hidden)
+ * @param string $path file path relative to volume root directory started with directory separator
+ * @param string $data
+ * @param string $volume
+ * @return bool|null
+ **/
+ public function access($attr, $path, $data, $volume)
+ {
+ return strpos(basename($path), '.') === 0 // if file/folder begins with '.' (dot)
+ ? !($attr == 'read' || $attr == 'write') // set read+write to false, other (locked+hidden) set to true
+ : null; // else elFinder decide it itself
+ }
+
+ /**
+ * @param string $cmd
+ * @param array $result
+ * @param array $args
+ * @param Finder $elFinder
+ */
+ public function manageCommands($cmd, $result, $args, $elFinder)
+ {
+ $cmd = ucfirst($cmd);
+ $cmd = 'after'.$cmd;
+/*
+ if (isset($args['target'])) {
+ $driverName = $elFinder->getVolumeDriverNameByTarget($args['target']);
+ }
+
+ if (isset($args['targets'])) {
+ foreach ($args['targets'] as $target) {
+ $driverName = $elFinder->getVolumeDriverNameByTarget($target);
+ break;
+ }
+ }
+*/
+ if (empty($driverName)) {
+ return false;
+ }
+
+ if (!empty($result['error'])) {
+ }
+
+ if (!empty($result['warning'])) {
+ }
+
+ if (!empty($result['removed'])) {
+ foreach ($result['removed'] as $file) {
+ /** @var Driver $driver */
+// $driver = $this->getDriver($driverName);
+// $driver->$cmd($file, $args, $elFinder);
+ // removed file contain additional field "realpath"
+ //$log .= "\tREMOVED: ".$file['realpath']."\n";
+ }
+ }
+
+ if (!empty($result['added'])) {
+ foreach ($result['added'] as $file) {
+// $driver = $this->getDriver($driverName);
+// $driver->$cmd($file, $args, $elFinder);
+ }
+ }
+
+ if (!empty($result['changed'])) {
+ foreach ($result['changed'] as $file) {
+ //$log .= "\tCHANGED: ".$elfinder->realpath($file['hash'])."\n";
+ }
+ }
+ }
+
+ /**
+ * @param string $driver
+ * @return string
+ */
+ private function getDriverClass($driver)
+ {
+ return 'Chamilo\CoreBundle\Component\Editor\Driver\\'.$driver;
+ }
+}
diff --git a/src/Chamilo/CoreBundle/Component/Editor/Driver/CourseDriver.php b/src/Chamilo/CoreBundle/Component/Editor/Driver/CourseDriver.php
new file mode 100644
index 0000000000..d4a3dad565
--- /dev/null
+++ b/src/Chamilo/CoreBundle/Component/Editor/Driver/CourseDriver.php
@@ -0,0 +1,163 @@
+connector->course)) {
+ //$translator = $this->connector->translator;
+ //$code = $this->connector->course->getCode();
+ $courseCode = $this->connector->course['code'];
+ $alias = $courseCode.' '.get_lang('Documents');
+
+ return array(
+ 'driver' => 'CourseDriver',
+ 'path' => $this->getCourseDocumentSysPath(),
+ 'URL' => $this->getCourseDocumentRelativeWebPath(),
+ 'accessControl' => array($this, 'access'),
+ 'alias' => $alias,
+ 'attributes' => array(
+ // Hide shared_folder
+ array(
+ 'pattern' => '/shared_folder/',
+ 'read' => false,
+ 'write' => false,
+ 'hidden' => true,
+ 'locked' => false
+ ),
+ )
+ );
+ }
+ }
+
+ /**
+ * This is the absolute document course path like
+ * /var/www/portal/data/courses/XXX/document/
+ * @return string
+ */
+ public function getCourseDocumentSysPath()
+ {
+ $url = null;
+ if (isset($this->connector->course)) {
+ //$directory = $this->connector->course->getDirectory();
+ $directory = $this->connector->course['directory'];
+ $dataPath = $this->connector->paths['sys_data_path'];
+ $url = $dataPath.$directory.'/document/';
+ }
+
+ return $url;
+ }
+
+ /**
+ * @return string
+ */
+ public function getCourseDocumentRelativeWebPath()
+ {
+ $url = null;
+ if (isset($this->connector->course)) {
+ $directory = $this->connector->course['directory'];
+ $url = api_get_path(REL_COURSE_PATH).$directory.'/document/';
+ }
+
+ return $url;
+ }
+
+
+ /**
+ * @return string
+ */
+ public function getCourseDocumentWebPath()
+ {
+ $url = null;
+ if (isset($this->connector->course)) {
+ $directory = $this->connector->course->getDirectory();
+ $url = api_get_path(WEB_COURSE_PATH).$directory.'/document/';
+ }
+
+ return $url;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function upload($fp, $dst, $name, $tmpname)
+ {
+ $this->setConnectorFromPlugin();
+
+ // upload file by elfinder.
+ $result = parent::upload($fp, $dst, $name, $tmpname);
+
+ $name = $result['name'];
+ $filtered = \URLify::filter($result['name'], 80);
+
+ if (strcmp($name, $filtered) != 0) {
+ /*$arg = array('target' => $file['hash'], 'name' => $filtered);
+ $elFinder->exec('rename', $arg);*/
+ $this->rename($result['hash'], $filtered);
+ }
+
+ $realPath = $this->realpath($result['hash']);
+
+ if (!empty($realPath)) {
+ // Getting file info
+ //$info = $elFinder->exec('file', array('target' => $file['hash']));
+ /** @var elFinderVolumeLocalFileSystem $volume */
+ //$volume = $info['volume'];
+ //$root = $volume->root();
+ //var/www/chamilogits/data/courses/NEWONE/document
+ $realPathRoot = $this->getCourseDocumentSysPath();
+
+ // Removing course path
+ $realPath = str_replace($realPathRoot, '/', $realPath);
+ add_document(
+ $this->connector->course,
+ $realPath,
+ 'file',
+ intval($result['size']),
+ $result['name']
+ );
+ }
+
+ return $result;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function rm($hash)
+ {
+ // elfinder does not delete the file
+ //parent::rm($hash);
+ $this->setConnectorFromPlugin();
+
+ $path = $this->decode($hash);
+ $stat = $this->stat($path);
+ $stat['realpath'] = $path;
+ $this->removed[] = $stat;
+
+ $realFilePath = $path;
+ $coursePath = $this->getCourseDocumentSysPath();
+ $filePath = str_replace($coursePath, '/', $realFilePath);
+
+ \DocumentManager::delete_document(
+ $this->connector->course,
+ $filePath,
+ $coursePath
+ );
+
+ return true;
+ }
+}
diff --git a/src/Chamilo/CoreBundle/Component/Editor/Driver/CourseUserDriver.php b/src/Chamilo/CoreBundle/Component/Editor/Driver/CourseUserDriver.php
new file mode 100644
index 0000000000..b543073b7d
--- /dev/null
+++ b/src/Chamilo/CoreBundle/Component/Editor/Driver/CourseUserDriver.php
@@ -0,0 +1,37 @@
+connector->course)) {
+ $userId = api_get_user_id();
+ $path = 'shared_folder/sf_user_'.$userId;
+
+ $alias = $this->connector->course['code'].' '.get_lang('CourseUserDocument');
+
+ if (!empty($userId)) {
+ return array(
+ 'driver' => 'CourseUserDriver',
+ 'alias' => $alias,
+ 'path' => $this->getCourseDocumentSysPath().$path,
+ //'alias' => $courseInfo['code'].' personal documents',
+ 'URL' => $this->getCourseDocumentRelativeWebPath().$path,
+ 'accessControl' => 'access'
+ );
+ }
+ }
+ }
+}
diff --git a/src/Chamilo/CoreBundle/Component/Editor/Driver/Driver.php b/src/Chamilo/CoreBundle/Component/Editor/Driver/Driver.php
new file mode 100644
index 0000000000..8b2dc73bda
--- /dev/null
+++ b/src/Chamilo/CoreBundle/Component/Editor/Driver/Driver.php
@@ -0,0 +1,63 @@
+name;
+ }
+
+ /**
+ * Gets driver name.
+ * @param string
+ */
+ public function setName($name)
+ {
+ $this->name = $name;
+ }
+
+ /**
+ * Set connector
+ * @param Connector $connector
+ */
+ public function setConnector(Connector $connector)
+ {
+ $this->connector = $connector;
+ }
+
+ /**
+ * @return array
+ */
+ public function getAppPluginOptions()
+ {
+ return $this->getOptionsPlugin('chamilo');
+ }
+
+ /**
+ * @return Connector
+ */
+ public function setConnectorFromPlugin()
+ {
+ $options = $this->getAppPluginOptions();
+ $this->setConnector($options['connector']);
+ }
+}
diff --git a/src/Chamilo/CoreBundle/Component/Editor/Driver/DriverInterface.php b/src/Chamilo/CoreBundle/Component/Editor/Driver/DriverInterface.php
new file mode 100644
index 0000000000..fdc6e06c97
--- /dev/null
+++ b/src/Chamilo/CoreBundle/Component/Editor/Driver/DriverInterface.php
@@ -0,0 +1,41 @@
+name;
+ }
+
+ /**
+ * Gets driver name.
+ * @param string
+ */
+ public function setName($name)
+ {
+ $this->name = $name;
+ }
+
+ /**
+ * Set connector
+ * @param Connector $connector
+ */
+ public function setConnector(Connector $connector)
+ {
+ $this->connector = $connector;
+ }
+
+ /**
+ * @return array
+ */
+ public function getAppPluginOptions()
+ {
+ return $this->getOptionsPlugin('chamilo');
+ }
+
+ /**
+ * @return Connector
+ */
+ public function setConnectorFromPlugin()
+ {
+ $options = $this->getAppPluginOptions();
+ $this->setConnector($options['connector']);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getConfiguration()
+ {
+ if ($this->connector->security->isGranted('IS_AUTHENTICATED_FULLY')) {
+
+ /** @var \Chamilo\CoreBundle\Entity\Repository\UserRepository $repository */
+ /*$repository = $this->connector->entityManager->getRepository('Chamilo\UserBundle\Entity\User');
+ $courses = $repository->getCourses($this->connector->user);*/
+
+ //if (!empty($courses)) {
+ $userId = $this->connector->user->getUserId();
+ if (!empty($userId)) {
+ return array(
+ 'driver' => 'DropBoxDriver',
+ 'path' => '1',
+ 'alias' => 'dropbox',
+ 'tmpPath' => $this->connector->paths['path.temp'],
+ //'alias' => $courseInfo['code'].' personal documents',
+ //'URL' => $this->getCourseDocumentRelativeWebPath().$path,
+ 'accessControl' => 'access'
+ );
+ }
+ //}
+ }
+ }
+
+ public function __construct()
+ {
+ parent::__construct();
+ }
+
+ protected function init()
+ {
+ $this->updateCache($this->options['path'], $this->_stat($this->options['path']));
+ return true;
+ }
+
+ /**
+ * Set tmp path
+ *
+ * @return void
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function configure() {
+ parent::configure();
+
+ if (($tmp = $this->options['tmpPath'])) {
+ if (!file_exists($tmp)) {
+ if (@mkdir($tmp)) {
+ @chmod($tmp, $this->options['tmbPathMode']);
+ }
+ }
+
+ $this->tmpPath = is_dir($tmp) && is_writable($tmp) ? $tmp : false;
+ }
+
+ if (!$this->tmpPath && $this->tmbPath && $this->tmbPathWritable) {
+ $this->tmpPath = $this->tmbPath;
+ }
+
+ $this->mimeDetect = 'internal';
+ }
+
+
+
+ /**
+ * Close connection
+ *
+ * @return void
+ * @author Dmitry (dio) Levashov
+ **/
+ public function umount() {
+ return true;
+ }
+
+
+ /* FS API */
+
+ /**
+ * Cache dir contents
+ *
+ * @param string $path dir path
+ * @return void
+ * @author Dmitry Levashov
+ **/
+ protected function cacheDir($path)
+ {
+ $this->setConnectorFromPlugin();
+ $posts = $this->connector->user->getDropBoxReceivedFiles();
+ $this->dirsCache[$path] = array();
+
+ if (!empty($posts)) {
+ foreach ($posts as $post) {
+ /** @var CDropboxFile $file */
+ $file = $post->getFile();
+
+ $data = $this->transformFileInStat($file);
+ $id = $data['id'];
+ if (($stat = $this->updateCache($id, $data)) && empty($stat['hidden'])) {
+ $this->dirsCache[$path][] = $id;
+ }
+ }
+ return $this->dirsCache[$path];
+ }
+ return $this->dirsCache[$path];
+ }
+
+ /***************** file stat ********************/
+ /**
+ * Return stat for given path.
+ * Stat contains following fields:
+ * - (int) size file size in b. required
+ * - (int) ts file modification time in unix time. required
+ * - (string) mime mimetype. required for folders, others - optionally
+ * - (bool) read read permissions. required
+ * - (bool) write write permissions. required
+ * - (bool) locked is object locked. optionally
+ * - (bool) hidden is object hidden. optionally
+ * - (string) alias for symlinks - link target path relative to root path. optionally
+ * - (string) target for symlinks - link target path. optionally
+ *
+ * If file does not exists - returns empty array or false.
+ *
+ * @param string $path file path
+ * @return array|false
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _stat($path)
+ {
+ $this->setConnectorFromPlugin();
+
+ $userId = $this->connector->user->getUserId();
+ $criteria = array();
+ $criteria['uploaderId'] = $userId;
+
+ if ($path != 1) {
+ $criteria['filename'] = $path;
+ $criteria = array('filename' => $path);
+ } else {
+ return $this->returnDirectory();
+ }
+
+ $file = $this->connector->entityManager->getRepository('Chamilo\CoreBundle\Entity\CDropboxFile')->findOneBy($criteria);
+
+ if ($file) {
+ $stat = $this->transformFileInStat($file);
+ return $stat;
+ }
+ return array();
+ }
+
+ /**
+ * @return array
+ */
+ private function returnDirectory()
+ {
+ return array(
+ //'id' => $file->getId().$file->getCId(),
+ 'name' => 'Dropbox',
+ //'ts' => $file->getUploadDate(),
+ 'mime' => 'directory',
+ 'read' => true,
+ 'write' => true,
+ 'locked' => false,
+ 'hidden' => false,
+ 'dirs' => 0
+ );
+ }
+
+ /**
+ * @param CDropboxFile $file
+ * @return array
+ */
+ private function transformFileInStat(CDropboxFile $file)
+ {
+ $stat = array(
+ 'id' => $file->getId().$file->getCId(),
+ 'name' => $file->getFilename(),
+ 'ts' => $file->getUploadDate(),
+ 'mime' => 'directory',
+ 'read' => true,
+ 'write' => false,
+ 'locked' => false,
+ 'hidden' => false,
+ 'width' => 100,
+ 'height' => 100,
+ 'dirs' => 0
+ );
+ return $stat;
+
+ /*
+ if ($stat['parent_id']) {
+ $stat['phash'] = $this->encode($stat['parent_id']);
+ }
+ if ($stat['mime'] == 'directory') {
+ unset($stat['width']);
+ unset($stat['height']);
+ } else {
+ unset($stat['dirs']);
+ }
+ unset($stat['id']);
+ unset($stat['parent_id']);
+ */
+ }
+
+ /**
+ * Return array of parents paths (ids)
+ *
+ * @param int $path file path (id)
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function getParents($path) {
+ $parents = array();
+
+ while ($path) {
+ if ($file = $this->stat($path)) {
+ array_unshift($parents, $path);
+ $path = isset($file['phash']) ? $this->decode($file['phash']) : false;
+ }
+ }
+
+ if (count($parents)) {
+ array_pop($parents);
+ }
+ return $parents;
+ }
+
+ /**
+ * Return correct file path for LOAD_FILE method
+ *
+ * @param string $path file path (id)
+ * @return string
+ * @author Troex Nevelin
+ **/
+ protected function loadFilePath($path) {
+ $realPath = realpath($path);
+ if (DIRECTORY_SEPARATOR == '\\') { // windows
+ $realPath = str_replace('\\', '\\\\', $realPath);
+ }
+ return $this->db->real_escape_string($realPath);
+ }
+
+ /**
+ * Recursive files search
+ *
+ * @param string $path dir path
+ * @param string $q search string
+ * @param array $mimes
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function doSearch($path, $q, $mimes) {
+ return array();
+ }
+
+
+ /*********************** paths/urls *************************/
+
+ /**
+ * Return parent directory path
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _dirname($path) {
+ return ($stat = $this->stat($path)) ? ($stat['phash'] ? $this->decode($stat['phash']) : $this->root) : false;
+ }
+
+ /**
+ * Return file name
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _basename($path) {
+ return ($stat = $this->stat($path)) ? $stat['name'] : false;
+ }
+
+
+ /**
+ * Return normalized path, this works the same as os.path.normpath() in Python
+ *
+ * @param string $path path
+ * @return string
+ * @author Troex Nevelin
+ **/
+ protected function _normpath($path) {
+ return $path;
+ }
+
+ /**
+ * Return file path related to root dir
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _relpath($path) {
+ return $path;
+ }
+
+ /**
+ * Convert path related to root dir into real path
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _abspath($path) {
+ return $path;
+ }
+
+ /**
+ * Return fake path started from root dir
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _path($path) {
+ if (($file = $this->stat($path)) == false) {
+ return '';
+ }
+
+ $parentsIds = $this->getParents($path);
+ $path = '';
+ foreach ($parentsIds as $id) {
+ $dir = $this->stat($id);
+ $path .= $dir['name'].$this->separator;
+ }
+ return $path.$file['name'];
+ }
+
+ /**
+ * Return true if $path is children of $parent
+ *
+ * @param string $path path to check
+ * @param string $parent parent path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _inpath($path, $parent) {
+ return $path == $parent
+ ? true
+ : in_array($parent, $this->getParents($path));
+ }
+
+
+
+ /**
+ * Return true if path is dir and has at least one childs directory
+ *
+ * @param string $path dir path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _subdirs($path) {
+ return ($stat = $this->stat($path)) && isset($stat['dirs']) ? $stat['dirs'] : false;
+ }
+
+ /**
+ * Return object width and height
+ * Usualy used for images, but can be realize for video etc...
+ *
+ * @param string $path file path
+ * @param string $mime file mime type
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _dimensions($path, $mime) {
+ return ($stat = $this->stat($path)) && isset($stat['width']) && isset($stat['height']) ? $stat['width'].'x'.$stat['height'] : '';
+ }
+
+ /******************** file/dir content *********************/
+
+ /**
+ * Return files list in directory.
+ *
+ * @param string $path dir path
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _scandir($path) {
+ return isset($this->dirsCache[$path])
+ ? $this->dirsCache[$path]
+ : $this->cacheDir($path);
+ }
+
+ /**
+ * Open file and return file pointer
+ *
+ * @param string $path file path
+ * @param string $mode open file mode (ignored in this driver)
+ * @return resource|false
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _fopen($path, $mode='rb') {
+ $fp = $this->tmbPath
+ ? @fopen($this->tmpname($path), 'w+')
+ : @tmpfile();
+
+
+ if ($fp) {
+ if (($res = $this->query('SELECT content FROM '.$this->tbf.' WHERE id="'.$path.'"'))
+ && ($r = $res->fetch_assoc())) {
+ fwrite($fp, $r['content']);
+ rewind($fp);
+ return $fp;
+ } else {
+ $this->_fclose($fp, $path);
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Close opened file
+ *
+ * @param resource $fp file pointer
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _fclose($fp, $path='') {
+ @fclose($fp);
+ if ($path) {
+ @unlink($this->tmpname($path));
+ }
+ }
+
+ /******************** file/dir manipulations *************************/
+
+ /**
+ * Create dir and return created dir path or false on failed
+ *
+ * @param string $path parent dir path
+ * @param string $name new directory name
+ * @return string|bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _mkdir($path, $name) {
+ return $this->make($path, $name, 'directory') ? $this->_joinPath($path, $name) : false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function _mkfile($path, $name) {
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function _symlink($target, $path, $name) {
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function _copy($source, $targetDir, $name) {
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function _move($source, $targetDir, $name) {
+ return false;
+ }
+
+ /**
+ * Remove file
+ *
+ * @param string $path file path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _unlink($path) {
+ return false;
+ return $this->query(sprintf('DELETE FROM %s WHERE id=%d AND mime!="directory" LIMIT 1', $this->tbf, $path)) && $this->db->affected_rows;
+ }
+
+ /**
+ * Remove dir
+ *
+ * @param string $path dir path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _rmdir($path) {
+ return false;
+ return $this->query(sprintf('DELETE FROM %s WHERE id=%d AND mime="directory" LIMIT 1', $this->tbf, $path)) && $this->db->affected_rows;
+ }
+
+ /**
+ * undocumented function
+ *
+ * @return void
+ * @author Dmitry Levashov
+ **/
+ protected function _setContent($path, $fp) {
+ rewind($fp);
+ $fstat = fstat($fp);
+ $size = $fstat['size'];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function _save($fp, $dir, $name, $stat) {
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function _getContents($path) {
+ return false;
+ //return ($res = $this->query(sprintf('SELECT content FROM %s WHERE id=%d', $this->tbf, $path))) && ($r = $res->fetch_assoc()) ? $r['content'] : false;
+ }
+
+ /**
+ * Write a string to a file
+ *
+ * @param string $path file path
+ * @param string $content new file content
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _filePutContents($path, $content) {
+ return false;
+ //return $this->query(sprintf('UPDATE %s SET content="%s", size=%d, mtime=%d WHERE id=%d LIMIT 1', $this->tbf, $this->db->real_escape_string($content), strlen($content), time(), $path));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function _checkArchivers() {
+ return;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function _unpack($path, $arc) {
+ return;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function _findSymlinks($path) {
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function _extract($path, $arc) {
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function _archive($dir, $files, $name, $arc) {
+ return false;
+ }
+
+}
diff --git a/src/Chamilo/CoreBundle/Component/Editor/Driver/HomeDriver.php b/src/Chamilo/CoreBundle/Component/Editor/Driver/HomeDriver.php
new file mode 100644
index 0000000000..292d4e4dd1
--- /dev/null
+++ b/src/Chamilo/CoreBundle/Component/Editor/Driver/HomeDriver.php
@@ -0,0 +1,54 @@
+connector->security->isGranted('ROLE_ADMIN')) {
+ if (api_is_platform_admin()) {
+ $home = api_get_path(SYS_PATH).'home';
+
+ return array(
+ 'driver' => 'HomeDriver',
+ 'alias' => get_lang('Portal'),
+ 'path' => $home,
+ 'URL' => api_get_path(WEB_PATH) . 'home',
+ 'accessControl' => array($this, 'access'),
+ );
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function upload($fp, $dst, $name, $tmpname)
+ {
+ $this->setConnectorFromPlugin();
+ if ($this->connector->security->isGranted('ROLE_ADMIN')) {
+ return parent::upload($fp, $dst, $name, $tmpname);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function rm($hash)
+ {
+ $this->setConnectorFromPlugin();
+ if ($this->connector->security->isGranted('ROLE_ADMIN')) {
+ return parent::rm($hash);
+ }
+ }
+}
diff --git a/src/Chamilo/CoreBundle/Component/Editor/Driver/PersonalDriver.php b/src/Chamilo/CoreBundle/Component/Editor/Driver/PersonalDriver.php
new file mode 100644
index 0000000000..91eaeafe6b
--- /dev/null
+++ b/src/Chamilo/CoreBundle/Component/Editor/Driver/PersonalDriver.php
@@ -0,0 +1,62 @@
+connector->security->isGranted('IS_AUTHENTICATED_FULLY')) {
+ $userId = api_get_user_id();
+ if (!empty($userId)) {
+
+ // Adding user personal files
+ $dir = \UserManager::get_user_picture_path_by_id($userId, 'system');
+ $dirWeb = \UserManager::get_user_picture_path_by_id($userId, 'web');
+
+ $driver = array(
+ 'driver' => 'PersonalDriver',
+ 'alias' => get_lang('MyFiles'),
+ 'path' => $dir['dir'].'my_files',
+ 'URL' => $dirWeb['dir'].'my_files',
+ 'accessControl' => array($this, 'access')
+ );
+
+ return $driver;
+ }
+ //}
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function upload($fp, $dst, $name, $tmpname)
+ {
+ $this->setConnectorFromPlugin();
+ //if ($this->connector->security->isGranted('IS_AUTHENTICATED_FULLY')) {
+ return parent::upload($fp, $dst, $name, $tmpname);
+ //}
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function rm($hash)
+ {
+ $this->setConnectorFromPlugin();
+ //if ($this->connector->security->isGranted('IS_AUTHENTICATED_FULLY')) {
+ return parent::rm($hash);
+ //}
+ }
+}
diff --git a/src/Chamilo/CoreBundle/Component/Editor/Editor.php b/src/Chamilo/CoreBundle/Component/Editor/Editor.php
new file mode 100644
index 0000000000..8ad5708ca2
--- /dev/null
+++ b/src/Chamilo/CoreBundle/Component/Editor/Editor.php
@@ -0,0 +1,240 @@
+toolbarSet = 'Basic';
+ $this->value = '';
+ $this->config = array();
+ $this->setConfigAttribute('width', '100%');
+ $this->setConfigAttribute('height', '200');
+ $this->setConfigAttribute('fullPage', false);
+ /*$this->translator = $translator;
+ $this->urlGenerator = $urlGenerator;*/
+ //$this->course = $course;
+ }
+
+ /**
+ * @return string
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * @param string $name
+ */
+ public function setName($name)
+ {
+ $this->name = $name;
+ }
+
+ /**
+ * Return the HTML code required to run editor.
+ *
+ * @return string
+ */
+ public function createHtml()
+ {
+ $html = '';
+ //$html .= $this->editorReplace();
+ return $html;
+ }
+
+ /**
+ * @return string
+ */
+ public function editorReplace()
+ {
+ $toolbar = new Toolbar($this->toolbarSet, $this->config);
+ $toolbar->setLanguage($this->getLocale());
+ $config = $toolbar->getConfig();
+ $javascript = $this->toJavascript($config);
+ $html = "";
+
+ return $html;
+ }
+
+ /**
+ * Converts a PHP variable into its Javascript equivalent.
+ * The code of this method has been "borrowed" from the function drupal_to_js() within the Drupal CMS.
+ * @param mixed $var The variable to be converted into Javascript syntax
+ * @return string Returns a string
+ * Note: This function is similar to json_encode(), in addition it produces HTML-safe strings, i.e. with <, > and & escaped.
+ * @link http://drupal.org/
+ */
+ protected function toJavascript($var)
+ {
+ switch (gettype($var)) {
+ case 'boolean':
+ return $var ? 'true' : 'false'; // Lowercase necessary!
+ case 'integer':
+ case 'double':
+ return (string)$var;
+ case 'resource':
+ case 'string':
+ return '"'.str_replace(
+ array("\r", "\n", "<", ">", "&"),
+ array('\r', '\n', '\x3c', '\x3e', '\x26'),
+ addslashes($var)
+ ).'"';
+ case 'array':
+ // Arrays in JSON can't be associative. If the array is empty or if it
+ // has sequential whole number keys starting with 0, it's not associative
+ // so we can go ahead and convert it as an array.
+ if (empty($var) || array_keys($var) === range(0, sizeof($var) - 1)) {
+ $output = array();
+ foreach ($var as $v) {
+ $output[] = $this->toJavascript($v);
+ }
+
+ return '[ '.implode(', ', $output).' ]';
+ }
+ case 'object':
+ // Otherwise, fall through to convert the array as an object.
+ $output = array();
+ foreach ($var as $k => $v) {
+ $output[] = $this->toJavascript(strval($k)).': '.$this->toJavascript($v);
+ }
+
+ return '{ '.implode(', ', $output).' }';
+ default:
+ return 'null';
+ }
+ }
+
+ /**
+ * @param string $key
+ * @param mixed $value
+ */
+ public function setConfigAttribute($key, $value)
+ {
+ $this->config[$key] = $value;
+ }
+
+ /**
+ * @param string $key
+ * @return mixed
+ */
+ public function getConfigAttribute($key)
+ {
+ return isset($this->config[$key]) ? $this->config[$key] : null;
+ }
+
+ /**
+ * @param array $config
+ */
+ public function processConfig($config)
+ {
+ if (is_array($config)) {
+ foreach ($config as $key => $value) {
+ switch($key) {
+ case 'ToolbarSet':
+ $this->toolbarSet = $value;
+ break;
+ case 'Config':
+ $this->processConfig($value);
+ break;
+ case 'Width':
+ $this->setConfigAttribute('width', $value);
+ break;
+ case 'Height':
+ $this->setConfigAttribute('height', $value);
+ break;
+ case 'FullPage':
+ $this->setConfigAttribute('fullPage', $value);
+ break;
+ default:
+ $this->setConfigAttribute($key, $value);
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * @return null
+ */
+ public function getEditorTemplate()
+ {
+ return null;
+ }
+
+ /**
+ * @return string
+ */
+ public function getEditorStandAloneTemplate()
+ {
+ return 'javascript/editor/elfinder_standalone.tpl';
+ }
+
+ /**
+ * @return null
+ */
+ public function formatTemplates($templates)
+ {
+ return null;
+ }
+
+ /**
+ * @return string
+ */
+ public function getLocale()
+ {
+ return 'en';
+ }
+}
diff --git a/src/Chamilo/CoreBundle/Component/Editor/Finder.php b/src/Chamilo/CoreBundle/Component/Editor/Finder.php
new file mode 100644
index 0000000000..b970897f57
--- /dev/null
+++ b/src/Chamilo/CoreBundle/Component/Editor/Finder.php
@@ -0,0 +1,112 @@
+time = $this->utime();
+ $this->debug = (isset($opts['debug']) && $opts['debug'] ? true : false);
+ $this->timeout = (isset($opts['timeout']) ? $opts['timeout'] : 0);
+ $this->netVolumesSessionKey = !empty($opts['netVolumesSessionKey'])? $opts['netVolumesSessionKey'] : 'elFinderNetVolumes';
+ $this->callbackWindowURL = (isset($opts['callbackWindowURL']) ? $opts['callbackWindowURL'] : '');
+
+ // setlocale and global locale regists to elFinder::locale
+ self::$locale = !empty($opts['locale']) ? $opts['locale'] : 'en_US.UTF-8';
+ if (false === @setlocale(LC_ALL, self::$locale)) {
+ self::$locale = setlocale(LC_ALL, '');
+ }
+
+ // bind events listeners
+ if (!empty($opts['bind']) && is_array($opts['bind'])) {
+ $_req = $_SERVER["REQUEST_METHOD"] == 'POST' ? $_POST : $_GET;
+ $_reqCmd = isset($_req['cmd']) ? $_req['cmd'] : '';
+ foreach ($opts['bind'] as $cmd => $handlers) {
+ $doRegist = (strpos($cmd, '*') !== false);
+ if (! $doRegist) {
+ $_getcmd = create_function('$cmd', 'list($ret) = explode(\'.\', $cmd);return trim($ret);');
+ $doRegist = ($_reqCmd && in_array($_reqCmd, array_map($_getcmd, explode(' ', $cmd))));
+ }
+ if ($doRegist) {
+ if (! is_array($handlers) || is_object($handlers[0])) {
+ $handlers = array($handlers);
+ }
+ foreach($handlers as $handler) {
+ if ($handler) {
+ if (is_string($handler) && strpos($handler, '.')) {
+ list($_domain, $_name, $_method) = array_pad(explode('.', $handler), 3, '');
+ if (strcasecmp($_domain, 'plugin') === 0) {
+ if ($plugin = $this->getPluginInstance($_name, isset($opts['plugin'][$_name])? $opts['plugin'][$_name] : array())
+ and method_exists($plugin, $_method)) {
+ $this->bind($cmd, array($plugin, $_method));
+ }
+ }
+ } else {
+ $this->bind($cmd, $handler);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!isset($opts['roots']) || !is_array($opts['roots'])) {
+ $opts['roots'] = array();
+ }
+
+ // check for net volumes stored in session
+ foreach ($this->getNetVolumes() as $root) {
+ $opts['roots'][] = $root;
+ }
+
+ // "mount" volumes
+ foreach ($opts['roots'] as $i => $o) {
+ //$class = 'elFinderVolume'.(isset($o['driver']) ? $o['driver'] : '');
+ $class = isset($o['driver']) ? $o['driver'] : '';
+
+ if (class_exists($class)) {
+ $volume = new $class();
+
+ if ($volume->mount($o)) {
+ // unique volume id (ends on "_") - used as prefix to files hash
+ $id = $volume->id();
+
+ $this->volumes[$id] = $volume;
+ if (!$this->default && $volume->isReadable()) {
+ $this->default = $this->volumes[$id];
+ }
+ } else {
+ $this->mountErrors[] = 'Driver "'.$class.'" : '.implode(' ', $volume->error());
+ }
+ } else {
+ $this->mountErrors[] = 'Driver "'.$class.'" does not exists';
+ }
+ }
+
+ // if at least one readable volume - ii desu >_<
+ $this->loaded = !empty($this->default);
+ }
+}
diff --git a/src/Chamilo/CoreBundle/Component/Editor/TinyMce/TinyMce.php b/src/Chamilo/CoreBundle/Component/Editor/TinyMce/TinyMce.php
new file mode 100644
index 0000000000..78a39e44f9
--- /dev/null
+++ b/src/Chamilo/CoreBundle/Component/Editor/TinyMce/TinyMce.php
@@ -0,0 +1,82 @@
+template->addResource($jsFolder.'tinymce/tinymce.min.js', 'js');
+ }
+
+ /**
+ * @return string
+ */
+ public function getEditorTemplate()
+ {
+ return 'javascript/editor/tinymce/elfinder.tpl';
+ }
+
+ /**
+ * Return the HTML code required to run editor.
+ *
+ * @return string
+ */
+ public function createHtml()
+ {
+ $html = '';
+ $html .= $this->editorReplace();
+
+ return $html;
+ }
+
+ /**
+ * @return string
+ */
+ public function editorReplace()
+ {
+ $toolbar = new Toolbar\Basic($this->urlGenerator, $this->toolbarSet, $this->config, 'TinyMce');
+ $toolbar->setLanguage($this->getLocale());
+ $config = $toolbar->getConfig();
+ $config['selector'] = "#".$this->name;
+ $javascript = $this->toJavascript($config);
+ $javascript = str_replace('"elFinderBrowser"', "elFinderBrowser", $javascript);
+
+ $html = "";
+
+ return $html;
+ }
+}
diff --git a/src/Chamilo/CoreBundle/Component/Editor/TinyMce/Toolbar/Basic.php b/src/Chamilo/CoreBundle/Component/Editor/TinyMce/Toolbar/Basic.php
new file mode 100644
index 0000000000..006c17a934
--- /dev/null
+++ b/src/Chamilo/CoreBundle/Component/Editor/TinyMce/Toolbar/Basic.php
@@ -0,0 +1,38 @@
+ "modern",
+ 'width'=> 300,
+ 'height'=> 300,
+ 'plugins'=> array(
+ "advlist autolink link image lists charmap print preview hr anchor pagebreak spellchecker",
+ "searchreplace wordcount visualblocks visualchars code fullscreen insertdatetime media nonbreaking",
+ "save table contextmenu directionality emoticons template paste textcolor"
+ ),
+ 'content_css'=> "css/content.css",
+ 'toolbar' => "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | l ink image | print preview media fullpage | forecolor backcolor emoticons",
+ 'file_browser_callback' => 'elFinderBrowser'
+ );
+
+ if (isset($this->config)) {
+ $this->config = array_merge($config, $this->config);
+ } else {
+ $this->config = $config;
+ }
+
+ return $this->config;
+ }
+}
diff --git a/src/Chamilo/CoreBundle/Component/Editor/Toolbar.php b/src/Chamilo/CoreBundle/Component/Editor/Toolbar.php
new file mode 100644
index 0000000000..5a61fbbe4b
--- /dev/null
+++ b/src/Chamilo/CoreBundle/Component/Editor/Toolbar.php
@@ -0,0 +1,120 @@
+setConfig($toolbarObj->getConfig());
+ }
+ }
+
+ if (!empty($config)) {
+ $this->updateConfig($config);
+ }
+ //$this->urlGenerator = $urlGenerator;
+ }
+
+ /**
+ * @return string
+ */
+ public function getPluginsToString()
+ {
+ $plugins = array_filter(array_merge($this->getDefaultPlugins(), $this->getPlugins()));
+
+ return
+ $this->getConfigAttribute('extraPlugins').
+ implode(',', $plugins);
+ }
+
+ /**
+ * @return array
+ */
+ public function getPlugins()
+ {
+ return $this->plugins;
+ }
+
+ /**
+ * @return array
+ */
+ public function getDefaultPlugins()
+ {
+ return $this->defaultPlugins;
+ }
+
+ /**
+ * @param array $config
+ */
+ public function setConfig(array $config)
+ {
+ $this->config = $config;
+ }
+
+ /**
+ * @param array $config
+ */
+ public function updateConfig(array $config)
+ {
+ if (empty($this->config)) {
+ $this->setConfig($config);
+ } else {
+ $this->config = array_merge($this->config, $config);
+ }
+ }
+
+ /**
+ * @return array
+ */
+ public function getConfig()
+ {
+ return $this->config;
+ }
+
+ /**
+ * @param string $variable
+ *
+ * @return array
+ */
+ public function getConfigAttribute($variable)
+ {
+ if (isset($this->config[$variable])) {
+ return $this->config[$variable];
+ }
+
+ return null;
+ }
+
+ /**
+ * @param string $language
+ */
+ public function setLanguage($language)
+ {
+ $this->config['language'] = $language;
+ }
+}