ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
class.ilContainerSorting.php
Go to the documentation of this file.
1 <?php
2 /*
3  +-----------------------------------------------------------------------------+
4  | ILIAS open source |
5  +-----------------------------------------------------------------------------+
6  | Copyright (c) 1998-2006 ILIAS open source, University of Cologne |
7  | |
8  | This program is free software; you can redistribute it and/or |
9  | modify it under the terms of the GNU General Public License |
10  | as published by the Free Software Foundation; either version 2 |
11  | of the License, or (at your option) any later version. |
12  | |
13  | This program is distributed in the hope that it will be useful, |
14  | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16  | GNU General Public License for more details. |
17  | |
18  | You should have received a copy of the GNU General Public License |
19  | along with this program; if not, write to the Free Software |
20  | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21  +-----------------------------------------------------------------------------+
22 */
23 
24 include_once './Services/Container/classes/class.ilContainer.php';
25 include_once('Services/Container/classes/class.ilContainerSortingSettings.php');
26 
36 {
40  protected $log;
41 
45  protected $tree;
46 
47  protected static $instances = array();
48 
49  protected $obj_id;
50  protected $db;
51 
52  protected $sorting_settings = null;
53  const ORDER_DEFAULT = 999999;
54 
62  private function __construct($a_obj_id)
63  {
64  global $DIC;
65 
66  $this->log = $DIC["ilLog"];
67  $this->tree = $DIC->repositoryTree();
68  $ilDB = $DIC->database();
69 
70  $this->db = $ilDB;
71  $this->obj_id = $a_obj_id;
72 
73  $this->read();
74  }
75 
80  public function getSortingSettings()
81  {
83  }
84 
93  public static function _getInstance($a_obj_id)
94  {
95  if (isset(self::$instances[$a_obj_id])) {
96  return self::$instances[$a_obj_id];
97  }
98  return self::$instances[$a_obj_id] = new ilContainerSorting($a_obj_id);
99  }
100 
106  public static function lookupPositions($a_obj_id)
107  {
108  global $DIC;
109 
110  $ilDB = $DIC->database();
111 
112  $query = "SELECT * FROM container_sorting WHERE " .
113  "obj_id = " . $ilDB->quote($a_obj_id, 'integer');
114  $res = $ilDB->query($query);
115  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
116  $sorted[$row->child_id] = $row->position;
117  }
118  return $sorted ? $sorted : array();
119  }
120 
127  public function cloneSorting($a_target_id, $a_copy_id)
128  {
129  $ilDB = $this->db;
130 
132  $ilLog->debug("Cloning container sorting.");
133 
134  $target_obj_id = ilObject::_lookupObjId($a_target_id);
135 
136  include_once('./Services/CopyWizard/classes/class.ilCopyWizardOptions.php');
137  $mappings = ilCopyWizardOptions::_getInstance($a_copy_id)->getMappings();
138 
139 
140  // copy blocks sorting
141  $set = $ilDB->queryF(
142  "SELECT * FROM container_sorting_bl " .
143  " WHERE obj_id = %s ",
144  array("integer"),
145  array($this->obj_id)
146  );
147  if ($rec = $ilDB->fetchAssoc($set)) {
148  if ($rec["block_ids"] != "") {
149  $ilLog->debug("Got block sorting for obj_id = " . $this->obj_id . ": " . $rec["block_ids"]);
150  $new_ids = implode(";", array_map(function ($block_id) use ($mappings) {
151  if (is_numeric($block_id)) {
152  $block_id = $mappings[$block_id];
153  }
154  return $block_id;
155  }, explode(";", $rec["block_ids"])));
156 
157  $ilDB->insert("container_sorting_bl", array(
158  "obj_id" => array("integer", $target_obj_id),
159  "block_ids" => array("text", $new_ids)
160  ));
161 
162  $ilLog->debug("Write block sorting for obj_id = " . $target_obj_id . ": " . $new_ids);
163  }
164  }
165 
166 
167  $ilLog->debug("Read container_sorting for obj_id = " . $this->obj_id);
168 
169  $query = "SELECT * FROM container_sorting " .
170  "WHERE obj_id = " . $ilDB->quote($this->obj_id, 'integer');
171 
172  $res = $ilDB->query($query);
173 
174  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
175  if (!isset($mappings[$row->child_id]) or !$mappings[$row->child_id]) {
176  $ilLog->debug("No mapping found for child id:" . $row->child_id);
177  continue;
178  }
179 
180 
181  $new_parent_id = 0;
182  if ($row->parent_id) {
183  // see bug #20347
184  // at least in the case of sessions and item groups parent_ids in container sorting are object IDs but $mappings store references
185  if (in_array($row->parent_type, array("sess", "itgr"))) {
186  $par_refs = ilObject::_getAllReferences($row->parent_id);
187  $par_ref_id = current($par_refs); // should be only one
188  $ilLog->debug("Got ref id: " . $par_ref_id . " for obj_id " . $row->parent_id . " map ref id: " . $mappings[$par_ref_id] . ".");
189  if (isset($mappings[$par_ref_id])) {
190  $new_parent_ref_id = $mappings[$par_ref_id];
191  $new_parent_id = ilObject::_lookupObjectId($new_parent_ref_id);
192  }
193  } else { // not sure if this is still used for other cases that expect ref ids
194  $new_parent_id = $mappings[$row->parent_id];
195  }
196  if ((int) $new_parent_id == 0) {
197  $ilLog->debug("No mapping found for parent id:" . $row->parent_id . ", child_id: " . $row->child_id);
198  continue;
199  }
200  }
201 
202  $query = "DELETE FROM container_sorting " .
203  "WHERE obj_id = " . $ilDB->quote($target_obj_id, 'integer') . " " .
204  "AND child_id = " . $ilDB->quote($mappings[$row->child_id], 'integer') . " " .
205  "AND parent_type = " . $ilDB->quote($row->parent_type, 'text') . ' ' .
206  "AND parent_id = " . $ilDB->quote((int) $new_parent_id, 'integer');
207  $ilLog->debug($query);
208  $ilDB->manipulate($query);
209 
210  // Add new value
211  $query = "INSERT INTO container_sorting (obj_id,child_id,position,parent_type,parent_id) " .
212  "VALUES( " .
213  $ilDB->quote($target_obj_id, 'integer') . ", " .
214  $ilDB->quote($mappings[$row->child_id], 'integer') . ", " .
215  $ilDB->quote($row->position, 'integer') . ", " .
216  $ilDB->quote($row->parent_type, 'text') . ", " .
217  $ilDB->quote((int) $new_parent_id, 'integer') .
218  ")";
219  $ilLog->debug($query);
220  $ilDB->manipulate($query);
221  }
222  return true;
223  }
224 
225 
226 
234  public function sortItems($a_items)
235  {
236  $sorted = array();
237  if ($this->getSortingSettings()->getSortMode() != ilContainer::SORT_MANUAL) {
238  switch ($this->getSortingSettings()->getSortMode()) {
240  foreach ((array) $a_items as $type => $data) {
241  // #16311 - sorting will remove keys (prev/next)
242  if ($type == 'sess_link') {
243  $sorted[$type] = $data;
244  continue;
245  }
246 
247  // this line used until #4389 has been fixed (3.10.6)
248  // reanimated with 4.4.0
249  $sorted[$type] = ilUtil::sortArray(
250  (array) $data,
251  'title',
252  ($this->getSortingSettings()->getSortDirection() == ilContainer::SORT_DIRECTION_ASC) ? 'asc' : 'desc',
253  false
254  );
255 
256  // the next line tried to use db sorting and has replaced sortArray due to bug #4389
257  // but leads to bug #12165. PHP should be able to do a proper sorting, if the locale
258  // is set correctly, so we witch back to sortArray (with 4.4.0) and see what
259  // feedback we get
260  // (next line has been used from 3.10.6 to 4.3.x)
261 // $sorted[$type] = $data;
262  }
263  return $sorted ? $sorted : array();
264 
266  foreach ((array) $a_items as $type => $data) {
267  // #16311 - sorting will remove keys (prev/next)
268  if ($type == 'sess_link') {
269  $sorted[$type] = $data;
270  continue;
271  }
272 
273  $sorted[$type] = ilUtil::sortArray(
274  (array) $data,
275  'start',
276  ($this->getSortingSettings()->getSortDirection() == ilContainer::SORT_DIRECTION_ASC) ? 'asc' : 'desc',
277  true
278  );
279  }
280  return $sorted ? $sorted : array();
281 
282 
284  foreach ((array) $a_items as $type => $data) {
285  // #16311 - sorting will remove keys (prev/next)
286  if ($type == 'sess_link') {
287  $sorted[$type] = $data;
288  continue;
289  }
290 
291  $sorted[$type] = ilUtil::sortArray(
292  (array) $data,
293  'create_date',
294  ($this->getSortingSettings()->getSortDirection() == ilContainer::SORT_DIRECTION_ASC) ? 'asc' : 'desc',
295  true
296  );
297  }
298  return $sorted ? $sorted : array();
299  }
300  return $a_items;
301  }
302  if (!is_array($a_items) || !count($a_items)) {
303  return $a_items;
304  }
305  $sorted = array();
306  foreach ((array) $a_items as $type => $data) {
307  if ($type == 'sess_link') {
308  $sorted[$type] = $data;
309  continue;
310  }
311 
312  // Add position
313  $items = array();
314  foreach ((array) $data as $key => $item) {
315  $items[$key] = $item;
316  if (is_array($this->sorting['all']) and isset($this->sorting['all'][$item['child']])) {
317  $items[$key]['position'] = $this->sorting['all'][$item['child']];
318  } else {
319  $items[$key]['position'] = self::ORDER_DEFAULT;
320  }
321  }
322 
323  $items = $this->sortOrderDefault($items);
324 
325  switch ($type) {
326  case '_all':
327  $sorted[$type] = ilUtil::sortArray((array) $items, 'position', 'asc', true);
328  break;
329 
330  case '_non_sess':
331  $sorted[$type] = ilUtil::sortArray((array) $items, 'position', 'asc', true);
332  break;
333 
334  default:
335  $sorted[$type] = ilUtil::sortArray((array) $items, 'position', 'asc', true);
336  break;
337  }
338  }
339  return $sorted ? $sorted : array();
340  }
341 
349  public function sortSubItems($a_parent_type, $a_parent_id, $a_items)
350  {
351  switch ($this->getSortingSettings()->getSortMode()) {
353  $items = array();
354  foreach ($a_items as $key => $item) {
355  $items[$key] = $item;
356  $items[$key]['position'] = isset($this->sorting[$a_parent_type][$a_parent_id][$item['child']]) ?
357  $this->sorting[$a_parent_type][$a_parent_id][$item['child']] : self::ORDER_DEFAULT;
358  }
359 
360  $items = $this->sortOrderDefault($items);
361  return ilUtil::sortArray((array) $items, 'position', 'asc', true);
362 
363 
365  return ilUtil::sortArray(
366  (array) $a_items,
367  'start',
368  ($this->getSortingSettings()->getSortDirection() == ilContainer::SORT_DIRECTION_ASC) ? 'asc' : 'desc',
369  true
370  );
371 
373  return ilUtil::sortArray(
374  (array) $a_items,
375  'create_date',
376  ($this->getSortingSettings()->getSortDirection() == ilContainer::SORT_DIRECTION_ASC) ? 'asc' : 'desc',
377  true
378  );
379 
380  default:
382  return ilUtil::sortArray(
383  (array) $a_items,
384  'title',
385  ($this->getSortingSettings()->getSortDirection() == ilContainer::SORT_DIRECTION_ASC) ? 'asc' : 'desc',
386  false
387  );
388  }
389  }
390 
398  public function savePost($a_type_positions)
399  {
400  if (!is_array($a_type_positions)) {
401  return false;
402  }
403  $items = [];
404  foreach ($a_type_positions as $key => $position) {
405  if ($key == "blocks") {
406  $this->saveBlockPositions($position);
407  } elseif (!is_array($position)) {
408  $items[$key] = $position * 100;
409  } else {
410  foreach ($position as $parent_id => $sub_items) {
411  $this->saveSubItems($key, $parent_id, $sub_items ? $sub_items : array());
412  }
413  }
414  }
415 
416  if (!count($items)) {
417  return $this->saveItems(array());
418  }
419 
420  asort($items);
421  $new_indexed = [];
422  $position = 0;
423  foreach ($items as $key => $null) {
424  $new_indexed[$key] = ++$position;
425  }
426 
427  $this->saveItems($new_indexed);
428  }
429 
430 
440  protected function saveItems($a_items)
441  {
442  $ilDB = $this->db;
443 
444  foreach ($a_items as $child_id => $position) {
445  $ilDB->replace(
446  'container_sorting',
447  array(
448  'obj_id' => array('integer',$this->obj_id),
449  'child_id' => array('integer',$child_id),
450  'parent_id' => array('integer',0)
451  ),
452  array(
453  'parent_type' => array('text',''),
454  'position' => array('integer',$position)
455  )
456  );
457  }
458  return true;
459  }
460 
468  protected function saveSubItems($a_parent_type, $a_parent_id, $a_items)
469  {
470  $ilDB = $this->db;
471 
472  foreach ($a_items as $child_id => $position) {
473  $ilDB->replace(
474  'container_sorting',
475  array(
476  'obj_id' => array('integer',$this->obj_id),
477  'child_id' => array('integer',$child_id),
478  'parent_id' => array('integer',$a_parent_id)
479  ),
480  array(
481  'parent_type' => array('text',$a_parent_type),
482  'position' => array('integer',$position)
483  )
484  );
485  }
486  return true;
487  }
488 
494  protected function saveBlockPositions(array $a_values)
495  {
496  $ilDB = $this->db;
497 
498  asort($a_values);
499  $ilDB->replace(
500  'container_sorting_bl',
501  array(
502  'obj_id' => array('integer',$this->obj_id)
503  ),
504  array(
505  'block_ids' => array('text', implode(";", array_keys($a_values)))
506  )
507  );
508  }
509 
515  public function getBlockPositions()
516  {
517  $ilDB = $this->db;
518 
519  $set = $ilDB->query("SELECT block_ids" .
520  " FROM container_sorting_bl" .
521  " WHERE obj_id = " . $ilDB->quote($this->obj_id, "integer"));
522  $row = $ilDB->fetchAssoc($set);
523  if ($row["block_ids"]) {
524  return explode(";", $row["block_ids"]);
525  }
526  }
527 
528 
535  private function read()
536  {
537  $tree = $this->tree;
538 
539  if (!$this->obj_id) {
540  $this->sorting_settings = new ilContainerSortingSettings();
541  return true;
542  }
543 
545  $this->sorting_settings = $sorting_settings->loadEffectiveSettings();
546  $query = "SELECT * FROM container_sorting " .
547  "WHERE obj_id = " . $this->db->quote($this->obj_id, 'integer') . " ORDER BY position";
548  $res = $this->db->query($query);
549  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
550  if ($row->parent_id) {
551  $this->sorting[$row->parent_type][$row->parent_id][$row->child_id] = $row->position;
552  } else {
553  $this->sorting['all'][$row->child_id] = $row->position;
554  }
555  }
556  return true;
557  }
558 
565  private function sortOrderDefault($items)
566  {
567  $no_position = array();
568 
569  foreach ($items as $key => $item) {
570  if ($item["position"] == self::ORDER_DEFAULT) {
571  $no_position[] = array("key" => $key, "title" => $item["title"], "create_date" => $item["create_date"],
572  "start" => $item["start"]);
573  }
574  }
575 
576  if (!count($no_position)) {
577  return $items;
578  }
579 
580  switch ($this->getSortingSettings()->getSortNewItemsOrder()) {
582  $no_position = ilUtil::sortArray(
583  (array) $no_position,
584  'title',
585  ($this->getSortingSettings()->getSortDirection() == ilContainer::SORT_DIRECTION_ASC) ? 'asc' : 'desc',
586  true
587  );
588  break;
590  $no_position = ilUtil::sortArray(
591  (array) $no_position,
592  'create_date',
593  ($this->getSortingSettings()->getSortDirection() == ilContainer::SORT_DIRECTION_ASC) ? 'asc' : 'desc',
594  true
595  );
596  break;
598  $no_position = ilUtil::sortArray(
599  (array) $no_position,
600  'start',
601  ($this->getSortingSettings()->getSortDirection() == ilContainer::SORT_DIRECTION_ASC) ? 'asc' : 'desc',
602  true
603  );
604 
605  }
606  $count = $this->getSortingSettings()->getSortNewItemsPosition()
607  == ilContainer::SORT_NEW_ITEMS_POSITION_TOP ? -900000 : 900000;
608 
609  foreach ($no_position as $values) {
610  $items[$values["key"]]["position"] = $count;
611  $count++;
612  }
613  return $items;
614  }
615 }
static sortArray( $array, $a_array_sortby, $a_array_sortorder=0, $a_numeric=false, $a_keep_keys=false)
sortArray
saveItems($a_items)
save items
const SORT_NEW_ITEMS_POSITION_TOP
$type
saveBlockPositions(array $a_values)
Save block custom positions (for current object id)
global $DIC
Definition: saml.php:7
sortOrderDefault($items)
Position and order sort order for new object without position in manual sorting type.
savePost($a_type_positions)
Save post.
getBlockPositions()
Read block custom positions (for current object id)
sortSubItems($a_parent_type, $a_parent_id, $a_items)
sort subitems (items of sessions or learning objectives)
static _getAllReferences($a_id)
get all reference ids of object
static _lookupObjectId($a_ref_id)
lookup object id
getSortingSettings()
Get sorting settings.
sortItems($a_items)
sort subitems
__construct($a_obj_id)
Constructor.
static _getInstance($a_copy_id)
Get instance of copy wizard options.
foreach($_POST as $key=> $value) $res
$values
saveSubItems($a_parent_type, $a_parent_id, $a_items)
Save subitem ordering (sessions, learning objectives)
const SORT_NEW_ITEMS_ORDER_CREATION
static _lookupObjId($a_id)
$query
$row
const SORT_NEW_ITEMS_ORDER_ACTIVATION
global $ilDB
static getLogger($a_component_id)
Get component logger.
static getInstanceByObjId($a_obj_id)
Get singleton instance.
static _getInstance($a_obj_id)
get instance by obj_id
static lookupPositions($a_obj_id)
Get positions of subitems.
const SORT_NEW_ITEMS_ORDER_TITLE
$key
Definition: croninfo.php:18
cloneSorting($a_target_id, $a_copy_id)
clone sorting
$data
Definition: bench.php:6