/**
  * @return bool
  */
 public function valid()
 {
     $this->data = $this->db->fetchAssoc($this->res);
     if (is_array($this->data) && (strpos($this->data['login'], ',') !== false || strpos($this->data['login'], ';') !== false)) {
         $parts = array_filter(array_map('trim', preg_split("/[ ]*[;,][ ]*/", trim($this->data['login']))));
         foreach ($parts as $part) {
             if (ilStr::strPos(ilStr::strToLower($part), ilStr::strToLower($this->term)) !== false) {
                 $this->users_stack[] = $part;
             }
         }
         if ($this->users_stack) {
             $this->data = null;
         }
     }
     return is_array($this->data) || count($this->users_stack) > 0;
 }
コード例 #2
0
 /**
  * Add a line to the ical string 
  * @return 
  * @param object $a_line
  */
 public function addLine($a_line)
 {
     //$chunks = str_split($a_line, self::LINE_SIZE);
     include_once './Services/Utilities/classes/class.ilStr.php';
     // use multibyte split
     $chunks = array();
     $len = ilStr::strLen($a_line);
     while ($len) {
         $chunks[] = ilStr::subStr($a_line, 0, self::LINE_SIZE);
         $a_line = ilStr::subStr($a_line, self::LINE_SIZE, $len);
         $len = ilStr::strLen($a_line);
     }
     for ($i = 0; $i < count($chunks); $i++) {
         $this->ical .= $chunks[$i];
         if (isset($chunks[$i + 1])) {
             $this->ical .= self::LINEBREAK;
             $this->ical .= self::BEGIN_LINE_WHITESPACE;
         }
     }
     $this->ical .= self::LINEBREAK;
 }
コード例 #3
0
 /**
  * Insert page toc
  *
  * @param string output
  * @return string output
  */
 function insertPageToc($a_output)
 {
     global $lng;
     include_once "./Services/Utilities/classes/class.ilStr.php";
     // extract all headings
     $offsets = ilStr::strPosAll($a_output, "ilPageTocH");
     $page_heads = array();
     foreach ($offsets as $os) {
         $level = (int) substr($a_output, $os + 10, 1);
         if (in_array($level, array(1, 2, 3))) {
             $anchor = str_replace("TocH", "TocA", substr($a_output, $os, strpos($a_output, "<", $os) - $os - 3));
             // get heading
             $tag_start = stripos($a_output, "<h" . $level . " ", $os);
             $tag_end = stripos($a_output, "</h" . $level . ">", $tag_start);
             $head = substr($a_output, $tag_start, $tag_end - $tag_start);
             // get headings text
             $text_start = stripos($head, ">") + 1;
             $text_end = strripos($head, "<!--", $text_start);
             $text = substr($head, $text_start, $text_end - $text_start);
             $page_heads[] = array("level" => $level, "text" => $text, "anchor" => $anchor);
         }
     }
     if (count($page_heads) > 1) {
         include_once "./Services/UIComponent/NestedList/classes/class.ilNestedList.php";
         $list = new ilNestedList();
         $list->setAutoNumbering(true);
         $list->setListClass("ilc_page_toc_PageTOCList");
         $list->setItemClass("ilc_page_toc_PageTOCItem");
         $i = 0;
         $c_depth = 1;
         $c_par[1] = 0;
         $c_par[2] = 0;
         $nr[1] = 1;
         $nr[2] = 1;
         $nr[3] = 1;
         foreach ($page_heads as $ind => $h) {
             $i++;
             $par = 0;
             // check if we have a parent for one level up
             $par = 0;
             if ($h["level"] == 2 && $c_par[1] > 0) {
                 $par = $c_par[1];
             }
             if ($h["level"] == 3 && $c_par[2] > 0) {
                 $par = $c_par[2];
             }
             $h["text"] = str_replace("<!--PageTocPH-->", "", $h["text"]);
             // add the list node
             $list->addListNode("<a href='#" . $h["anchor"] . "' class='ilc_page_toc_PageTOCLink'>" . $h["text"] . "</a>", $i, $par);
             // set the node as current parent of the level
             if ($h["level"] == 1) {
                 $c_par[1] = $i;
                 $c_par[2] = 0;
             }
             if ($h["level"] == 2) {
                 $c_par[2] = $i;
             }
         }
         $tpl = new ilTemplate("tpl.page_toc.html", true, true, "Services/COPage");
         $tpl->setVariable("PAGE_TOC", $list->getHTML());
         $tpl->setVariable("TXT_PAGE_TOC", $lng->txt("cont_page_toc"));
         $tpl->setVariable("TXT_HIDE", $lng->txt("hide"));
         $tpl->setVariable("TXT_SHOW", $lng->txt("show"));
         $a_output = str_replace("{{{{{PageTOC}}}}}", $tpl->get(), $a_output);
         $numbers = $list->getNumbers();
         if (count($numbers) > 0) {
             include_once "./Services/Utilities/classes/class.ilStr.php";
             foreach ($numbers as $n) {
                 $a_output = ilStr::replaceFirsOccurence("<!--PageTocPH-->", $n . " ", $a_output);
             }
         }
     } else {
         $a_output = str_replace("{{{{{PageTOC}}}}}", "", $a_output);
     }
     return $a_output;
 }
