Portfolio: Add subcategories, templates, new filters - refs BT#19052

pull/3973/head
Christian 4 years ago
parent 8196eb8e70
commit 210a4e20a5
  1. 40
      main/admin/settings.lib.php
  2. 57
      main/inc/ajax/lang.ajax.php
  3. 508
      main/inc/lib/PortfolioController.php
  4. 5
      main/install/configuration.dist.php
  5. 43
      main/portfolio/index.php
  6. 34
      main/template/default/portfolio/list.html.twig
  7. 25
      src/Chamilo/CoreBundle/Component/Editor/CkEditor/CkEditor.php
  8. 27
      src/Chamilo/CoreBundle/Entity/PortfolioCategory.php
  9. 31
      src/Chamilo/CoreBundle/Entity/SystemTemplate.php

@ -1227,8 +1227,14 @@ function displayTemplates()
);
$table->set_header(0, get_lang('Image'), true, ['style' => 'width: 101px;']);
$table->set_header(1, get_lang('Title'));
$table->set_header(2, get_lang('Actions'), false, ['style' => 'width:50px;']);
$table->set_column_filter(2, 'actionsFilter');
if (true === api_get_configuration_value('template_activate_language_filter')) {
$table->set_header(2, get_lang('Language'));
$table->set_header(3, get_lang('Actions'), false, ['style' => 'width:50px;']);
$table->set_column_filter(3, 'actionsFilter');
} else {
$table->set_header(2, get_lang('Actions'), false, ['style' => 'width:50px;']);
$table->set_column_filter(2, 'actionsFilter');
}
$table->set_column_filter(0, 'searchImageFilter');
$table->display();
}
@ -1285,7 +1291,11 @@ function getTemplateData($from, $number_of_items, $column, $direction)
$direction = !in_array(strtolower(trim($direction)), ['asc', 'desc']) ? 'asc' : $direction;
// The sql statement.
$sql = "SELECT image as col0, title as col1, id as col2 FROM $table_system_template";
if (true === api_get_configuration_value('template_activate_language_filter')) {
$sql = "SELECT image as col0, title as col1, language as col2, id as col3 FROM $table_system_template";
} else {
$sql = "SELECT image as col0, title as col1, id as col2 FROM $table_system_template";
}
$sql .= " ORDER BY col$column $direction ";
$sql .= " LIMIT $from,$number_of_items";
$result = Database::query($sql);
@ -1353,6 +1363,8 @@ function searchImageFilter($image)
*/
function addEditTemplate()
{
global $language_interface;
$em = Database::getManager();
// Initialize the object.
$id = isset($_GET['id']) ? (int) $_GET['id'] : 0;
@ -1386,6 +1398,11 @@ function addEditTemplate()
true,
['ToolbarSet' => 'Documents', 'Width' => '100%', 'Height' => '400']
);
if (true === api_get_configuration_value('template_activate_language_filter')) {
$form->addSelectLanguage('language', get_lang('Language'), null);
} else {
$form->addHidden('language', $language_interface);
}
// Setting the form elements: the form to upload an image to be used with the template.
if (empty($template->getImage())) {
@ -1402,6 +1419,7 @@ function addEditTemplate()
// Forcing get_lang().
$defaults['title'] = $template->getTitle();
$defaults['comment'] = $template->getComment();
$defaults['language'] = $template->getLanguage();
// Adding an extra field: a hidden field with the id of the template we are editing.
$form->addElement('hidden', 'template_id');
@ -1446,8 +1464,7 @@ function addEditTemplate()
// if the form validates (complies to all rules) we save the information,
// else we display the form again (with error message if needed)
if ($form->validate()) {
$check = Security::check_token('post');
$check = Security::check_token('post', null, 'frm');
if ($check) {
// Exporting the values.
$values = $form->exportValues();
@ -1498,6 +1515,7 @@ function addEditTemplate()
->setTitle($values['title'])
->setComment(Security::remove_XSS($values['comment']))
->setContent(Security::remove_XSS($templateContent, COURSEMANAGERLOWSECURITY))
->setLanguage($values['language'])
->setImage($new_file_name);
$em->persist($template);
$em->flush();
@ -1515,6 +1533,7 @@ function addEditTemplate()
$template
->setTitle($values['title'])
->setComment(Security::remove_XSS($values['comment']))
->setLanguage($values['language'])
->setContent(Security::remove_XSS($templateContent, COURSEMANAGERLOWSECURITY));
if ($isDelete) {
@ -1536,12 +1555,13 @@ function addEditTemplate()
echo Display::return_message(get_lang('TemplateEdited'), 'confirm');
}
}
Security::clear_token();
displayTemplates();
Security::clear_token('frm');
header('Location: '.api_get_path(WEB_CODE_PATH).'admin/settings.php?category=Templates');
exit;
} else {
$token = Security::get_token();
$form->addElement('hidden', 'sec_token');
$form->setConstants(['sec_token' => $token]);
$token = Security::get_token('frm');
$form->addElement('hidden', 'frm_sec_token');
$form->setConstants(['frm_sec_token' => $token]);
// Display the form.
$form->display();
}

@ -16,6 +16,63 @@ switch ($action) {
echo api_get_language_translate_html();
break;
case 'translate_portfolio_category':
if (isset($_REQUEST['new_language']) && isset($_REQUEST['variable_language']) && isset($_REQUEST['category_id'])) {
$newLanguage = Security::remove_XSS($_REQUEST['new_language']);
$langVariable = Security::remove_XSS($_REQUEST['variable_language']);
$categoryId = (int) $_REQUEST['category_id'];
$languageId = (int) $_REQUEST['id'];
$subLanguageId = (int) $_REQUEST['sub'];
$langFilesToLoad = SubLanguageManager:: get_lang_folder_files_list(
api_get_path(SYS_LANG_PATH).'english',
true
);
$fileLanguage = $langFilesToLoad[0].'.inc.php';
$allDataOfLanguage = SubLanguageManager::get_all_information_of_sub_language($languageId, $subLanguageId);
$pathFolder = api_get_path(SYS_LANG_PATH).$allDataOfLanguage['dokeos_folder'].'/'.$fileLanguage;
$allFileOfDirectory = SubLanguageManager::get_all_language_variable_in_file($pathFolder);
$returnValue = SubLanguageManager::add_file_in_language_directory($pathFolder);
//update variable language
// Replace double quotes to avoid parse errors
$newLanguage = str_replace('"', '\"', $newLanguage);
$newLanguage = str_replace("\n", "\\n", $newLanguage);
$allFileOfDirectory[$langVariable] = "\"".$newLanguage."\";";
$resultArray = [];
foreach ($allFileOfDirectory as $key => $value) {
$resultArray[$key] = SubLanguageManager::write_data_in_file($pathFolder, $value, $key);
}
$variablesWithProblems = '';
if (!empty($resultArray)) {
foreach ($resultArray as $key => $result) {
if ($result == false) {
$variablesWithProblems .= $key.' <br />';
}
}
}
if (isset($_REQUEST['redirect'])) {
$message = Display::return_message(get_lang('TheNewWordHasBeenAdded'), 'success');
if (!empty($variablesWithProblems)) {
$message = Display::return_message(
$pathFolder.' '.get_lang('IsNotWritable').'<br /> '.api_ucwords(get_lang('ErrorsFound'))
.': <br />'.$variablesWithProblems,
'error'
);
}
Display::addFlash($message);
header('Location: '.api_get_path(WEB_CODE_PATH).'portfolio/index.php?'.api_get_cidreq().'&action=translate_category&id='.$categoryId.'&sub_language='.$subLanguageId);
exit;
}
}
break;
default:
echo '';
}

@ -56,6 +56,188 @@ class PortfolioController
$this->baseUrl = api_get_self().'?'.($cidreq ? $cidreq.'&' : '');
}
/**
*
* @throws \Doctrine\ORM\ORMException
* @throws \Doctrine\ORM\OptimisticLockException
*/
public function translateCategory($category, $languages, $languageId)
{
global $interbreadcrumb;
$originalName = $category->getTitle();
$variableLanguage = '$'.$this->getLanguageVariable($originalName);
$translateUrl = api_get_path(WEB_AJAX_PATH).'lang.ajax.php?a=translate_portfolio_category';
$form = new FormValidator('new_lang_variable', 'POST', $translateUrl);
$form->addHeader(get_lang('AddWordForTheSubLanguage'));
$form->addText('variable_language', get_lang('LanguageVariable'), false);
$form->addText('original_name', get_lang('OriginalName'), false);
$languagesOptions = [0 => get_lang('None')];
foreach ($languages as $language) {
$languagesOptions[$language->getId()] = $language->getOriginalName();
}
$form->addSelect(
'sub_language',
[get_lang('SubLanguage'), get_lang('OnlyActiveSubLanguagesAreListed')],
$languagesOptions
);
if ($languageId) {
$languageInfo = api_get_language_info($languageId);
$form->addText(
'new_language',
[get_lang('Translation'), get_lang('IfThisTranslationExistsThisWillReplaceTheTerm')]
);
$form->addHidden('category_id', $category->getId());
$form->addHidden('id', $languageInfo['parent_id']);
$form->addHidden('sub', $languageInfo['id']);
$form->addHidden('sub_language_id', $languageInfo['id']);
$form->addHidden('redirect', true);
$form->addButtonSave(get_lang('Save'));
}
$form->setDefaults([
'variable_language' => $variableLanguage,
'original_name' => $originalName,
'sub_language' => $languageId,
]);
$form->addRule('sub_language', get_lang('Required'), 'required');
$form->freeze(['variable_language', 'original_name']);
$interbreadcrumb[] = [
'name' => get_lang('Portfolio'),
'url' => $this->baseUrl,
];
$interbreadcrumb[] = [
'name' => get_lang('Categories'),
'url' => $this->baseUrl.'action=list_categories&parent_id='.$category->getParentId(),
];
$interbreadcrumb[] = [
'name' => Security::remove_XSS($category->getTitle()),
'url' => $this->baseUrl.'action=edit_category&id='.$category->getId(),
];
$actions = [];
$actions[] = Display::url(
Display::return_icon('back.png', get_lang('Back'), [], ICON_SIZE_MEDIUM),
$this->baseUrl.'action=edit_category&id='.$category->getId()
);
$js = '<script>
$(function() {
$("select[name=\'sub_language\']").on("change", function () {
location.href += "&sub_language=" + this.value;
});
});
</script>';
$content = $form->returnForm();
$this->renderView($content.$js, get_lang('TranslateCategory'), $actions);
}
/**
* @throws \Doctrine\ORM\ORMException
* @throws \Doctrine\ORM\OptimisticLockException
*/
public function listCategories()
{
global $interbreadcrumb;
$parentId = isset($_REQUEST['parent_id']) ? (int) $_REQUEST['parent_id'] : 0;
$table = new HTML_Table(['class' => 'table table-hover table-striped data_table']);
$headers = [
get_lang('Title'),
get_lang('Description'),
];
if ($parentId === 0) {
$headers[] = get_lang('SubCategories');
}
$headers[] = get_lang('Actions');
$column = 0;
foreach ($headers as $header) {
$table->setHeaderContents(0, $column, $header);
$column++;
}
$currentUserId = api_get_user_id();
$row = 1;
$categories = $this->getCategoriesForIndex(null, $parentId);
foreach ($categories as $category) {
$column = 0;
$subcategories = $this->getCategoriesForIndex(null, $category->getId());
$linkSubCategories = $category->getTitle();
if (count($subcategories) > 0) {
$linkSubCategories = Display::url(
$category->getTitle(),
$this->baseUrl.'action=list_categories&parent_id='.$category->getId()
);
}
$table->setCellContents($row, $column++, $linkSubCategories);
$table->setCellContents($row, $column++, strip_tags($category->getDescription()));
if ($parentId === 0) {
$table->setCellContents($row, $column++, count($subcategories));
}
// Actions
$links = null;
// Edit action
$url = $this->baseUrl.'action=edit_category&id='.$category->getId();
$links .= Display::url(Display::return_icon('edit.png', get_lang('Edit')), $url).'&nbsp;';
// Visible action : if active
if ($category->isVisible() != 0) {
$url = $this->baseUrl.'action=hide_category&id='.$category->getId();
$links .= Display::url(Display::return_icon('visible.png', get_lang('Hide')), $url).'&nbsp;';
} else { // else if not active
$url = $this->baseUrl.'action=show_category&id='.$category->getId();
$links .= Display::url(Display::return_icon('invisible.png', get_lang('Show')), $url).'&nbsp;';
}
// Delete action
$url = $this->baseUrl.'action=delete_category&id='.$category->getId();
$links .= Display::url(Display::return_icon('delete.png', get_lang('Delete')), $url, ['onclick' => 'javascript:if(!confirm(\''.get_lang('AreYouSureToDeleteJS').'\')) return false;']);
$table->setCellContents($row, $column++, $links);
$row++;
}
$interbreadcrumb[] = [
'name' => get_lang('Portfolio'),
'url' => $this->baseUrl,
];
if ($parentId > 0) {
$interbreadcrumb[] = [
'name' => get_lang('Categories'),
'url' => $this->baseUrl.'action=list_categories',
];
}
$actions = [];
$actions[] = Display::url(
Display::return_icon('back.png', get_lang('Back'), [], ICON_SIZE_MEDIUM),
$this->baseUrl.($parentId > 0 ? 'action=list_categories' : '')
);
if ($currentUserId == $this->owner->getId() && $parentId === 0) {
$actions[] = Display::url(
Display::return_icon('new_folder.png', get_lang('AddCategory'), [], ICON_SIZE_MEDIUM),
$this->baseUrl.'action=add_category'
);
}
$content = $table->toHtml();
$pageTitle = get_lang('Categories');
if ($parentId > 0) {
$em = Database::getManager();
$parentCategory = $em->find('ChamiloCoreBundle:PortfolioCategory', $parentId);
$pageTitle = $parentCategory->getTitle().' : '.get_lang('SubCategories');
}
$this->renderView($content, $pageTitle, $actions);
}
/**
* @throws \Doctrine\ORM\ORMException
* @throws \Doctrine\ORM\OptimisticLockException
@ -78,6 +260,18 @@ class PortfolioController
}
$form->addHtmlEditor('description', get_lang('Description'), false, false, ['ToolbarSet' => 'Minimal']);
$parentSelect = $form->addSelect(
'parent_id',
get_lang('ParentCategory')
);
$parentSelect->addOption(get_lang('Level0'), 0);
$currentUserId = api_get_user_id();
$categories = $this->getCategoriesForIndex(null, 0);
foreach ($categories as $category) {
$parentSelect->addOption($category->getTitle(), $category->getId());
}
$form->addButtonCreate(get_lang('Create'));
if ($form->validate()) {
@ -87,6 +281,7 @@ class PortfolioController
$category
->setTitle($values['title'])
->setDescription($values['description'])
->setParentId($values['parent_id'])
->setUser($this->owner);
$this->em->persist($category);
@ -96,7 +291,7 @@ class PortfolioController
Display::return_message(get_lang('CategoryAdded'), 'success')
);
header("Location: {$this->baseUrl}");
header("Location: {$this->baseUrl}action=list_categories");
exit;
}
@ -104,11 +299,15 @@ class PortfolioController
'name' => get_lang('Portfolio'),
'url' => $this->baseUrl,
];
$interbreadcrumb[] = [
'name' => get_lang('Categories'),
'url' => $this->baseUrl.'action=list_categories',
];
$actions = [];
$actions[] = Display::url(
Display::return_icon('back.png', get_lang('Back'), [], ICON_SIZE_MEDIUM),
$this->baseUrl
$this->baseUrl.'action=list_categories'
);
$content = $form->returnForm();
@ -142,7 +341,12 @@ class PortfolioController
if (api_get_configuration_value('save_titles_as_html')) {
$form->addHtmlEditor('title', get_lang('Title'), true, false, ['ToolbarSet' => 'TitleAsHtml']);
} else {
$form->addText('title', get_lang('Title'));
$translateUrl = $this->baseUrl.'action=translate_category&id='.$category->getId();
$translateButton = Display::toolbarButton(get_lang('TranslateThisTerm'), $translateUrl, 'language', 'link');
$form->addText(
'title',
[get_lang('Title'), $translateButton]
);
$form->applyFilter('title', 'trim');
}
@ -169,7 +373,7 @@ class PortfolioController
Display::return_message(get_lang('Updated'), 'success')
);
header("Location: $this->baseUrl");
header("Location: {$this->baseUrl}action=list_categories&parent_id=".$category->getParentId());
exit;
}
@ -177,11 +381,24 @@ class PortfolioController
'name' => get_lang('Portfolio'),
'url' => $this->baseUrl,
];
$interbreadcrumb[] = [
'name' => get_lang('Categories'),
'url' => $this->baseUrl.'action=list_categories',
];
if ($category->getParentId() > 0) {
$em = Database::getManager();
$parentCategory = $em->find('ChamiloCoreBundle:PortfolioCategory', $category->getParentId());
$pageTitle = $parentCategory->getTitle().' : '.get_lang('SubCategories');
$interbreadcrumb[] = [
'name' => Security::remove_XSS($pageTitle),
'url' => $this->baseUrl.'action=list_categories&parent_id='.$category->getParentId(),
];
}
$actions = [];
$actions[] = Display::url(
Display::return_icon('back.png', get_lang('Back'), [], ICON_SIZE_MEDIUM),
$this->baseUrl
$this->baseUrl.'action=list_categories&parent_id='.$category->getParentId()
);
$content = $form->returnForm();
@ -208,7 +425,7 @@ class PortfolioController
Display::return_message(get_lang('VisibilityChanged'), 'success')
);
header("Location: $this->baseUrl");
header("Location: {$this->baseUrl}action=list_categories");
exit;
}
@ -229,7 +446,7 @@ class PortfolioController
Display::return_message(get_lang('CategoryDeleted'), 'success')
);
header("Location: $this->baseUrl");
header("Location: {$this->baseUrl}action=list_categories");
exit;
}
@ -243,10 +460,6 @@ class PortfolioController
{
global $interbreadcrumb;
$categories = $this->em
->getRepository('ChamiloCoreBundle:PortfolioCategory')
->findBy(['user' => $this->owner]);
$form = new FormValidator('add_portfolio', 'post', $this->baseUrl.'action=add_item');
if (api_get_configuration_value('save_titles_as_html')) {
@ -255,15 +468,29 @@ class PortfolioController
$form->addText('title', get_lang('Title'));
$form->applyFilter('title', 'trim');
}
$editorConfig = [
'ToolbarSet' => 'NotebookStudent',
'Width' => '100%',
'Height' => '400',
'cols-size' => [2, 10, 0],
];
$form->addHtmlEditor('content', get_lang('Content'), true, false, $editorConfig);
$form->addHtmlEditor('content', get_lang('Content'), true, false, ['ToolbarSet' => 'NotebookStudent']);
$form->addSelectFromCollection(
$categoriesSelect = $form->addSelect(
'category',
[get_lang('Category'), get_lang('PortfolioCategoryFieldHelp')],
$categories,
[],
true
[get_lang('Category'), get_lang('PortfolioCategoryFieldHelp')]
);
$categoriesSelect->addOption(get_lang('SelectACategory'), 0);
$parentCategories = $this->getCategoriesForIndex(null, 0);
foreach ($parentCategories as $parentCategory) {
$categoriesSelect->addOption($parentCategory->getTitle(), $parentCategory->getId());
$subCategories = $this->getCategoriesForIndex(null, $parentCategory->getId());
if (count($subCategories) > 0) {
foreach ($subCategories as $subCategory) {
$categoriesSelect->addOption(' &mdash; '.$subCategory->getTitle(), $subCategory->getId());
}
}
}
$extraField = new ExtraField('portfolio');
$extra = $extraField->addElements($form);
@ -360,11 +587,46 @@ class PortfolioController
Display::return_icon('back.png', get_lang('Back'), [], ICON_SIZE_MEDIUM),
$this->baseUrl
);
$content = $form->returnForm();
$actions[] = '<a id="hide_bar_template" href="#" role="button">'.
Display::return_icon('expand.png', get_lang('Expand'), ['id' => 'expand'], ICON_SIZE_MEDIUM).
Display::return_icon('contract.png', get_lang('Collapse'), ['id' => 'contract', 'class' => 'hide'], ICON_SIZE_MEDIUM).'</a>';
$js = '<script>
$(function() {
$(".scrollbar-light").scrollbar();
$(".scroll-wrapper").css("height", "550px");
expandColumnToogle("#hide_bar_template", {
selector: "#template_col",
width: 3
}, {
selector: "#doc_form",
width: 9
});
CKEDITOR.on("instanceReady", function (e) {
showTemplates();
});
$(window).on("load", function () {
$("input[name=\'title\']").focus();
});
'.$extra['jquery_ready_content'].'
});
</script>';
$content = '<div class="page-create">
<div class="row" style="overflow:hidden">
<div id="template_col" class="col-md-3">
<div class="panel panel-default">
<div class="panel-body">
<div id="frmModel" class="items-templates scrollbar-light"></div>
</div>
</div>
</div>
<div id="doc_form" class="col-md-9">
'.$form->returnForm().'
</div>
</div></div>';
$this->renderView(
$content."<script> $(function() { {$extra['jquery_ready_content']} }); </script>",
$content.$js,
get_lang('AddPortfolioItem'),
$actions
);
@ -418,8 +680,13 @@ class PortfolioController
);
}
}
$form->addHtmlEditor('content', get_lang('Content'), true, false, ['ToolbarSet' => 'NotebookStudent']);
$editorConfig = [
'ToolbarSet' => 'NotebookStudent',
'Width' => '100%',
'Height' => '400',
'cols-size' => [2, 10, 0],
];
$form->addHtmlEditor('content', get_lang('Content'), true, false, $editorConfig);
$form->addSelectFromCollection(
'category',
[get_lang('Category'), get_lang('PortfolioCategoryFieldHelp')],
@ -492,10 +759,46 @@ class PortfolioController
Display::return_icon('back.png', get_lang('Back'), [], ICON_SIZE_MEDIUM),
$this->baseUrl
);
$content = $form->returnForm();
$actions[] = '<a id="hide_bar_template" href="#" role="button">'.
Display::return_icon('expand.png', get_lang('Expand'), ['id' => 'expand'], ICON_SIZE_MEDIUM).
Display::return_icon('contract.png', get_lang('Collapse'), ['id' => 'contract', 'class' => 'hide'], ICON_SIZE_MEDIUM).'</a>';
$js = '<script>
$(function() {
$(".scrollbar-light").scrollbar();
$(".scroll-wrapper").css("height", "550px");
expandColumnToogle("#hide_bar_template", {
selector: "#template_col",
width: 3
}, {
selector: "#doc_form",
width: 9
});
CKEDITOR.on("instanceReady", function (e) {
showTemplates();
});
$(window).on("load", function () {
$("input[name=\'title\']").focus();
});
'.$extra['jquery_ready_content'].'
});
</script>';
$content = '<div class="page-create">
<div class="row" style="overflow:hidden">
<div id="template_col" class="col-md-3">
<div class="panel panel-default">
<div class="panel-body">
<div id="frmModel" class="items-templates scrollbar-light"></div>
</div>
</div>
</div>
<div id="doc_form" class="col-md-9">
'.$form->returnForm().'
</div>
</div></div>';
$this->renderView(
$content."<script> $(function() { {$extra['jquery_ready_content']} }); </script>",
$content.$js,
get_lang('EditPortfolioItem'),
$actions
);
@ -568,51 +871,115 @@ class PortfolioController
$actions = [];
if ($currentUserId == $this->owner->getId()) {
if (api_is_platform_admin()) {
$actions[] = Display::url(
Display::return_icon('add.png', get_lang('Add'), [], ICON_SIZE_MEDIUM),
$this->baseUrl.'action=add_item'
);
$actions[] = Display::url(
Display::return_icon('folder.png', get_lang('AddCategory'), [], ICON_SIZE_MEDIUM),
$this->baseUrl.'action=add_category'
$this->baseUrl.'action=list_categories'
);
$actions[] = Display::url(
Display::return_icon('waiting_list.png', get_lang('PortfolioDetails'), [], ICON_SIZE_MEDIUM),
$this->baseUrl.'action=details'
);
} else {
$actions[] = Display::url(
Display::return_icon('back.png', get_lang('Back'), [], ICON_SIZE_MEDIUM),
$this->baseUrl
);
if ($currentUserId == $this->owner->getId()) {
$actions[] = Display::url(
Display::return_icon('add.png', get_lang('Add'), [], ICON_SIZE_MEDIUM),
$this->baseUrl.'action=add_item'
);
$actions[] = Display::url(
Display::return_icon('waiting_list.png', get_lang('PortfolioDetails'), [], ICON_SIZE_MEDIUM),
$this->baseUrl.'action=details'
);
} else {
$actions[] = Display::url(
Display::return_icon('back.png', get_lang('Back'), [], ICON_SIZE_MEDIUM),
$this->baseUrl
);
}
}
$frmStudentList = null;
$frmTagList = null;
$categories = [];
$portfolio = [];
if ($this->course) {
$frmTagList = $this->createFormTagFilter($listByUser);
$frmStudentList = $this->createFormStudentFilter($listByUser);
$frmStudentList->setDefaults(['user' => $this->owner->getId()]);
// it translates the category title with the current user language
$categories = $this->getCategoriesForIndex(null, 0);
if (count($categories) > 0) {
foreach ($categories as &$category) {
$translated = $this->translateDisplayName($category->getTitle());
$category->setTitle($translated);
}
}
} else {
$categories = $this->getCategoriesForIndex($currentUserId);
// it displays the list in Network Social for the current user
$portfolio = $this->getCategoriesForIndex();
}
$items = $this->getItemsForIndex($listByUser, $frmTagList);
// it gets and translate the sub-categories
$categoryId = $httpRequest->query->getInt('categoryId');
$subCategoryIdsReq = isset($_REQUEST['subCategoryIds']) ? Security::remove_XSS($_REQUEST['subCategoryIds']) : '';
$subCategoryIds = $subCategoryIdsReq;
if ('all' !== $subCategoryIdsReq) {
$subCategoryIds = !empty($subCategoryIdsReq) ? explode(',', $subCategoryIdsReq) : [];
}
$subcategories = [];
if ($categoryId > 0) {
$subcategories = $this->getCategoriesForIndex(null, $categoryId);
if (count($subcategories) > 0) {
foreach ($subcategories as &$subcategory) {
$translated = $this->translateDisplayName($subcategory->getTitle());
$subcategory->setTitle($translated);
}
}
}
$template = new Template(null, false, false, false, false, false, false);
$template->assign('user', $this->owner);
$template->assign('course', $this->course);
$template->assign('session', $this->session);
$template->assign('portfolio', $categories);
$template->assign('portfolio', $portfolio);
$template->assign('categories', $categories);
$template->assign('uncategorized_items', $items);
$template->assign('frm_student_list', $this->course ? $frmStudentList->returnForm() : '');
$template->assign('frm_tag_list', $this->course ? $frmTagList->returnForm() : '');
$template->assign('category_id', $categoryId);
$template->assign('subcategories', $subcategories);
$template->assign('subcategory_ids', $subCategoryIds);
$js = '<script>
$(function() {
$(".category-filters").bind("click", function() {
var categoryId = parseInt($(this).find("input[type=\'radio\']").val());
$("input[name=\'categoryId\']").val(categoryId);
$("input[name=\'subCategoryIds\']").val("all");
$("#frm_tag_list_submit").trigger("click");
});
$(".subcategory-filters").bind("click", function() {
var checkedVals = $(".subcategory-filters:checkbox:checked").map(function() {
return this.value;
}).get();
$("input[name=\'subCategoryIds\']").val(checkedVals.join(","));
$("#frm_tag_list_submit").trigger("click");
});
});
</script>';
$template->assign('js_script', $js);
$layout = $template->get_template('portfolio/list.html.twig');
Display::addFlash(
Display::return_message(get_lang('PortfolioPostAddHelp'), 'info', false)
);
$content = $template->fetch($layout);
$this->renderView($content, get_lang('Portfolio'), $actions);
@ -2033,6 +2400,8 @@ class PortfolioController
$frmTagList->addHidden('gidReq', 0);
$frmTagList->addHidden('gradebook', 0);
$frmTagList->addHidden('origin', '');
$frmTagList->addHidden('categoryId', 0);
$frmTagList->addHidden('subCategoryIds', '');
if ($listByUser) {
$frmTagList->addHidden('user', $this->owner->getId());
@ -2098,15 +2467,18 @@ class PortfolioController
return $frmStudentList;
}
private function getCategoriesForIndex(int $currentUserId): array
private function getCategoriesForIndex(?int $currentUserId = null, ?int $parentId = null): array
{
$categoriesCriteria = [];
$categoriesCriteria['user'] = $this->owner;
if ($currentUserId !== $this->owner->getId()) {
if (isset($currentUserId)) {
$categoriesCriteria['user'] = $this->owner;
}
if (!api_is_platform_admin() && $currentUserId !== $this->owner->getId()) {
$categoriesCriteria['isVisible'] = true;
}
if (isset($parentId)) {
$categoriesCriteria['parentId'] = $parentId;
}
return $this->em
->getRepository(PortfolioCategory::class)
->findBy($categoriesCriteria);
@ -2160,6 +2532,36 @@ class PortfolioController
$queryBuilder->setParameter('text', '%'.$values['text'].'%');
}
// Filters by category level 0
$searchCategories = [];
if (!empty($values['categoryId'])) {
$searchCategories[] = $values['categoryId'];
$subCategories = $this->getCategoriesForIndex(null, $values['categoryId']);
if (count($subCategories) > 0) {
foreach ($subCategories as $subCategory) {
$searchCategories[] = $subCategory->getId();
}
}
$queryBuilder->andWhere('pi.category IN('.implode(',', $searchCategories).')');
}
// Filters by sub-category, don't show the selected values
$diff = [];
if (!empty($values['subCategoryIds']) && !('all' === $values['subCategoryIds'])) {
$subCategoryIds = explode(',', $values['subCategoryIds']);
$diff = array_diff($searchCategories, $subCategoryIds);
} else {
if (trim($values['subCategoryIds']) === '') {
$diff = $searchCategories;
}
}
if (!empty($diff)) {
unset($diff[0]);
if (!empty($diff)) {
$queryBuilder->andWhere('pi.category NOT IN('.implode(',', $diff).')');
}
}
}
if ($listByUser) {
@ -2515,4 +2917,32 @@ class PortfolioController
return $doc->saveHTML();
}
/**
* It parsers a title for a variable in lang
*
* @param $defaultDisplayText
* @return string
*/
private function getLanguageVariable($defaultDisplayText)
{
$variableLanguage = api_replace_dangerous_char(strtolower($defaultDisplayText));
$variableLanguage = str_replace('-', '_', $variableLanguage);
$variableLanguage = api_underscore_to_camel_case($variableLanguage);
return $variableLanguage;
}
/**
* It translates the text as parameter
*
* @param $defaultDisplayText
* @return mixed
*/
private function translateDisplayName($defaultDisplayText)
{
$variableLanguage = $this->getLanguageVariable($defaultDisplayText);
return isset($GLOBALS[$variableLanguage]) ? $GLOBALS[$variableLanguage] : $defaultDisplayText;
}
}

