Glossary updates see BT#10895

Remove glossary_title and glossary_comment madness.
Add update option when import from csv.
Format code.
Update docs.
ofaj
jmontoyaa 9 years ago
parent 04cd41642c
commit 412e4b567e
  1. 6
      main/glossary/glossary_ajax_request.php
  2. 103
      main/glossary/index.php
  3. 177
      main/inc/lib/glossary.lib.php
  4. 18
      main/inc/lib/internationalization.lib.php
  5. 2
      tests/main/inc/lib/glossary.lib.test.php

@ -46,14 +46,14 @@ if (isset($_POST['glossary_id']) &&
$my_glossary_name = api_convert_encoding($my_glossary_name, $charset, 'UTF-8');
$my_glossary_name = trim($my_glossary_name);
$glossary_description = GlossaryManager::get_glossary_term_by_glossary_name(
$glossaryInfo = GlossaryManager::get_glossary_term_by_glossary_name(
$my_glossary_name
);
$glossary_description = str_replace(
$path_image_search,
$path_image,
$glossary_description
$glossaryInfo['description']
);
if (is_null($glossary_description) || strlen(trim($glossary_description)) == 0) {

@ -63,21 +63,21 @@ switch ($action) {
$form->addElement('header', get_lang('TermAddNew'));
$form->addElement(
'text',
'glossary_title',
'name',
get_lang('TermName'),
array('id' => 'glossary_title')
);
$form->addElement(
'html_editor',
'glossary_comment',
'description',
get_lang('TermDefinition'),
null,
array('ToolbarSet' => 'Glossary', 'Height' => '300')
);
$form->addButtonCreate(get_lang('TermAddButton'), 'SubmitGlossary');
// setting the rules
$form->addRule('glossary_title', get_lang('ThisFieldIsRequired'), 'required');
$form->addRule('name', get_lang('ThisFieldIsRequired'), 'required');
// The validation or display
if ($form->validate()) {
$check = Security::check_token('post');
@ -110,41 +110,46 @@ switch ($action) {
// Setting the form elements
$form->addElement('header', get_lang('TermEdit'));
$form->addElement('hidden', 'glossary_id');
$form->addElement('text', 'glossary_title', get_lang('TermName'));
$form->addElement('text', 'name', get_lang('TermName'));
$form->addElement(
'html_editor',
'glossary_comment',
'description',
get_lang('TermDefinition'),
null,
array('ToolbarSet' => 'Glossary', 'Height' => '300')
);
$element = $form->addElement('text', 'insert_date', get_lang('CreationDate'));
$element->freeze();
$element = $form->addElement('text', 'update_date', get_lang('UpdateDate'));
$element->freeze();
$form->addButtonUpdate(get_lang('TermUpdateButton'), 'SubmitGlossary');
// setting the defaults
$glossary_data = GlossaryManager::get_glossary_information($_GET['glossary_id']);
// Date treatment for timezones
if (!empty($glossary_data['insert_date'])) {
$glossary_data['insert_date'] = api_get_local_time($glossary_data['insert_date']);
$glossary_data['insert_date'] = Display::tip(
date_to_str_ago($glossary_data['insert_date']),
api_get_local_time($glossary_data['insert_date'])
);
} else {
$glossary_data['insert_date'] = '';
$glossary_data['insert_date'] = '';
}
if (!empty($glossary_data['update_date'])) {
$glossary_data['update_date'] = api_get_local_time($glossary_data['update_date']);
$glossary_data['update_date'] = Display::tip(
date_to_str_ago($glossary_data['update_date']),
api_get_local_time($glossary_data['update_date'])
);
} else {
$glossary_data['update_date'] = '';
$glossary_data['update_date'] = '';
}
$form->addLabel(get_lang('CreationDate'), $glossary_data['insert_date']);
$form->addLabel(get_lang('UpdateDate'), $glossary_data['update_date']);
$form->addButtonUpdate(get_lang('TermUpdateButton'), 'SubmitGlossary');
$form->setDefaults($glossary_data);
// setting the rules
$form->addRule('glossary_title', get_lang('ThisFieldIsRequired'), 'required');
$form->addRule('name', get_lang('ThisFieldIsRequired'), 'required');
// The validation or display
if ($form->validate()) {
@ -193,7 +198,10 @@ switch ($action) {
);
$form->addElement('header', '', get_lang('ImportGlossary'));
$form->addElement('file', 'file', get_lang('ImportCSVFileLocation'));
$form->addElement('checkbox', 'replace', null, get_lang('DeleteAllGlossaryTerms'));
$form->addElement('checkbox', 'update', null, get_lang('UpdateExistingGlossaryTerms'));
$form->addButtonImport(get_lang('Import'), 'SubmitImport');
$content = $form->returnForm();
@ -201,21 +209,31 @@ switch ($action) {
$content .= '<pre>
<strong>term</strong>;<strong>definition</strong>;
"Hello";"Hola";
"Good";"Bueno";</pre>';
"Goodbye";"Adiós";
</pre>';
if ($form->validate()) {
$termsDeleted = [];
//this is a bad idea //jm
if (isset($_POST['replace']) && $_POST['replace']) {
foreach (GlossaryManager::get_glossary_terms() as $term) {
if (!GlossaryManager::delete_glossary($term['id'])) {
if (!GlossaryManager::delete_glossary($term['id'], false)) {
Display::addFlash(
Display::return_message(get_lang("CannotDeleteGlossary") . ':' . $term['id'], 'error')
);
} else {
$termsDeleted[] = $term['name'];
}
}
}
$updateTerms = isset($_POST['update']) && $_POST['update'] ? true : false;
$data = Import::csv_reader($_FILES['file']['tmp_name']);
$goodList = [];
$updatedList = [];
$addedList = [];
$badList = [];
$doubles = [];
$added = [];
@ -225,20 +243,22 @@ switch ($action) {
$termsToAdd = [];
foreach ($data as $item) {
$items = [
'glossary_title' => $item['term'],
'glossary_comment' => $item['definition']
'name' => $item['term'],
'description' => $item['definition']
];
$termsToAdd[] = $items;
$termsPerKey[$item['term']] = $items;
}
if (empty($termsToAdd)) {
Display::return_message(get_lang("NothingToAdd"), 'warning');
Display::addFlash(
Display::return_message(get_lang('NothingToAdd'), 'warning')
);
header('Location: '.$currentUrl);
exit;
}
$repeatItems = array_count_values(array_column($termsToAdd, 'glossary_title'));
$repeatItems = array_count_values(array_column($termsToAdd, 'name'));
foreach ($repeatItems as $item => $count) {
if ($count > 1) {
$doubles[] = $item;
@ -249,19 +269,48 @@ switch ($action) {
foreach ($uniqueTerms as $itemTerm) {
$item = $termsPerKey[$itemTerm];
$result = GlossaryManager::save_glossary($item, false);
if ($result) {
$goodList[] = $item['glossary_title'];
if ($updateTerms) {
$glossaryInfo = GlossaryManager::get_glossary_term_by_glossary_name($item['name']);
if (!empty($glossaryInfo)) {
$glossaryInfo['description'] = $item['description'];
GlossaryManager::update_glossary($glossaryInfo, false);
$updatedList[] = $item['name'];
} else {
$result = GlossaryManager::save_glossary($item, false);
if ($result) {
$addedList[] = $item['name'];
} else {
$badList[] = $item['name'];
}
}
} else {
$badList[] = $item['glossary_title'];
$result = GlossaryManager::save_glossary($item, false);
if ($result) {
$addedList[] = $item['name'];
} else {
$badList[] = $item['name'];
}
}
}
}
if (count($goodList) > 0) {
if (count($termsDeleted) > 0) {
Display::addFlash(
Display::return_message(get_lang("TermDeleted").': '.implode(', ', $termsDeleted))
);
}
if (count($updatedList) > 0) {
Display::addFlash(
Display::return_message(get_lang("TermsUpdated").': '.implode(', ', $updatedList))
);
}
if (count($addedList) > 0) {
Display::addFlash(
Display::return_message(get_lang("TermsImported").': '.implode(', ', $goodList))
Display::return_message(get_lang("TermsAdded").': '.implode(', ', $addedList))
);
}

@ -7,6 +7,11 @@ use ChamiloSession as Session;
* Class GlossaryManager
* This library provides functions for the glossary tool.
* Include/require it in your code to use its functionality.
*
* @author Julio Montoya
* @author Christian Fasanando
* @author Patrick Cool <patrick.cool@ugent.be>, Ghent University, Belgium januari 2009, dokeos 1.8.6
*
* @package chamilo.library
*/
class GlossaryManager
@ -63,7 +68,7 @@ class GlossaryManager
* @author Isaac Flores <florespaz_isaac@hotmail.com>
* @param string $glossary_name The glossary term name
*
* @return string The glossary description
* @return array The glossary info
*/
public static function get_glossary_term_by_glossary_name($glossary_name)
{
@ -71,33 +76,31 @@ class GlossaryManager
$session_id = api_get_session_id();
$course_id = api_get_course_int_id();
$sql_filter = api_get_session_condition($session_id);
$sql = 'SELECT description FROM '.$glossary_table.'
$sql = 'SELECT * FROM '.$glossary_table.'
WHERE
c_id = '.$course_id.' AND
name LIKE trim("'.Database::escape_string($glossary_name).'")'.$sql_filter;
$rs = Database::query($sql);
if (Database::num_rows($rs) > 0) {
$row = Database::fetch_array($rs);
return $row['description'];
} else {
$row = Database::fetch_array($rs, 'ASSOC');
return '';
return $row;
}
return [];
}
/**
* This functions stores the glossary in the database
*
* @param array Array of title + description (glossary_title => $title, glossary_comment => $comment)
* @param array $values Array of title + description (name => $title, description => $comment)
*
* @return mixed Term id on success, false on failure
* @author Christian Fasanando <christian.fasanando@dokeos.com>
* @author Patrick Cool <patrick.cool@ugent.be>, Ghent University, Belgium
* @version januari 2009, dokeos 1.8.6
*
*/
public static function save_glossary($values, $showMessage = true)
{
if (!is_array($values) || !isset($values['glossary_title'])) {
if (!is_array($values) || !isset($values['name'])) {
return false;
}
@ -111,7 +114,7 @@ class GlossaryManager
$session_id = api_get_session_id();
// check if the glossary term already exists
if (GlossaryManager::glossary_exists($values['glossary_title'])) {
if (GlossaryManager::glossary_exists($values['name'])) {
// display the feedback message
if ($showMessage) {
Display::addFlash(
@ -124,8 +127,8 @@ class GlossaryManager
$params = [
'glossary_id' => 0,
'c_id' => api_get_course_int_id(),
'name' => $values['glossary_title'],
'description' => $values['glossary_comment'],
'name' => $values['name'],
'description' => $values['description'],
'display_order' => $max_glossary_item + 1,
'session_id' => $session_id,
];
@ -160,33 +163,33 @@ class GlossaryManager
*
* @param array $values an array containing all the form elements
* @return boolean True on success, false on failure
* @author Christian Fasanando <christian.fasanando@dokeos.com>
* @author Patrick Cool <patrick.cool@ugent.be>, Ghent University, Belgium
* @version januari 2009, dokeos 1.8.6
*/
public static function update_glossary($values)
public static function update_glossary($values, $showMessage = true)
{
// Database table definition
$t_glossary = Database :: get_course_table(TABLE_GLOSSARY);
$course_id = api_get_course_int_id();
// check if the glossary term already exists
if (GlossaryManager::glossary_exists($values['glossary_title'], $values['glossary_id'])) {
if (GlossaryManager::glossary_exists($values['name'], $values['glossary_id'])) {
// display the feedback message
Display::addFlash(
Display::return_message(get_lang('GlossaryTermAlreadyExistsYouShouldEditIt'), 'error')
);
if ($showMessage) {
Display::addFlash(
Display::return_message(get_lang('GlossaryTermAlreadyExistsYouShouldEditIt'), 'error')
);
}
return false;
} else {
$sql = "UPDATE $t_glossary SET
name = '".Database::escape_string($values['glossary_title'])."',
description = '".Database::escape_string($values['glossary_comment'])."'
name = '".Database::escape_string($values['name'])."',
description = '".Database::escape_string($values['description'])."'
WHERE
c_id = $course_id AND
glossary_id = ".intval($values['glossary_id']);
$result = Database::query($sql);
if ($result === false) {
return false;
}
@ -199,11 +202,12 @@ class GlossaryManager
api_get_user_id()
);
// display the feedback message
Display::addFlash(
Display::return_message(get_lang('TermUpdated'))
);
if ($showMessage) {
// display the feedback message
Display::addFlash(
Display::return_message(get_lang('TermUpdated'))
);
}
}
return true;
@ -212,9 +216,6 @@ class GlossaryManager
/**
* Get the maximum display order of the glossary item
* @return integer Maximum glossary display order
* @author Christian Fasanando <christian.fasanando@dokeos.com>
* @author Patrick Cool <patrick.cool@ugent.be>, Ghent University, Belgium
* @version januari 2009, dokeos 1.8.6
*/
public static function get_max_glossary_item()
{
@ -242,8 +243,6 @@ class GlossaryManager
* @param integer $not_id ID to counter-check if the term exists with this ID as well (optional)
* @return bool True if term exists
*
* @author Patrick Cool <patrick.cool@ugent.be>, Ghent University, Belgium
* @version januari 2009, dokeos 1.8.6
*/
public static function glossary_exists($term, $not_id = '')
{
@ -271,9 +270,8 @@ class GlossaryManager
* Get one specific glossary term data
*
* @param integer $glossary_id ID of the flossary term
* @return mixed Array(glossary_id,glossary_title,glossary_comment,glossary_display_order) or false on error
* @return mixed Array(glossary_id,name,description,glossary_display_order) or false on error
*
* @author Patrick Cool <patrick.cool@ugent.be>, Ghent University, Belgium
*/
public static function get_glossary_information($glossary_id)
{
@ -285,8 +283,8 @@ class GlossaryManager
}
$sql = "SELECT
g.glossary_id as glossary_id,
g.name as glossary_title,
g.description as glossary_comment,
g.name as name,
g.description as description,
g.display_order as glossary_display_order,
ip.insert_date as insert_date,
ip.lastedit_date as update_date,
@ -303,31 +301,37 @@ class GlossaryManager
if ($result === false || Database::num_rows($result) != 1) {
return false;
}
return Database::fetch_array($result);
}
/**
* Delete a glossary term (and re-order all the others)
*
* @param integer The id of the glossary term to delete
* @param integer $glossary_id
* @param bool $showMessage
*
* @return bool True on success, false on failure
* @author Patrick Cool <patrick.cool@ugent.be>, Ghent University, Belgium
* @version januari 2009, dokeos 1.8.6
*/
public static function delete_glossary($glossary_id)
public static function delete_glossary($glossary_id, $showMessage = true)
{
// Database table definition
$t_glossary = Database :: get_course_table(TABLE_GLOSSARY);
$course_id = api_get_course_int_id();
if (empty($glossary_id)) {
$glossaryInfo = self::get_glossary_information($glossary_id);
if (empty($glossaryInfo)) {
return false;
}
$glossary_id = (int) $glossary_id;
$sql = "DELETE FROM $t_glossary
WHERE
c_id = $course_id AND
glossary_id='".intval($glossary_id)."'";
glossary_id='".$glossary_id."'";
$result = Database::query($sql);
if ($result === false || Database::affected_rows($result) < 1) {
return false;
@ -337,7 +341,7 @@ class GlossaryManager
api_item_property_update(
api_get_course_info(),
TOOL_GLOSSARY,
intval($glossary_id),
$glossary_id,
'delete',
api_get_user_id()
);
@ -345,9 +349,11 @@ class GlossaryManager
// reorder the remaining terms
GlossaryManager::reorder_glossary();
Display::addFlash(
Display::return_message(get_lang('TermDeleted'))
);
if ($showMessage) {
Display::addFlash(
Display::return_message(get_lang('TermDeleted').': '.$glossaryInfo['name'])
);
}
return true;
}
@ -357,9 +363,8 @@ class GlossaryManager
* the glossary terms
* @param string View ('table' or 'list'). Optional parameter.
* Defaults to 'table' and prefers glossary_view from the session by default.
*
* @return string
* @author Patrick Cool <patrick.cool@ugent.be>, Ghent University, Belgium
* @version januari 2009, dokeos 1.8.6
*/
public static function display_glossary($view = 'table')
{
@ -372,14 +377,14 @@ class GlossaryManager
// action links
//echo '<div class="actions">';
$actionsLeft = '';
if (api_is_allowed_to_edit(null,true)) {
if (api_is_allowed_to_edit(null, true)) {
$actionsLeft .= '<a href="index.php?'.api_get_cidreq().'&action=addglossary&msg=add?'.api_get_cidreq().'">'.
Display::return_icon('new_glossary_term.png',get_lang('TermAddNew'),'', ICON_SIZE_MEDIUM).'</a>';
}
$actionsLeft .= '<a href="index.php?'.api_get_cidreq().'&action=export">'.
Display::return_icon('export_csv.png',get_lang('ExportGlossaryAsCSV'),'',ICON_SIZE_MEDIUM).'</a>';
if (api_is_allowed_to_edit(null,true)) {
if (api_is_allowed_to_edit(null, true)) {
$actionsLeft .= '<a href="index.php?'.api_get_cidreq().'&action=import">'.
Display::return_icon('import_csv.png',get_lang('ImportGlossary'),'',ICON_SIZE_MEDIUM).'</a>';
}
@ -417,7 +422,7 @@ class GlossaryManager
$content = $toolbar;
if (!$view || $view == 'table') {
if (!$view || $view === 'table') {
$table = new SortableTable(
'glossary',
array('GlossaryManager', 'get_number_glossary_terms'),
@ -434,7 +439,7 @@ class GlossaryManager
$content .= $table->return_table();
}
if ($view == 'list') {
if ($view === 'list') {
$content .= GlossaryManager::displayGlossaryList();
}
@ -443,9 +448,7 @@ class GlossaryManager
/**
* Display the glossary terms in a list
* @return bool True
* @author Patrick Cool <patrick.cool@ugent.be>, Ghent University, Belgium
* @version januari 2009, dokeos 1.8.6
* @return bool true
*/
public static function displayGlossaryList()
{
@ -466,8 +469,6 @@ class GlossaryManager
* @param int Session ID filter (optional)
* @return integer Count of glossary terms
*
* @author Patrick Cool <patrick.cool@ugent.be>, Ghent University, Belgium
* @version januari 2009, dokeos 1.8.6
*/
public static function get_number_glossary_terms($session_id=0)
{
@ -499,17 +500,14 @@ class GlossaryManager
/**
* Get all the data of a glossary
*
* @param integer From which item
* @param integer Number of items to collect
* @param string Name of column on which to order
* @param string Whether to sort in ascending (ASC) or descending (DESC)
* @return unknown
* @param int $from From which item
* @param int $number_of_items Number of items to collect
* @param string $column Name of column on which to order
* @param string $direction Whether to sort in ascending (ASC) or descending (DESC)
*
* @author Patrick Cool <patrick.cool@ugent.be>
* @author Julio Montoya fixing this function, adding intvals
* @version januari 2009, dokeos 1.8.6
* @return array
*/
public static function get_glossary_data($from, $number_of_items, $column, $direction)
public static function get_glossary_data($from, $number_of_items, $column, $direction)
{
$_user = api_get_user_info();
$view = Session::read('glossary_view');
@ -521,7 +519,7 @@ class GlossaryManager
if (api_is_allowed_to_edit(null, true)) {
$col2 = " glossary.glossary_id as col2, ";
} else {
$col2 = " ";
$col2 = ' ';
}
//condition for the session
@ -568,7 +566,7 @@ class GlossaryManager
$session_img = api_get_session_image($data['session_id'], $_user['status']);
$array[0] = $data[0] . $session_img;
if (!$view || $view == 'table') {
if (!$view || $view === 'table') {
$array[1] = str_replace(array('<p>', '</p>'), array('', '<br />'), $data[1]);
} else {
$array[1] = $data[1];
@ -587,12 +585,10 @@ class GlossaryManager
* Update action icons column
*
* @param integer $glossary_id
* @param array Parameters to use to affect links
* @param array The line of results from a query on the glossary table
* @return string HTML string for the action icons columns
* @param array $url_params Parameters to use to affect links
* @param array $row The line of results from a query on the glossary table
*
* @author Patrick Cool <patrick.cool@ugent.be>, Ghent University, Belgium
* @version januari 2009, dokeos 1.8.6
* @return string HTML string for the action icons columns
*/
public static function actions_filter($glossary_id, $url_params, $row)
{
@ -600,9 +596,7 @@ class GlossaryManager
$return = '<a href="'.api_get_self().'?action=edit_glossary&amp;glossary_id='.$glossary_id.'&'.api_get_cidreq().'&msg=edit">'.
Display::return_icon('edit.png',get_lang('Edit'),'',22).'</a>';
$glossary_data = GlossaryManager::get_glossary_information($glossary_id);
$glossary_term = $glossary_data['glossary_title'];
$glossary_term = $glossary_data['name'];
if (api_is_allowed_to_edit(null, true)) {
if ($glossary_data['session_id'] == api_get_session_id()) {
$return .= '<a href="'.api_get_self().'?action=delete_glossary&amp;glossary_id='.$glossary_id.'&'.api_get_cidreq().'" onclick="return confirmation(\''.$glossary_term.'\');">'.
@ -620,26 +614,22 @@ class GlossaryManager
*
* @return string HTML string including JavaScript
*
* @author Patrick Cool <patrick.cool@ugent.be>, Ghent University, Belgium
* @version januari 2009, dokeos 1.8.6
*/
public static function javascript_glossary()
{
return "<script>
function confirmation (name) {
if (confirm(\" ".get_lang("TermConfirmDelete")." \"+ name + \" ?\"))
{return true;}
else
{return false;}
}
function confirmation (name) {
if (confirm(\" ".get_lang("TermConfirmDelete")." \"+ name + \" ?\")) {
return true;
} else {
return false;
}
}
</script>";
}
/**
* Re-order glossary
*
* @author Patrick Cool <patrick.cool@ugent.be>, Ghent University, Belgium
* @version januari 2009, dokeos 1.8.6
*/
public static function reorder_glossary()
{
@ -665,9 +655,6 @@ class GlossaryManager
*
* @param string $direction
* @param string $glossary_id
*
* @author Patrick Cool <patrick.cool@ugent.be>, Ghent University, Belgium
* @version januari 2009, dokeos 1.8.6
*/
public static function move_glossary($direction, $glossary_id)
{
@ -675,7 +662,7 @@ class GlossaryManager
$t_glossary = Database :: get_course_table(TABLE_GLOSSARY);
// sort direction
if ($direction == 'up') {
if ($direction === 'up') {
$sortorder = 'DESC';
} else {
$sortorder = 'ASC';
@ -730,6 +717,6 @@ class GlossaryManager
$html .= '</body></html>';
$courseCode = api_get_course_id();
$pdf = new PDF();
$pdf->content_to_pdf($html, '', get_lang('Glossary').'_'.$courseCode, $course_code);
$pdf->content_to_pdf($html, '', get_lang('Glossary').'_'.$courseCode, $courseCode);
}
}

@ -644,15 +644,19 @@ function api_format_date($time, $format = null, $language = null)
* Example: $date = '2008-03-07 15:44:08';
* date_to_str($date) it will return 3 days, 20 hours
* The given date should be in the timezone chosen by the user or administrator. Use api_get_local_time() to get it...
* You can use it like this:
* Display::tip(date_to_str_ago($dateInUtc), api_get_local_time($dateInUtc));
*
* @param string $date The string has to be the result of a date function in this format -> date('Y-m-d H:i:s', time());
* @return string $timeZone
*
* @param string The string has to be the result of a date function in this format -> date('Y-m-d H:i:s', time());
* @return string The difference between the current date and the parameter in a literal way "3 days, 2 hour" *
* @author Julio Montoya
*/
function date_to_str_ago($date, $timeZone = 'UTC')
{
if ($date == '0000-00-00 00:00:00') {
if ($date === '0000-00-00 00:00:00') {
return '';
}
@ -1965,15 +1969,15 @@ function _api_convert_encoding_supports($encoding) {
function apiGetHumanDateTime($date, $showTime = true, $humanForm = false) {
if ($showTime) {
if ($humanForm) {
return $date->format('j M Y H:i:s');
return $date->format('j M Y H:i:s');
} else {
return $date->format('Y-m-d H:i:s');
return $date->format('Y-m-d H:i:s');
}
} else {
if ($humanForm) {
return $date->format('j M Y');
return $date->format('j M Y');
} else {
return $date->format('Y-m-d');
return $date->format('Y-m-d');
}
}
}

@ -52,7 +52,7 @@ class TestGlossary extends UnitTestCase {
function testGetGlossaryTermByGlossaryName() {
$glossary_name = '';
$res = GlossaryManager::get_glossary_term_by_glossary_name($glossary_name);
$this->assertTrue(is_string($res));
$this->assertTrue(is_array($res));
}
function testUpdateGlossary() {

Loading…
Cancel
Save