コード例 #4
0
 /**
  * 
  * Called by class ilMailFormGUI
  * 
  * @param	string		search string surrounded with wildcards
  * @param	string		native search string
  * @return	stdClass	search result as an object of type stdClass
  * @access	public
  * 
  */
 public function getRecipientAsync($a_search, $a_native_search)
 {
     global $ilDB;
     $query = "SELECT DISTINCT\n\t\t\t\tabook.login login,\n\t\t\t\tabook.firstname firstname,\n\t\t\t\tabook.lastname lastname,\n\t\t\t\t'addressbook' type\n\t\t\tFROM addressbook abook\n\t\t\tWHERE abook.user_id = " . $ilDB->quote($this->user_id, 'integer') . "\n\t\t\tAND abook.login IS NOT NULL\n\t\t\tAND (" . $ilDB->like('abook.login', 'text', $a_search) . "\n\t\t\t\t\tOR " . $ilDB->like('abook.firstname', 'text', $a_search) . "\n\t\t\t\t\tOR " . $ilDB->like('abook.lastname', 'text', $a_search) . "\n\t\t\t)";
     $union_query_1 = "SELECT DISTINCT\n\t\t\t\tabook.email login,\n\t\t\t\tabook.firstname firstname,\n\t\t\t\tabook.lastname lastname,\n\t\t\t\t'addressbook' type\n\t\t\tFROM addressbook abook\n\t\t\tWHERE abook.user_id = " . $ilDB->quote($this->user_id, 'integer') . "\n\t\t\tAND abook.login IS NULL\n\t\t\tAND (" . $ilDB->like('abook.email', 'text', $a_search) . "\n\t\t\t\t\tOR " . $ilDB->like('abook.firstname', 'text', $a_search) . "\n\t\t\t\t\tOR " . $ilDB->like('abook.lastname', 'text', $a_search) . "\n\t\t\t)";
     $union_query_2 = "SELECT DISTINCT\n\t\t\t\tmail.rcp_to login,\n\t\t\t\t'' firstname,\n\t\t\t\t'' lastname,\n\t\t\t\t'mail' type\n\t\t\tFROM mail\n\t\t\tWHERE " . $ilDB->like('mail.rcp_to', 'text', $a_search) . "\n\t\t\tAND sender_id = " . $ilDB->quote($this->user_id, 'integer') . "\n\t\t\tAND mail.sender_id = mail.user_id";
     $queries = array('addressbook_1' => $query, 'mail' => $union_query_2);
     if ($this->allow_smtp == 1) {
         $queries['addressbook_2'] = $union_query_1;
     }
     include_once 'Services/Utilities/classes/class.ilStr.php';
     try {
         // MySql: Join the array values for mysql to one select statement
         if ($ilDB->getDbType() != 'oracle') {
             $queries['all'] = implode(' UNION ', $queries);
         }
         foreach ($queries as $type => $query) {
             // Oracle: Distincts do no work with clobs
             if ('mail' == $type && $ilDB->getDbType() == 'oracle') {
                 $query = str_replace('DISTINCT', '', $query);
             }
             $ilDB->setLimit(0, 20);
             $query_res = $ilDB->query($query);
             while ($row = $ilDB->fetchObject($query_res)) {
                 if ($row->type == 'mail') {
                     if (strpos($row->login, ',') || strpos($row->login, ';')) {
                         $parts = preg_split("/[ ]*[;,][ ]*/", trim($row->login));
                         foreach ($parts as $part) {
                             if (ilStr::strPos(ilStr::strToLower($part), ilStr::strToLower($a_native_search)) !== false) {
                                 $this->addResult($part, '', '', 'mail');
                             }
                         }
                     } else {
                         $this->addResult($row->login, '', '', 'mail');
                     }
                 } else {
                     $this->addResult($row->login, $row->firstname, $row->lastname, 'addressbook');
                 }
             }
         }
     } catch (ilException $e) {
     }
     return $this->result;
 }
コード例 #5
0
 /**
  * Retrieves the full path to a question pool with a given reference id
  *
  * @return string The full path to the question pool including the locator
  * @access public
  */
 function _getFullPathToQpl($ref_id)
 {
     global $tree;
     $path = $tree->getPathFull($ref_id);
     $items = array();
     $counter = 0;
     foreach ($path as $item) {
         if ($counter > 0 && $counter < count($path) - 1) {
             array_push($items, $item["title"]);
         }
         $counter++;
     }
     $fullpath = join(" > ", $items);
     include_once "./Services/Utilities/classes/class.ilStr.php";
     if (strlen($fullpath) > 60) {
         $fullpath = ilStr::subStr($fullpath, 0, 30) . "..." . ilStr::subStr($fullpath, ilStr::strLen($fullpath) - 30, 30);
     }
     return $fullpath;
 }
コード例 #6
0
 /**
  * Converts a path consisting of object titles into a path consisting of tree
  * nodes. The comparison is non-case sensitive.
  *
  * Note: this function returns the same result as getNodePath, 
  * but takes a title path as parameter.
  *
  * @access	public
  * @param	Array	Path array with object titles.
  *                       e.g. array('ILIAS','English','Course A')
  * @param	ref_id	Startnode of the relative path. 
  *                       Specify null, if the title path is an absolute path.
  *                       Specify a ref id, if the title path is a relative 
  *                       path starting at this ref id.
  * @return	array	ordered path info (depth,parent,child,obj_id,type,title)
  *               or null, if the title path can not be converted into a node path.
  */
 function getNodePathForTitlePath($titlePath, $a_startnode_id = null)
 {
     global $ilDB, $log;
     //$log->write('getNodePathForTitlePath('.implode('/',$titlePath));
     // handle empty title path
     if ($titlePath == null || count($titlePath) == 0) {
         if ($a_startnode_id == 0) {
             return null;
         } else {
             return $this->getNodePath($a_startnode_id);
         }
     }
     // fetch the node path up to the startnode
     if ($a_startnode_id != null && $a_startnode_id != 0) {
         // Start using the node path to the root of the relative path
         $nodePath = $this->getNodePath($a_startnode_id);
         $parent = $a_startnode_id;
     } else {
         // Start using the root of the tree
         $nodePath = array();
         $parent = 0;
     }
     // Convert title path into Unicode Normal Form C
     // This is needed to ensure that we can compare title path strings with
     // strings from the database.
     require_once 'include/Unicode/UtfNormal.php';
     include_once './Services/Utilities/classes/class.ilStr.php';
     $inClause = 'd.title IN (';
     for ($i = 0; $i < count($titlePath); $i++) {
         $titlePath[$i] = ilStr::strToLower(UtfNormal::toNFC($titlePath[$i]));
         if ($i > 0) {
             $inClause .= ',';
         }
         $inClause .= $ilDB->quote($titlePath[$i], 'text');
     }
     $inClause .= ')';
     // Fetch all rows that are potential path elements
     if ($this->table_obj_reference) {
         $joinClause = 'JOIN ' . $this->table_obj_reference . '  r ON t.child = r.' . $this->ref_pk . ' ' . 'JOIN ' . $this->table_obj_data . ' d ON r.' . $this->obj_pk . ' = d.' . $this->obj_pk;
     } else {
         $joinClause = 'JOIN ' . $this->table_obj_data . '  d ON t.child = d.' . $this->obj_pk;
     }
     // The ORDER BY clause in the following SQL statement ensures that,
     // in case of a multiple objects with the same title, always the Object
     // with the oldest ref_id is chosen.
     // This ensure, that, if a new object with the same title is added,
     // WebDAV clients can still work with the older object.
     $q = 'SELECT t.depth, t.parent, t.child, d.' . $this->obj_pk . ' obj_id, d.type, d.title ' . 'FROM ' . $this->table_tree . '  t ' . $joinClause . ' ' . 'WHERE ' . $inClause . ' ' . 'AND t.depth <= ' . (count($titlePath) + count($nodePath)) . ' ' . 'AND t.tree = 1 ' . 'ORDER BY t.depth, t.child ASC';
     $r = $ilDB->query($q);
     $rows = array();
     while ($row = $r->fetchRow(DB_FETCHMODE_ASSOC)) {
         $row['title'] = UtfNormal::toNFC($row['title']);
         $row['ref_id'] = $row['child'];
         $rows[] = $row;
     }
     // Extract the path elements from the fetched rows
     for ($i = 0; $i < count($titlePath); $i++) {
         $pathElementFound = false;
         foreach ($rows as $row) {
             if ($row['parent'] == $parent && ilStr::strToLower($row['title']) == $titlePath[$i]) {
                 // FIXME - We should test here, if the user has
                 // 'visible' permission for the object.
                 $nodePath[] = $row;
                 $parent = $row['child'];
                 $pathElementFound = true;
                 break;
             }
         }
         // Abort if we haven't found a path element for the current depth
         if (!$pathElementFound) {
             //$log->write('ilTree.getNodePathForTitlePath('.var_export($titlePath,true).','.$a_startnode_id.'):null');
             return null;
         }
     }
     // Return the node path
     //$log->write('ilTree.getNodePathForTitlePath('.var_export($titlePath,true).','.$a_startnode_id.'):'.var_export($nodePath,true));
     return $nodePath;
 }
