ILIAS  release_7 Revision v7.30-3-g800a261c036
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
24include_once './Services/Container/classes/class.ilContainer.php';
25include_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 {
130
131 $ilLog = ilLoggerFactory::getLogger("cont");
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->replace(
158 "container_sorting_bl",
159 array("obj_id" => array("integer", $target_obj_id)),
160 array("block_ids" => array("text", $new_ids))
161 );
162
163 $ilLog->debug("Write block sorting for obj_id = " . $target_obj_id . ": " . $new_ids);
164 }
165 }
166
167
168 $ilLog->debug("Read container_sorting for obj_id = " . $this->obj_id);
169
170 $query = "SELECT * FROM container_sorting " .
171 "WHERE obj_id = " . $ilDB->quote($this->obj_id, 'integer');
172
173 $res = $ilDB->query($query);
174
175 while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
176 if (!isset($mappings[$row->child_id]) or !$mappings[$row->child_id]) {
177 $ilLog->debug("No mapping found for child id:" . $row->child_id);
178 continue;
179 }
180
181
182 $new_parent_id = 0;
183 if ($row->parent_id) {
184 // see bug #20347
185 // at least in the case of sessions and item groups parent_ids in container sorting are object IDs but $mappings store references
186 if (in_array($row->parent_type, array("sess", "itgr"))) {
187 $par_refs = ilObject::_getAllReferences($row->parent_id);
188 $par_ref_id = current($par_refs); // should be only one
189 $ilLog->debug("Got ref id: " . $par_ref_id . " for obj_id " . $row->parent_id . " map ref id: " . $mappings[$par_ref_id] . ".");
190 if (isset($mappings[$par_ref_id])) {
191 $new_parent_ref_id = $mappings[$par_ref_id];
192 $new_parent_id = ilObject::_lookupObjectId($new_parent_ref_id);
193 }
194 } else { // not sure if this is still used for other cases that expect ref ids
195 $new_parent_id = $mappings[$row->parent_id];
196 }
197 if ((int) $new_parent_id == 0) {
198 $ilLog->debug("No mapping found for parent id:" . $row->parent_id . ", child_id: " . $row->child_id);
199 continue;
200 }
201 }
202
203 $query = "DELETE FROM container_sorting " .
204 "WHERE obj_id = " . $ilDB->quote($target_obj_id, 'integer') . " " .
205 "AND child_id = " . $ilDB->quote($mappings[$row->child_id], 'integer') . " " .
206 "AND parent_type = " . $ilDB->quote($row->parent_type, 'text') . ' ' .
207 "AND parent_id = " . $ilDB->quote((int) $new_parent_id, 'integer');
208 $ilLog->debug($query);
209 $ilDB->manipulate($query);
210
211 // Add new value
212 $query = "INSERT INTO container_sorting (obj_id,child_id,position,parent_type,parent_id) " .
213 "VALUES( " .
214 $ilDB->quote($target_obj_id, 'integer') . ", " .
215 $ilDB->quote($mappings[$row->child_id], 'integer') . ", " .
216 $ilDB->quote($row->position, 'integer') . ", " .
217 $ilDB->quote($row->parent_type, 'text') . ", " .
218 $ilDB->quote((int) $new_parent_id, 'integer') .
219 ")";
220 $ilLog->debug($query);
221 $ilDB->manipulate($query);
222 }
223 return true;
224 }
225
226
227
235 public function sortItems($a_items)
236 {
237 if (!is_array($a_items)) {
238 return [];
239 }
240
241 $sorted = array();
242 if ($this->getSortingSettings()->getSortMode() != ilContainer::SORT_MANUAL) {
243 switch ($this->getSortingSettings()->getSortMode()) {
245 foreach ((array) $a_items as $type => $data) {
246 // #16311 - sorting will remove keys (prev/next)
247 if ($type == 'sess_link') {
248 $sorted[$type] = $data;
249 continue;
250 }
251
252 // this line used until #4389 has been fixed (3.10.6)
253 // reanimated with 4.4.0
254 $sorted[$type] = ilUtil::sortArray(
255 (array) $data,
256 'title',
257 ($this->getSortingSettings()->getSortDirection() == ilContainer::SORT_DIRECTION_ASC) ? 'asc' : 'desc',
258 false
259 );
260
261 // the next line tried to use db sorting and has replaced sortArray due to bug #4389
262 // but leads to bug #12165. PHP should be able to do a proper sorting, if the locale
263 // is set correctly, so we witch back to sortArray (with 4.4.0) and see what
264 // feedback we get
265 // (next line has been used from 3.10.6 to 4.3.x)
266// $sorted[$type] = $data;
267 }
268 return $sorted ? $sorted : array();
269
271 foreach ((array) $a_items as $type => $data) {
272 // #16311 - sorting will remove keys (prev/next)
273 if ($type == 'sess_link') {
274 $sorted[$type] = $data;
275 continue;
276 }
277
278 $sorted[$type] = ilUtil::sortArray(
279 (array) $data,
280 'start',
281 ($this->getSortingSettings()->getSortDirection() == ilContainer::SORT_DIRECTION_ASC) ? 'asc' : 'desc',
282 true
283 );
284 }
285 return $sorted ? $sorted : array();
286
287
289 foreach ((array) $a_items as $type => $data) {
290 // #16311 - sorting will remove keys (prev/next)
291 if ($type == 'sess_link') {
292 $sorted[$type] = $data;
293 continue;
294 }
295
296 $sorted[$type] = ilUtil::sortArray(
297 (array) $data,
298 'create_date',
299 ($this->getSortingSettings()->getSortDirection() == ilContainer::SORT_DIRECTION_ASC) ? 'asc' : 'desc',
300 true
301 );
302 }
303 return $sorted ? $sorted : array();
304 }
305 return $a_items;
306 }
307 if (!is_array($a_items) || !count($a_items)) {
308 return $a_items;
309 }
310 $sorted = array();
311 foreach ((array) $a_items as $type => $data) {
312 if ($type == 'sess_link') {
313 $sorted[$type] = $data;
314 continue;
315 }
316
317 // Add position
318 $items = array();
319 foreach ((array) $data as $key => $item) {
320 $items[$key] = $item;
321 if (is_array($this->sorting['all']) and isset($this->sorting['all'][$item['child']])) {
322 $items[$key]['position'] = $this->sorting['all'][$item['child']];
323 } else {
324 $items[$key]['position'] = self::ORDER_DEFAULT;
325 }
326 }
327
328 $items = $this->sortOrderDefault($items);
329
330 switch ($type) {
331 case '_all':
332 $sorted[$type] = ilUtil::sortArray((array) $items, 'position', 'asc', true);
333 break;
334
335 case '_non_sess':
336 $sorted[$type] = ilUtil::sortArray((array) $items, 'position', 'asc', true);
337 break;
338
339 default:
340 $sorted[$type] = ilUtil::sortArray((array) $items, 'position', 'asc', true);
341 break;
342 }
343 }
344 return $sorted ? $sorted : array();
345 }
346
354 public function sortSubItems($a_parent_type, $a_parent_id, $a_items)
355 {
356 switch ($this->getSortingSettings()->getSortMode()) {
358 $items = array();
359 foreach ($a_items as $key => $item) {
360 $items[$key] = $item;
361 $items[$key]['position'] = isset($this->sorting[$a_parent_type][$a_parent_id][$item['child']]) ?
362 $this->sorting[$a_parent_type][$a_parent_id][$item['child']] : self::ORDER_DEFAULT;
363 }
364
365 $items = $this->sortOrderDefault($items);
366 return ilUtil::sortArray((array) $items, 'position', 'asc', true);
367
368
370 return ilUtil::sortArray(
371 (array) $a_items,
372 'start',
373 ($this->getSortingSettings()->getSortDirection() == ilContainer::SORT_DIRECTION_ASC) ? 'asc' : 'desc',
374 true
375 );
376
378 return ilUtil::sortArray(
379 (array) $a_items,
380 'create_date',
381 ($this->getSortingSettings()->getSortDirection() == ilContainer::SORT_DIRECTION_ASC) ? 'asc' : 'desc',
382 true
383 );
384
385 default:
387 return ilUtil::sortArray(
388 (array) $a_items,
389 'title',
390 ($this->getSortingSettings()->getSortDirection() == ilContainer::SORT_DIRECTION_ASC) ? 'asc' : 'desc',
391 false
392 );
393 }
394 }
395
403 public function savePost($a_type_positions)
404 {
405 if (!is_array($a_type_positions)) {
406 return false;
407 }
408 $items = [];
409 foreach ($a_type_positions as $key => $position) {
410 if ($key == "blocks") {
411 $this->saveBlockPositions($position);
412 } elseif (!is_array($position)) {
413 $items[$key] = ((float) $position) * 100;
414 } else {
415 foreach ($position as $parent_id => $sub_items) {
416 $this->saveSubItems($key, $parent_id, $sub_items ? $sub_items : array());
417 }
418 }
419 }
420
421 if (!count($items)) {
422 return $this->saveItems(array());
423 }
424
425 asort($items);
426 $new_indexed = [];
427 $position = 0;
428 foreach ($items as $key => $null) {
429 $new_indexed[$key] = ++$position;
430 }
431
432 $this->saveItems($new_indexed);
433 }
434
435
445 protected function saveItems($a_items)
446 {
448
449 foreach ($a_items as $child_id => $position) {
450 $ilDB->replace(
451 'container_sorting',
452 array(
453 'obj_id' => array('integer',$this->obj_id),
454 'child_id' => array('integer',$child_id),
455 'parent_id' => array('integer',0)
456 ),
457 array(
458 'parent_type' => array('text',''),
459 'position' => array('integer',$position)
460 )
461 );
462 }
463 return true;
464 }
465
473 protected function saveSubItems($a_parent_type, $a_parent_id, $a_items)
474 {
476
477 foreach ($a_items as $child_id => $position) {
478 $ilDB->replace(
479 'container_sorting',
480 array(
481 'obj_id' => array('integer',$this->obj_id),
482 'child_id' => array('integer',$child_id),
483 'parent_id' => array('integer',$a_parent_id)
484 ),
485 array(
486 'parent_type' => array('text',$a_parent_type),
487 'position' => array('integer',$position)
488 )
489 );
490 }
491 return true;
492 }
493
499 protected function saveBlockPositions(array $a_values)
500 {
502 asort($a_values);
503 $ilDB->replace(
504 'container_sorting_bl',
505 array(
506 'obj_id' => array('integer',$this->obj_id)
507 ),
508 array(
509 'block_ids' => array('text', implode(";", array_keys($a_values)))
510 )
511 );
512 }
513
519 public function getBlockPositions()
520 {
522
523 $set = $ilDB->query("SELECT block_ids" .
524 " FROM container_sorting_bl" .
525 " WHERE obj_id = " . $ilDB->quote($this->obj_id, "integer"));
526 $row = $ilDB->fetchAssoc($set);
527 if ($row["block_ids"]) {
528 return explode(";", $row["block_ids"]);
529 }
530 }
531
532
539 private function read()
540 {
542
543 if (!$this->obj_id) {
544 $this->sorting_settings = new ilContainerSortingSettings();
545 return true;
546 }
547
549 $this->sorting_settings = $sorting_settings->loadEffectiveSettings();
550 $query = "SELECT * FROM container_sorting " .
551 "WHERE obj_id = " . $this->db->quote($this->obj_id, 'integer') . " ORDER BY position";
552 $res = $this->db->query($query);
553 while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
554 if ($row->parent_id) {
555 $this->sorting[$row->parent_type][$row->parent_id][$row->child_id] = $row->position;
556 } else {
557 $this->sorting['all'][$row->child_id] = $row->position;
558 }
559 }
560 return true;
561 }
562
569 private function sortOrderDefault($items)
570 {
571 $no_position = array();
572
573 foreach ($items as $key => $item) {
574 if ($item["position"] == self::ORDER_DEFAULT) {
575 $no_position[] = array("key" => $key, "title" => $item["title"], "create_date" => $item["create_date"],
576 "start" => $item["start"]);
577 }
578 }
579
580 if (!count($no_position)) {
581 return $items;
582 }
583
584 switch ($this->getSortingSettings()->getSortNewItemsOrder()) {
586 $no_position = ilUtil::sortArray(
587 (array) $no_position,
588 'title',
589 ($this->getSortingSettings()->getSortDirection() == ilContainer::SORT_DIRECTION_ASC) ? 'asc' : 'desc',
590 true
591 );
592 break;
594 $no_position = ilUtil::sortArray(
595 (array) $no_position,
596 'create_date',
597 ($this->getSortingSettings()->getSortDirection() == ilContainer::SORT_DIRECTION_ASC) ? 'asc' : 'desc',
598 true
599 );
600 break;
602 $no_position = ilUtil::sortArray(
603 (array) $no_position,
604 'start',
605 ($this->getSortingSettings()->getSortDirection() == ilContainer::SORT_DIRECTION_ASC) ? 'asc' : 'desc',
606 true
607 );
608
609 }
610 $count = $this->getSortingSettings()->getSortNewItemsPosition()
611 == ilContainer::SORT_NEW_ITEMS_POSITION_TOP ? -900000 : 900000;
612
613 foreach ($no_position as $values) {
614 $items[$values["key"]]["position"] = $count;
615 $count++;
616 }
617 return $items;
618 }
619}
An exception for terminatinating execution or to throw for unit testing.
static getInstanceByObjId($a_obj_id)
Get singleton instance.
cloneSorting($a_target_id, $a_copy_id)
clone sorting
sortItems($a_items)
sort subitems
getBlockPositions()
Read block custom positions (for current object id)
__construct($a_obj_id)
Constructor.
saveBlockPositions(array $a_values)
Save block custom positions (for current object id)
sortOrderDefault($items)
Position and order sort order for new object without position in manual sorting type.
saveItems($a_items)
save items
saveSubItems($a_parent_type, $a_parent_id, $a_items)
Save subitem ordering (sessions, learning objectives)
static lookupPositions($a_obj_id)
Get positions of subitems.
static _getInstance($a_obj_id)
get instance by obj_id
savePost($a_type_positions)
Save post.
sortSubItems($a_parent_type, $a_parent_id, $a_items)
sort subitems (items of sessions or learning objectives)
getSortingSettings()
Get sorting settings.
const SORT_NEW_ITEMS_ORDER_ACTIVATION
const SORT_NEW_ITEMS_ORDER_TITLE
const SORT_NEW_ITEMS_ORDER_CREATION
const SORT_NEW_ITEMS_POSITION_TOP
static _getInstance($a_copy_id)
Get instance of copy wizard options.
static getLogger($a_component_id)
Get component logger.
static _lookupObjId($a_id)
static _lookupObjectId($a_ref_id)
lookup object id
static _getAllReferences($a_id)
get all reference ids of object
static sortArray( $array, $a_array_sortby, $a_array_sortorder=0, $a_numeric=false, $a_keep_keys=false)
sortArray
global $DIC
Definition: goto.php:24
$query
$type
foreach($_POST as $key=> $value) $res
global $ilDB
$data
Definition: storeScorm.php:23