@ -450,6 +450,7 @@ ALTER TABLE c_tool CHANGE name name LONGTEXT NOT NULL;
-- Only with allow_portfolio_tool enabled
ALTER TABLE portfolio CHANGE title title LONGTEXT NOT NULL;
ALTER TABLE portfolio_category CHANGE title title LONGTEXT NOT NULL;
ALTER TABLE portfolio_category ADD parent_id INT(11) NOT NULL DEFAULT 0;
New changes:
@ -1132,6 +1133,10 @@ VALUES (2, 13, 'session_courses_read_only_mode', 'Lock Course In Session', 1, 1,
);*/
// $_configuration['mail_template_system'] = false;
// Enable filter by language for system and courses templates
//ALTER TABLE system_template ADD language VARCHAR(40) NOT NULL DEFAULT 'english';
// $_configuration['template_activate_language_filter'] = false;
// Students can only upload one publication
// $_configuration['allow_only_one_student_publication_per_user'] = false;

@ -19,16 +19,53 @@ if (false === api_get_configuration_value('allow_portfolio_tool')) {
api_not_allowed(true);
}
$httpRequest = HttpRequest::createFromGlobals();
$action = $httpRequest->query->get('action', 'list');
// It validates the management of categories will be only for admins
if (in_array($action , ['list_categories', 'add_category', 'edit_category']) && !api_is_platform_admin()) {
api_not_allowed(true);
}
// It includes the user language for translations
$checkUserLanguage = true;
if ($checkUserLanguage) {
global $_user;
$langPath = api_get_path(SYS_LANG_PATH).$_user['language'].'/trad4all.inc.php';
if (file_exists($langPath)) {
require_once $langPath;
}
}
$controller = new \PortfolioController();
$em = Database::getManager();
$httpRequest = HttpRequest::createFromGlobals();
$action = $httpRequest->query->get('action', 'list');
$htmlHeadXtra[] = api_get_js('portfolio.js');
switch ($action) {
case 'translate_category':
$id = $httpRequest->query->getInt('id');
$languageId = $httpRequest->query->getInt('sub_language');
/** @var PortfolioCategory $category */
$category = $em->find('ChamiloCoreBundle:PortfolioCategory', $id);
if (empty($category)) {
break;
}
$languages = $em
->getRepository('ChamiloCoreBundle:Language')
->findAllPlatformSubLanguages();
$controller->translateCategory($category, $languages, $languageId);
return;
case 'list_categories':
$controller->listCategories();
return;
case 'add_category':
$controller->addCategory();

@ -18,6 +18,37 @@
{% endif %}
<div class="{{ course ? 'col-md-9' : 'col-xs-12' }}">
{% if (categories) %}
<div class="btn-group" data-toggle="buttons">
{% for category in categories %}
<label class="btn btn-default category-filters {{ category_id == category.id ? "active" : "" }}">
<input type="radio" value="{{ category.id }}" {{ category_id == category.id ? "checked" : "" }}>
{{ category.title }}
</label>
{% endfor %}
<label class="btn btn-default category-filters {{ category_id == category.id ? "active" : "" }}">
<input type="radio" value="0" {{ category_id == 0 ? "checked" : "" }}> {{ 'All'|get_lang }}
</label>
</div>
{% if (subcategories) %}
<br />
<div class="btn-block">
{% for subcategory in subcategories %}
<label class="btn btn-default">
{% set checked = '' %}
{% if (subcategory_ids == 'all') %}
{% set checked = 'checked' %}
{% else %}
{% if subcategory.id in subcategory_ids %}
{% set checked = 'checked' %}
{% endif %}
{% endif %}
<input type="checkbox" value="{{ subcategory.id }}" {{ checked }} class="subcategory-filters" />&nbsp;{{ subcategory.title }}
</label>
{% endfor %}
</div>
{% endif %}
{% endif %}
{% if _u.id != user.id %}
<h3>{{ user.completeName }} <small>{{ user.username }}</small></h3>
{% endif %}
@ -99,3 +130,6 @@
{% endif %}
});
</script>
{% if (js_script) %}
{{ js_script }}
{% endif %}