コード例 #7
0
 /**
  * Shorten text depending on target encoding
  * @param string $table
  * @param string $field
  * @param string $a_value
  * @param int $a_size
  * @return string
  */
 protected function shortenText($table, $field, $a_value, $a_size)
 {
     global $ilLog;
     if ($this->getTargetEncoding() == 'UTF-8') {
         return $a_value;
     }
     // Convert to target encoding
     $shortened = mb_convert_encoding($a_value, $this->getTargetEncoding(), 'UTF-8');
     // Shorten
     include_once './Services/Utilities/classes/class.ilStr.php';
     $shortened = ilStr::shortenText($shortened, 0, $a_size, $this->getTargetEncoding());
     // Convert back to UTF-8
     $shortened = mb_convert_encoding($shortened, 'UTF-8', $this->getTargetEncoding());
     if (strlen($a_value) != strlen($shortened)) {
         $ilLog->write('Table        : ' . $table);
         $ilLog->write('Field        : ' . $field);
         $ilLog->write('Type         : ' . $this->fields[$field]['type']);
         $ilLog->write('Length       : ' . $this->fields[$field]['length']);
         $ilLog->write('Before       : ' . $a_value);
         $ilLog->write('Shortened    : ' . $shortened);
         $ilLog->write('Strlen Before: ' . strlen($a_value));
         $ilLog->write('Strlen After : ' . strlen($shortened));
     }
     return $shortened;
 }
コード例 #8
0
 /**
  * Validate the logical structure of a lang file.
  * This function checks if a lang file exists, the file has a 
  * header, and each lang-entry consists of exactly three elements
  * (module, identifier, value).
  *
  * @return	string	system message
  * @param   string  $scope  empty (global) or "local"
  */
 function check($scope = '')
 {
     include_once "./Services/Utilities/classes/class.ilStr.php";
     if (!empty($scope)) {
         if ($scope == 'global') {
             $scope = '';
         } else {
             $scopeExtension = '.' . $scope;
         }
     }
     $path = $this->lang_path;
     if ($scope == "local") {
         $path = $this->cust_lang_path;
     }
     $tmpPath = getcwd();
     // dir check
     if (!is_dir($path)) {
         $this->ilias->raiseError("Directory not found: " . $path, $this->ilias->error_obj->MESSAGE);
     }
     chdir($path);
     // compute lang-file name format
     $lang_file = "ilias_" . $this->key . ".lang" . $scopeExtension;
     // file check
     if (!is_file($lang_file)) {
         $this->ilias->raiseError("File not found: " . $lang_file, $this->ilias->error_obj->MESSAGE);
     }
     // header check
     if (!($content = $this->cut_header(file($lang_file)))) {
         $this->ilias->raiseError("Wrong Header in " . $lang_file, $this->ilias->error_obj->MESSAGE);
     }
     // check (counting) elements of each lang-entry
     $line = 0;
     foreach ($content as $key => $val) {
         $separated = explode($this->separator, trim($val));
         $num = count($separated);
         ++$n;
         if ($num != 3) {
             $line = $n + 36;
             $this->ilias->raiseError("Wrong parameter count in " . $lang_file . " in line {$line} (Value: {$val})! Please check your language file!", $this->ilias->error_obj->MESSAGE);
         }
         if (!ilStr::isUtf8($separated[2])) {
             $this->ilias->raiseError("Non UTF8 character found in " . $lang_file . " in line {$line} (Value: {$val})! Please check your language file!", $this->ilias->error_obj->MESSAGE);
         }
     }
     chdir($tmpPath);
     // no error occured
     return true;
 }
コード例 #9
0
 /**
  * @return mixed|string
  */
 public function getSolutionSubmit()
 {
     $text = ilUtil::stripSlashes($_POST["TEXT"], FALSE);
     if ($this->getMaxNumOfChars()) {
         include_once "./Services/Utilities/classes/class.ilStr.php";
         $text_without_tags = preg_replace("/<[^>*?]>/is", "", $text);
         $len_with_tags = ilStr::strLen($text);
         $len_without_tags = ilStr::strLen($text_without_tags);
         if ($this->getMaxNumOfChars() < $len_without_tags) {
             if (!$this->isHTML($text)) {
                 $text = ilStr::subStr($text, 0, $this->getMaxNumOfChars());
             }
         }
     }
     if ($this->isHTML($text)) {
         $text = preg_replace("/<[^>]*\$/ims", "", $text);
         return $text;
     } else {
         //$text = htmlentities($text, ENT_QUOTES, "UTF-8");
     }
     return $text;
 }
コード例 #10
0
ファイル: class.ilUtil.php プロジェクト: bheyser/qplskl
 /**
  * sub-function to sort an array
  *
  * @param	array	$a
  * @param	array	$b
  *
  * @return	boolean	true on success / false on error
  * @static
  * 
  */
 public static function sort_func($a, $b)
 {
     global $array_sortby, $array_sortorder;
     if (!isset($array_sortby)) {
         // occured in: setup -> new client -> install languages -> sorting of languages
         $array_sortby = 0;
     }
     // this comparison should give optimal results if
     // locale is provided and mb string functions are supported
     if ($array_sortorder == "asc") {
         return ilStr::strCmp($a[$array_sortby], $b[$array_sortby]);
     }
     if ($array_sortorder == "desc") {
         return !ilStr::strCmp($a[$array_sortby], $b[$array_sortby]);
         return strcoll(ilStr::strToUpper($b[$array_sortby]), ilStr::strToUpper($a[$array_sortby]));
     }
 }
コード例 #11
0
 /**
  * Splits the answer string either by space(s) or the separator (eg. ::) and
  * trims the resulting array elements.
  * 
  * @param string $in_string OrderElements 
  * @param string $separator to be used for splitting.
  * 
  * @return array 
  */
 private function splitAndTrimOrderElementText($in_string, $separator)
 {
     $result = array();
     include_once "./Services/Utilities/classes/class.ilStr.php";
     if (ilStr::strPos($in_string, $separator) === false) {
         $result = preg_split("/\\s+/", $in_string);
     } else {
         $result = split($separator, $in_string);
     }
     foreach ($result as $key => $value) {
         $result[$key] = trim($value);
     }
     return $result;
 }
コード例 #12
0
 /**
  * Creates a the cumulated results data for the question
  *
  * @return array Data
  */
 public function getCumulatedResultData($survey_id, $counter, $finished_ids)
 {
     $cumulated =& $this->calculateCumulatedResults($survey_id, $finished_ids);
     $questiontext = preg_replace("/\\<[^>]+?>/ims", "", $this->getQuestiontext());
     include_once "./Services/Utilities/classes/class.ilStr.php";
     $maxlen = 75;
     if (strlen($questiontext) > $maxlen + 3) {
         $questiontext = ilStr::substr($questiontext, 0, $maxlen) . "...";
     }
     $result = array();
     $row = array('counter' => $counter, 'title' => $counter . '. ' . $this->getTitle(), 'question' => $questiontext, 'users_answered' => $cumulated['TOTAL']['USERS_ANSWERED'], 'users_skipped' => $cumulated['TOTAL']['USERS_SKIPPED'], 'question_type' => $this->lng->txt($cumulated['TOTAL']['QUESTION_TYPE']), 'mode' => $cumulated['TOTAL']['MODE'], 'mode_nr_of_selections' => $cumulated['TOTAL']['MODE_NR_OF_SELECTIONS'], 'median' => $cumulated['TOTAL']['MEDIAN'], 'arithmetic_mean' => $cumulated['TOTAL']['ARITHMETIC_MEAN']);
     array_push($result, $row);
     $maxlen -= 3;
     foreach ($cumulated as $key => $value) {
         if (is_numeric($key)) {
             if (strlen($value['ROW']) > $maxlen + 3) {
                 $value['ROW'] = ilStr::substr($value['ROW'], 0, $maxlen) . "...";
             }
             $row = array('title' => '', 'question' => $key + 1 . ". " . $value['ROW'], 'users_answered' => $value['USERS_ANSWERED'], 'users_skipped' => $value['USERS_SKIPPED'], 'question_type' => '', 'mode' => $value["MODE"], 'mode_nr_of_selections' => $value["MODE_NR_OF_SELECTIONS"], 'median' => $value["MEDIAN"], 'arithmetic_mean' => $value["ARITHMETIC_MEAN"]);
             array_push($result, $row);
         }
     }
     return $result;
 }
コード例 #13
0
 public function createErrorTextExport($selections = null)
 {
     $counter = 0;
     $errorcounter = 0;
     include_once "./Services/Utilities/classes/class.ilStr.php";
     if (!is_array($selections)) {
         $selections = array();
     }
     $textarray = preg_split("/[\n\r]+/", $this->getErrorText());
     foreach ($textarray as $textidx => $text) {
         $items = preg_split("/\\s+/", $text);
         foreach ($items as $idx => $item) {
             if (strpos($item, '#') === 0) {
                 $item = ilStr::substr($item, 1, ilStr::strlen($item));
                 if ($correct_solution) {
                     $errorobject = $this->errordata[$errorcounter];
                     if (is_object($errorobject)) {
                         $item = $errorobject->text_correct;
                     }
                     $errorcounter++;
                 }
             }
             $word = "";
             if (in_array($counter, $selections)) {
                 $word .= '#';
             }
             $word .= ilUtil::prepareFormOutput($item);
             if (in_array($counter, $selections)) {
                 $word .= '#';
             }
             $items[$idx] = $word;
             $counter++;
         }
         $textarray[$textidx] = join($items, " ");
     }
     return join($textarray, "\n");
 }