@ -161,8 +161,8 @@ class CkEditor extends Editor
public function simpleFormatTemplates()
{
$templates = $this->getEmptyTemplate();
if (api_is_allowed_to_edit(false, true)) {
// The templates are visible for all users in the course
if (api_is_allowed_to_edit(false, true) || api_is_allowed_in_course()) {
$platformTemplates = $this->getPlatformTemplates();
$templates = array_merge($templates, $platformTemplates);
}
@ -208,8 +208,25 @@ class CkEditor extends Editor
*/
private function getPlatformTemplates()
{
$entityManager = \Database::getManager();
$systemTemplates = $entityManager->getRepository('ChamiloCoreBundle:SystemTemplate')->findAll();
if (true === api_get_configuration_value('template_activate_language_filter')) {
global $language_interface;
$courseInfo = api_get_course_info();
if (isset($courseInfo['language'])) {
$language = $courseInfo['language'];
} else {
$language = $language_interface;
}
$entityManager = \Database::getManager();
$systemTemplates = $entityManager->getRepository('ChamiloCoreBundle:SystemTemplate')->findBy([
'language' => $language,
]);
} else {
$entityManager = \Database::getManager();
$systemTemplates = $entityManager->getRepository('ChamiloCoreBundle:SystemTemplate')->findAll();
}
$cssTheme = api_get_path(WEB_CSS_PATH).'themes/'.api_get_visual_theme().'/';
$search = ['{CSS_THEME}', '{IMG_DIR}', '{REL_PATH}', '{COURSE_DIR}', '{CSS}'];
$replace = [

@ -62,6 +62,13 @@ class PortfolioCategory
*/
protected $isVisible = true;
/**
* @var int
*
* @ORM\Column(name="parent_id", type="integer")
*/
protected $parentId = 0;
/**
* @var \Doctrine\Common\Collections\ArrayCollection
*
@ -201,6 +208,26 @@ class PortfolioCategory
return $this;
}
/**
* @return int
*/
public function getParentId()
{
return $this->parentId;
}
/**
* @param int $parentId
*/
public function setParentId(int $parentId)
{
$this->parentId = $parentId;
return $this;
}
/**
* Get items.
*

@ -50,6 +50,13 @@ class SystemTemplate
*/
protected $content;
/**
* @var string
*
* @ORM\Column(name="language", type="string", length=40, nullable=true, unique=false)
*/
protected $language;
public function __construct()
{
$this->comment = '';
@ -151,6 +158,30 @@ class SystemTemplate
return $this->content;
}
/**
* Set language.
*
* @param string $language
*
* @return SystemTemplate
*/
public function setLanguage($language)
{
$this->language = $language;
return $this;
}
/**
* Get language.
*
* @return string
*/
public function getLanguage()
{
return $this->language;
}
/**
* Get id.
*

Loading…
Cancel
Save