コード例 #14
0
 /**
  * Link terms in a dom page object in bb style
  *
  * @param
  * @return
  */
 protected static function linkTermsInDom($a_dom, $a_terms, $a_par_node = null)
 {
     // sort terms by their length (shortes first)
     // to prevent that nested tags are builded
     foreach ($a_terms as $k => $t) {
         $a_terms[$k]["termlength"] = strlen($t["term"]);
     }
     $a_terms = ilUtil::sortArray($a_terms, "termlength", "asc", true);
     if ($a_dom instanceof php4DOMDocument) {
         $a_dom = $a_dom->myDOMDocument;
     }
     if ($a_par_node instanceof php4DOMElement) {
         $a_par_node = $a_par_node->myDOMNode;
     }
     $xpath = new DOMXPath($a_dom);
     if ($a_par_node == null) {
         $parnodes = $xpath->query('//Paragraph');
     } else {
         $parnodes = $xpath->query('//Paragraph', $a_par_node);
     }
     include_once "./Services/Utilities/classes/class.ilStr.php";
     foreach ($parnodes as $parnode) {
         $textnodes = $xpath->query('//text()', $parnode);
         foreach ($textnodes as $node) {
             $p = $node->getNodePath();
             // we do not change text nodes inside of links
             if (!is_int(strpos($p, "/IntLink")) && !is_int(strpos($p, "/ExtLink"))) {
                 $node_val = $node->nodeValue;
                 // all terms
                 foreach ($a_terms as $t) {
                     $pos = ilStr::strIPos($node_val, $t["term"]);
                     // if term found
                     while (is_int($pos)) {
                         // check if the string is not included in another word
                         // note that []
                         $valid_limiters = array("", " ", "&nbsp;", ".", ",", ":", ";", "!", "?", "\"", "'", "(", ")");
                         $b = $pos > 0 ? ilStr::subStr($node_val, $pos - 1, 1) : "";
                         $a = ilStr::subStr($node_val, $pos + ilStr::strLen($t["term"]), 1);
                         if ((in_array($b, $valid_limiters) || htmlentities($b, null, 'utf-8') == "&nbsp;") && in_array($a, $valid_limiters)) {
                             $mid = '[iln term="' . $t["id"] . '"]' . ilStr::subStr($node_val, $pos, ilStr::strLen($t["term"])) . "[/iln]";
                             $node_val = ilStr::subStr($node_val, 0, $pos) . $mid . ilStr::subStr($node_val, $pos + ilStr::strLen($t["term"]));
                             $pos += ilStr::strLen($mid);
                         } else {
                             $pos += ilStr::strLen($t["term"]);
                         }
                         $pos = ilStr::strIPos($node_val, $t["term"], $pos);
                     }
                     // insert [iln] tags
                 }
                 $node->nodeValue = $node_val;
             }
             //			var_dump($p);
             //			var_dump($node->nodeValue);
         }
         // dump paragraph node
         $text = $a_dom->saveXML($parnode);
         $text = substr($text, 0, strlen($text) - strlen("</Paragraph>"));
         $text = substr($text, strpos($text, ">") + 1);
         // replace [iln] by tags with xml representation
         $text = self::intLinks2xml($text);
         // "set text"
         $temp_dom = domxml_open_mem('<?xml version="1.0" encoding="UTF-8"?><Paragraph>' . $text . '</Paragraph>', DOMXML_LOAD_PARSING, $error);
         $temp_dom = $temp_dom->myDOMDocument;
         if (empty($error)) {
             // delete children of paragraph node
             $children = $parnode->childNodes;
             while ($parnode->hasChildNodes()) {
                 $parnode->removeChild($parnode->firstChild);
             }
             // copy new content children in paragraph node
             $xpath_temp = new DOMXPath($temp_dom);
             $temp_pars = $xpath_temp->query("//Paragraph");
             foreach ($temp_pars as $new_par_node) {
                 $new_childs = $new_par_node->childNodes;
                 foreach ($new_childs as $new_child) {
                     //$cloned_child = $new_child->cloneNode(true);
                     $cloned_child = $a_dom->importNode($new_child, true);
                     $parnode->appendChild($cloned_child);
                 }
             }
         }
     }
 }
コード例 #15
0
 /**
  * Compare two strings
  */
 function strCmp($a, $b)
 {
     global $ilCollator;
     if (is_object($ilCollator)) {
         return $ilCollator->compare(ilStr::strToUpper($a), ilStr::strToUpper($b)) > 0;
     } else {
         return strcoll(ilStr::strToUpper($a), ilStr::strToUpper($b)) > 0;
     }
 }
コード例 #16
0
 /**
  * Prepare message for container view
  * @static
  * @param string $text
  * @return string
  */
 public static function prepareMessageForLists($text)
 {
     include_once 'Services/Utilities/classes/class.ilStr.php';
     $text = strip_tags($text);
     $text = preg_replace('/\\[(\\/)?quote\\]/', '', $text);
     if (ilStr::strLen($text) > 40) {
         $text = ilStr::subStr($text, 0, 37) . '...';
     }
     return $text;
 }
コード例 #17
0
 /**
  * Reads out the source file and writes all entries to the database
  *
  * @return void
  */
 public function writeSourcefileEntriesToDb()
 {
     //Read File
     $entries_from_file = array();
     switch ($this->getFiletype()) {
         case "ris":
             $entries_from_file = self::__readRisFile($this->getFileAbsolutePath());
             break;
         case "bib":
             $entries_from_file = self::__readBibFile($this->getFileAbsolutePath());
             break;
     }
     //fill each entry into a ilBibliographicEntry object and then write it to DB by executing doCreate()
     foreach ($entries_from_file as $file_entry) {
         $type = NULL;
         $x = 0;
         $parsed_entry = array();
         foreach ($file_entry as $key => $attribute) {
             // if the attribute is an array, make a comma separated string out of it
             if (is_array($attribute)) {
                 $attribute = implode(", ", $attribute);
             }
             // reduce the attribute strings to a maximum of 4000 (ATTRIBUTE_VALUE_MAXIMAL_TEXT_LENGTH) characters, in order to fit in the database
             //if (mb_strlen($attribute, 'UTF-8') > self::ATTRIBUTE_VALUE_MAXIMAL_TEXT_LENGTH) {
             if (ilStr::strLen($attribute) > self::ATTRIBUTE_VALUE_MAXIMAL_TEXT_LENGTH) {
                 // $attribute = mb_substr($attribute, 0, self::ATTRIBUTE_VALUE_MAXIMAL_TEXT_LENGTH - 3, 'UTF-8') . '...';
                 $attribute = ilStr::subStr($attribute, 0, self::ATTRIBUTE_VALUE_MAXIMAL_TEXT_LENGTH - 3) . '...';
             }
             // ty (RIS) or entryType (BIB) is the type and is treated seperately
             if (strtolower($key) == 'ty' || strtolower($key) == 'entrytype') {
                 $type = $attribute;
                 continue;
             }
             //TODO - Refactoring for ILIAS 4.5 - get rid off array restructuring
             //change array structure (name not as the key, but under the key "name")
             $parsed_entry[$x]['name'] = $key;
             $parsed_entry[$x++]['value'] = $attribute;
         }
         //create the entry and fill data into database by executing doCreate()
         $entry_model = ilBibliographicEntry::getInstance($this->getFiletype());
         $entry_model->setType($type);
         $entry_model->setAttributes($parsed_entry);
         $entry_model->setBibliographicObjId($this->getId());
         $entry_model->doCreate();
     }
 }
コード例 #18
0
 /**
  * Saves the learners input of the question to the database.
  * 
  * @access public
  * @param integer $active_id Active id of the user
  * @param integer $pass Test pass
  * @return boolean $status
  */
 public function saveWorkingData($active_id, $pass = NULL)
 {
     global $ilDB;
     global $ilUser;
     include_once "./Services/Utilities/classes/class.ilStr.php";
     if (is_null($pass)) {
         include_once "./Modules/Test/classes/class.ilObjTest.php";
         $pass = ilObjTest::_getPass($active_id);
     }
     $affectedRows = $ilDB->manipulateF("DELETE FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s", array('integer', 'integer', 'integer'), array($active_id, $this->getId(), $pass));
     $text = ilUtil::stripSlashes($_POST["TEXT"], FALSE);
     if ($this->getMaxNumOfChars()) {
         include_once "./Services/Utilities/classes/class.ilStr.php";
         $text_without_tags = preg_replace("/<[^>*?]>/is", "", $text);
         $len_with_tags = ilStr::strLen($text);
         $len_without_tags = ilStr::strLen($text_without_tags);
         if ($this->getMaxNumOfChars() < $len_without_tags) {
             if (!$this->isHTML($text)) {
                 $text = ilStr::subStr($text, 0, $this->getMaxNumOfChars());
             }
         }
     }
     if ($this->isHTML($text)) {
         $text = preg_replace("/<[^>]*\$/ims", "", $text);
     } else {
         //$text = htmlentities($text, ENT_QUOTES, "UTF-8");
     }
     $entered_values = 0;
     if (strlen($text)) {
         $next_id = $ilDB->nextId('tst_solutions');
         $affectedRows = $ilDB->insert("tst_solutions", array("solution_id" => array("integer", $next_id), "active_fi" => array("integer", $active_id), "question_fi" => array("integer", $this->getId()), "value1" => array("clob", trim($text)), "value2" => array("clob", null), "pass" => array("integer", $pass), "tstamp" => array("integer", time())));
         $entered_values++;
     }
     if ($entered_values) {
         include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
         if (ilObjAssessmentFolder::_enabledAssessmentLogging()) {
             $this->logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
         }
     } else {
         include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
         if (ilObjAssessmentFolder::_enabledAssessmentLogging()) {
             $this->logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
         }
     }
     return true;
 }
コード例 #19
0
 /**
  * Allows to add additional form fields to the certificate editor form
  * This method will be called when the certificate editor form will built
  * using the ilPropertyFormGUI class. Additional fields will be added at the
  * bottom of the form.
  *
  * @param object $form An ilPropertyFormGUI instance
  * @param array $form_fields An array containing the form values. The array keys are the names of the form fields
  */
 public function addAdditionalFormElements(&$form, $form_fields)
 {
     global $lng;
     $short_name = new ilTextInputGUI($lng->txt("certificate_short_name"), "short_name");
     $short_name->setRequired(TRUE);
     require_once "./Services/Utilities/classes/class.ilStr.php";
     $short_name->setValue(strlen($form_fields["short_name"]) ? $form_fields["short_name"] : ilStr::subStr($this->object->getTitle(), 0, 30));
     $short_name->setSize(30);
     if (strlen($form_fields["short_name"])) {
         $short_name->setInfo(str_replace("[SHORT_TITLE]", $form_fields["short_name"], $lng->txt("certificate_short_name_description")));
     } else {
         $short_name->setInfo($lng->txt("certificate_short_name_description"));
     }
     if (count($_POST)) {
         $short_name->checkInput();
     }
     $form->addItem($short_name);
     $visibility = new ilCheckboxInputGUI($lng->txt("certificate_enabled_scorm"), "certificate_enabled_scorm");
     $visibility->setInfo($lng->txt("certificate_enabled_scorm_introduction"));
     $visibility->setValue(1);
     if ($form_fields["certificate_enabled_scorm"]) {
         $visibility->setChecked(TRUE);
     }
     if (count($_POST)) {
         $visibility->checkInput();
     }
     $form->addItem($visibility);
 }
コード例 #20
0
 /**
  * Returns the points for a text gap and compares the given solution with
  * the entered solution using the text gap rating options.
  *
  * @param string $a_original The original (correct) text
  * @param string $a_entered The text entered by the user
  * @param integer $max_points The maximum number of points for the solution
  * @access public
  */
 function getTextgapPoints($a_original, $a_entered, $max_points)
 {
     include_once "./Services/Utilities/classes/class.ilStr.php";
     $result = 0;
     $gaprating = $this->getTextgapRating();
     switch ($gaprating) {
         case TEXTGAP_RATING_CASEINSENSITIVE:
             if (strcmp(ilStr::strToLower($a_original), ilStr::strToLower($a_entered)) == 0) {
                 $result = $max_points;
             }
             break;
         case TEXTGAP_RATING_CASESENSITIVE:
             if (strcmp($a_original, $a_entered) == 0) {
                 $result = $max_points;
             }
             break;
         case TEXTGAP_RATING_LEVENSHTEIN1:
             if (levenshtein($a_original, $a_entered) <= 1) {
                 $result = $max_points;
             }
             break;
         case TEXTGAP_RATING_LEVENSHTEIN2:
             if (levenshtein($a_original, $a_entered) <= 2) {
                 $result = $max_points;
             }
             break;
         case TEXTGAP_RATING_LEVENSHTEIN3:
             if (levenshtein($a_original, $a_entered) <= 3) {
                 $result = $max_points;
             }
             break;
         case TEXTGAP_RATING_LEVENSHTEIN4:
             if (levenshtein($a_original, $a_entered) <= 4) {
                 $result = $max_points;
             }
             break;
         case TEXTGAP_RATING_LEVENSHTEIN5:
             if (levenshtein($a_original, $a_entered) <= 5) {
                 $result = $max_points;
             }
             break;
     }
     return $result;
 }
コード例 #21
0
 /**
  * Creates a the cumulated results data for the question
  *
  * @return array Data
  */
 public function getCumulatedResultData($survey_id, $counter, $finished_ids)
 {
     $cumulated =& $this->calculateCumulatedResults($survey_id, $finished_ids);
     $questiontext = preg_replace("/\\<[^>]+?>/ims", "", $this->getQuestiontext());
     $maxlen = 75;
     include_once "./Services/Utilities/classes/class.ilStr.php";
     if (ilStr::strlen($questiontext) > $maxlen + 3) {
         $questiontext = ilStr::substr($questiontext, 0, $maxlen) . "...";
     }
     $result = array('counter' => $counter, 'title' => $counter . '. ' . $this->getTitle(), 'question' => $questiontext, 'users_answered' => $cumulated['USERS_ANSWERED'], 'users_skipped' => $cumulated['USERS_SKIPPED'], 'question_type' => $this->lng->txt($cumulated["QUESTION_TYPE"]), 'mode' => $cumulated["MODE"], 'mode_nr_of_selections' => $cumulated["MODE_NR_OF_SELECTIONS"], 'median' => $cumulated["MEDIAN"], 'arithmetic_mean' => $cumulated["ARITHMETIC_MEAN"]);
     return $result;
 }
コード例 #22
0
 /**
  * Returns the index of the found answer, if the given answer is in the 
  * set of correct answers and matchess
  * the matching options, otherwise FALSE is returned
  *
  * @param array $answers An array containing the correct answers
  * @param string $answer The text of the given answer
  * @return mixed The index of the correct answer, FALSE otherwise
  * @access public
  */
 function isAnswerCorrect($answers, $answer)
 {
     include_once "./Services/Utilities/classes/class.ilStr.php";
     $result = 0;
     $textrating = $this->getTextRating();
     foreach ($answers as $key => $value) {
         switch ($textrating) {
             case TEXTGAP_RATING_CASEINSENSITIVE:
                 if (strcmp(ilStr::strToLower($value), ilStr::strToLower($answer)) == 0 && $this->answers[$key]->getPoints() > 0) {
                     return $key;
                 }
                 break;
             case TEXTGAP_RATING_CASESENSITIVE:
                 if (strcmp($value, $answer) == 0 && $this->answers[$key]->getPoints() > 0) {
                     return $key;
                 }
                 break;
             case TEXTGAP_RATING_LEVENSHTEIN1:
                 if (levenshtein($value, $answer) <= 1 && $this->answers[$key]->getPoints() > 0) {
                     return $key;
                 }
                 break;
             case TEXTGAP_RATING_LEVENSHTEIN2:
                 if (levenshtein($value, $answer) <= 2 && $this->answers[$key]->getPoints() > 0) {
                     return $key;
                 }
                 break;
             case TEXTGAP_RATING_LEVENSHTEIN3:
                 if (levenshtein($value, $answer) <= 3 && $this->answers[$key]->getPoints() > 0) {
                     return $key;
                 }
                 break;
             case TEXTGAP_RATING_LEVENSHTEIN4:
                 if (levenshtein($value, $answer) <= 4 && $this->answers[$key]->getPoints() > 0) {
                     return $key;
                 }
                 break;
             case TEXTGAP_RATING_LEVENSHTEIN5:
                 if (levenshtein($value, $answer) <= 5 && $this->answers[$key]->getPoints() > 0) {
                     return $key;
                 }
                 break;
         }
     }
     return FALSE;
 }
コード例 #23
0
 public function sendCodesMailObject()
 {
     global $ilUser;
     $this->parent_gui->handleWriteAccess();
     $this->setCodesSubtabs();
     include_once "./Modules/Survey/classes/forms/FormMailCodesGUI.php";
     $form_gui = new FormMailCodesGUI($this);
     if ($form_gui->checkInput()) {
         $code_exists = strpos($_POST['m_message'], '[code]') !== FALSE;
         if (!$code_exists) {
             if (!$code_exists) {
                 ilUtil::sendFailure($this->lng->txt('please_enter_mail_code'));
             }
             $form_gui->setValuesByPost();
         } else {
             if ($_POST['savemessage'] == 1) {
                 global $ilUser;
                 $title = strlen($_POST['savemessagetitle']) ? $_POST['savemessagetitle'] : ilStr::substr($_POST['m_message'], 0, 40) . '...';
                 $this->object->saveUserSettings($ilUser->getId(), 'savemessage', $title, $_POST['m_message']);
             }
             $lang = $ilUser->getPref("survey_code_language");
             if (!$lang) {
                 $lang = $this->lng->getDefaultLanguage();
             }
             $this->object->sendCodes($_POST['m_notsent'], $_POST['m_subject'], $_POST['m_message'], $lang);
             ilUtil::sendSuccess($this->lng->txt('mail_sent'), true);
             $this->ctrl->redirect($this, 'mailCodes');
         }
     } else {
         $form_gui->setValuesByPost();
     }
     $this->tpl->setVariable("ADM_CONTENT", $form_gui->getHTML());
 }
コード例 #24
0
ファイル: class.ilPageObject.php プロジェクト: bheyser/qplskl
 /**
  * Truncate (html) string
  * 
  * @see http://dodona.wordpress.com/2009/04/05/how-do-i-truncate-an-html-string-without-breaking-the-html-code/
  * 
  * @param string $a_text
  * @param int $a_length
  * @param string $a_ending
  * @param bool $a_exact
  * @param bool $a_consider_html
  * @return string
  */
 public static function truncateHTML($a_text, $a_length = 100, $a_ending = '...', $a_exact = false, $a_consider_html = true)
 {
     include_once "Services/Utilities/classes/class.ilStr.php";
     if ($a_consider_html) {
         // if the plain text is shorter than the maximum length, return the whole text
         if (strlen(preg_replace('/<.*?>/', '', $a_text)) <= $a_length) {
             return $a_text;
         }
         // splits all html-tags to scanable lines
         $total_length = strlen($a_ending);
         $open_tags = array();
         $truncate = '';
         preg_match_all('/(<.+?>)?([^<>]*)/s', $a_text, $lines, PREG_SET_ORDER);
         foreach ($lines as $line_matchings) {
             // if there is any html-tag in this line, handle it and add it (uncounted) to the output
             if (!empty($line_matchings[1])) {
                 // if it's an "empty element" with or without xhtml-conform closing slash
                 if (preg_match('/^<(\\s*.+?\\/\\s*|\\s*(img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param)(\\s.+?)?)>$/is', $line_matchings[1])) {
                     // do nothing
                 } else {
                     if (preg_match('/^<\\s*\\/([^\\s]+?)\\s*>$/s', $line_matchings[1], $tag_matchings)) {
                         // delete tag from $open_tags list
                         $pos = array_search($tag_matchings[1], $open_tags);
                         if ($pos !== false) {
                             unset($open_tags[$pos]);
                         }
                     } else {
                         if (preg_match('/^<\\s*([^\\s>!]+).*?>$/s', $line_matchings[1], $tag_matchings)) {
                             // add tag to the beginning of $open_tags list
                             array_unshift($open_tags, strtolower($tag_matchings[1]));
                         }
                     }
                 }
                 // add html-tag to $truncate'd text
                 $truncate .= $line_matchings[1];
             }
             // calculate the length of the plain text part of the line; handle entities as one character
             $content_length = strlen(preg_replace('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|[0-9a-f]{1,6};/i', ' ', $line_matchings[2]));
             if ($total_length + $content_length > $a_length) {
                 // the number of characters which are left
                 $left = $a_length - $total_length;
                 $entities_length = 0;
                 // search for html entities
                 if (preg_match_all('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|[0-9a-f]{1,6};/i', $line_matchings[2], $entities, PREG_OFFSET_CAPTURE)) {
                     // calculate the real length of all entities in the legal range
                     foreach ($entities[0] as $entity) {
                         if ($entity[1] + 1 - $entities_length <= $left) {
                             $left--;
                             $entities_length += strlen($entity[0]);
                         } else {
                             // no more characters left
                             break;
                         }
                     }
                 }
                 // $truncate .= substr($line_matchings[2], 0, $left+$entities_length);
                 $truncate .= ilStr::shortenText($line_matchings[2], 0, $left + $entities_length);
                 // maximum lenght is reached, so get off the loop
                 break;
             } else {
                 $truncate .= $line_matchings[2];
                 $total_length += $content_length;
             }
             // if the maximum length is reached, get off the loop
             if ($total_length >= $a_length) {
                 break;
             }
         }
     } else {
         if (strlen($a_text) <= $a_length) {
             return $a_text;
         } else {
             // $truncate = substr($a_text, 0, $a_length - strlen($a_ending));
             $truncate = ilStr::shortenText($a_text, 0, $a_length - strlen($a_ending));
         }
     }
     // THIS IS BUGGY AS IT MIGHT BREAK AN OPEN TAG AT THE END
     if (!sizeof($open_tags)) {
         // if the words shouldn't be cut in the middle...
         if (!$a_exact) {
             // ...search the last occurance of a space...
             $spacepos = strrpos($truncate, ' ');
             if ($spacepos !== false) {
                 // ...and cut the text in this position
                 // $truncate = substr($truncate, 0, $spacepos);
                 $truncate = ilStr::shortenText($truncate, 0, $spacepos);
             }
         }
     }
     // add the defined ending to the text
     $truncate .= $a_ending;
     if ($a_consider_html) {
         // close all unclosed html-tags
         foreach ($open_tags as $tag) {
             $truncate .= '</' . $tag . '>';
         }
     }
     return $truncate;
 }
コード例 #25
0
 /**
  * sub-function to sort an array
  *
  * @param	array	$a
  * @param	array	$b
  *
  * @return	boolean	true on success / false on error
  * @static
  * 
  */
 public static function sort_func($a, $b)
 {
     global $array_sortby, $array_sortorder;
     // this comparison should give optimal results if
     // locale is provided and mb string functions are supported
     if ($array_sortorder == "asc") {
         return ilStr::strCmp($a[$array_sortby], $b[$array_sortby]);
     }
     if ($array_sortorder == "desc") {
         return !ilStr::strCmp($a[$array_sortby], $b[$array_sortby]);
         return strcoll(ilStr::strToUpper($b[$array_sortby]), ilStr::strToUpper($a[$array_sortby]));
     }
 }
コード例 #26
0
 public function createErrorTextExport($selections = null)
 {
     $counter = 0;
     $errorcounter = 0;
     include_once "./Services/Utilities/classes/class.ilStr.php";
     if (!is_array($selections)) {
         $selections = array();
     }
     $textarray = preg_split("/[\n\r]+/", $this->getErrorText());
     foreach ($textarray as $textidx => $text) {
         $items = preg_split("/\\s+/", $text);
         foreach ($items as $idx => $item) {
             if (($posHash = strpos($item, '#')) === 0 || ($posOpeningBrackets = strpos($item, '((')) === 0 || ($posClosingBrackets = strpos($item, '))')) !== false) {
                 /* (Word|Passage)-Marking delimiter found. */
                 if ($posHash !== false) {
                     $item = ilStr::substr($item, 1, ilStr::strlen($item) - 1);
                 } elseif ($posOpeningBrackets !== false) {
                     $item = ilStr::substr($item, 2, ilStr::strlen($item) - 2);
                     /* Sometimes a closing bracket group needs
                        to be removed as well. */
                     if (strpos($item, '))') !== false) {
                         $item = ilStr::substr($item, 0, ilStr::strlen($item) - 2);
                     }
                 } else {
                     $appendComma = "";
                     if ($item[$posClosingBrackets + 2] == ',') {
                         $appendComma = ",";
                     }
                     $item = ilStr::substr($item, 0, $posClosingBrackets) . $appendComma;
                 }
             }
             $word = "";
             if (in_array($counter, $selections)) {
                 $word .= '#';
             }
             $word .= ilUtil::prepareFormOutput($item);
             if (in_array($counter, $selections)) {
                 $word .= '#';
             }
             $items[$idx] = $word;
             $counter++;
         }
         $textarray[$textidx] = join($items, " ");
     }
     return join($textarray, "\n");
 }
コード例 #27
0
ファイル: class.ilWikiPage.php プロジェクト: arlendotcn/ilias
 public function afterUpdate($a_domdoc, $a_xml)
 {
     // internal == wiki links
     include_once "Modules/Wiki/classes/class.ilWikiUtil.php";
     $int_links = sizeof(ilWikiUtil::collectInternalLinks($a_xml, $this->getWikiId(), true));
     $xpath = new DOMXPath($a_domdoc);
     // external = internal + external links
     $ext_links = sizeof($xpath->query('//IntLink'));
     $ext_links += sizeof($xpath->query('//ExtLink'));
     $footnotes = sizeof($xpath->query('//Footnote'));
     // words/characters (xml)
     $xml = strip_tags($a_xml);
     include_once "Services/Utilities/classes/class.ilStr.php";
     $num_chars = ilStr::strLen($xml);
     $num_words = sizeof(explode(" ", $xml));
     $page_data = array("int_links" => $int_links, "ext_links" => $ext_links, "footnotes" => $footnotes, "num_words" => $num_words, "num_chars" => $num_chars);
     include_once "./Modules/Wiki/classes/class.ilWikiStat.php";
     ilWikiStat::handleEvent(ilWikiStat::EVENT_PAGE_UPDATED, $this, null, $page_data);
 }