ILIAS  release_8 Revision v8.19-1-g4e8f2f9140c
All Data Structures Namespaces Files Functions Variables Modules Pages
class.ilObjPortfolioBase.php
Go to the documentation of this file.
1 <?php
2 
24 abstract class ilObjPortfolioBase extends ilObject2
25 {
26  protected \ILIAS\Notes\Service $notes;
27  protected ilSetting $setting;
28  protected bool $online = false;
29  protected bool $comments = false;
30  protected string $bg_color = "";
31  protected string $font_color = "";
32  protected string $img = "";
33  protected string $ppic = "";
34  protected bool $style = false;
35 
36  public function __construct(
37  int $a_id = 0,
38  bool $a_reference = true
39  ) {
40  global $DIC;
41 
42  $this->notes = $DIC->notes();
43 
44  parent::__construct($a_id, $a_reference);
45 
46  $this->setting = $DIC->settings();
47 
48  $this->db = $DIC->database();
49  }
50 
51 
52  //
53  // PROPERTIES
54  //
55 
56  public function setOnline(bool $a_value): void
57  {
58  $this->online = $a_value;
59  }
60 
61  public function isOnline(): bool
62  {
63  return $this->online;
64  }
65 
66  public static function lookupOnline(int $a_id): bool
67  {
68  global $DIC;
69 
70  $ilDB = $DIC->database();
71 
72  $set = $ilDB->query("SELECT is_online" .
73  " FROM usr_portfolio" .
74  " WHERE id = " . $ilDB->quote($a_id, "integer"));
75  $row = $ilDB->fetchAssoc($set);
76  return (bool) $row["is_online"];
77  }
78 
79  public function setPublicComments(bool $a_value): void
80  {
81  $this->comments = $a_value;
82  }
83 
84  public function hasPublicComments(): bool
85  {
86  return $this->comments;
87  }
88 
89  public function hasProfilePicture(): bool
90  {
91  return $this->ppic;
92  }
93 
94  public function setProfilePicture(bool $a_status): void
95  {
96  $this->ppic = $a_status;
97  }
98 
99  public function getBackgroundColor(): string
100  {
101  if (!$this->bg_color) {
102  $this->bg_color = "ffffff";
103  }
104  return $this->bg_color;
105  }
106 
110  public function setBackgroundColor(string $a_value): void
111  {
112  $this->bg_color = $a_value;
113  }
114 
115  public function getFontColor(): string
116  {
117  if (!$this->font_color) {
118  $this->font_color = "505050";
119  }
120  return $this->font_color;
121  }
122 
123  public function setFontColor(string $a_value): void
124  {
125  $this->font_color = $a_value;
126  }
127 
131  public function getImage(): string
132  {
133  return $this->img;
134  }
135 
139  public function setImage(string $a_value): void
140  {
141  $this->img = $a_value;
142  }
143 
144  //
145  // CRUD
146  //
147 
148  protected function doRead(): void
149  {
150  $ilDB = $this->db;
151 
152  $set = $ilDB->query("SELECT * FROM usr_portfolio" .
153  " WHERE id = " . $ilDB->quote($this->id, "integer"));
154  $row = $ilDB->fetchAssoc($set);
155 
156  $this->setOnline((bool) $row["is_online"]);
157  $this->setProfilePicture((bool) $row["ppic"]);
158  $this->setBackgroundColor((string) $row["bg_color"]);
159  $this->setFontColor((string) $row["font_color"]);
160  $this->setImage((string) $row["img"]);
161 
162  // #14661
163  $this->setPublicComments($this->notes->domain()->commentsActive($this->id));
164 
165  $this->doReadCustom($row);
166  }
167 
171  protected function doReadCustom(array $a_row): void
172  {
173  }
174 
175  protected function doCreate(bool $clone_mode = false): void
176  {
177  $ilDB = $this->db;
178 
179  $ilDB->manipulate("INSERT INTO usr_portfolio (id,is_online)" .
180  " VALUES (" . $ilDB->quote($this->id, "integer") . "," .
181  $ilDB->quote(0, "integer") . ")");
182  }
183 
184  protected function doUpdate(): void
185  {
186  $ilDB = $this->db;
187 
188  $fields = array(
189  "is_online" => array("integer", $this->isOnline()),
190  "ppic" => array("integer", $this->hasProfilePicture()),
191  "bg_color" => array("text", $this->getBackgroundColor()),
192  "font_color" => array("text", $this->getFontColor()),
193  "img" => array("text", $this->getImage())
194  );
195  $this->doUpdateCustom($fields);
196 
197  // #14661
198  $this->notes->domain()->activateComments($this->id, $this->hasPublicComments());
199 
200  $ilDB->update(
201  "usr_portfolio",
202  $fields,
203  array("id" => array("integer", $this->id))
204  );
205  }
206 
210  protected function doUpdateCustom(array &$a_fields): void
211  {
212  }
213 
214  protected function doDelete(): void
215  {
216  $ilDB = $this->db;
217 
218  $this->deleteAllPages();
219  $this->deleteImage();
220 
221  $ilDB->manipulate("DELETE FROM usr_portfolio" .
222  " WHERE id = " . $ilDB->quote($this->id, "integer"));
223  }
224 
225  abstract protected function deleteAllPages(): void;
226 
227 
228  //
229  // IMAGES
230  //
231 
235  public function getImageFullPath(
236  bool $a_as_thumb = false
237  ): string {
238  if ($this->img) {
239  $path = self::initStorage($this->id);
240  if (!$a_as_thumb) {
241  return $path . $this->img;
242  }
243 
244  return $path . "thb_" . $this->img;
245  }
246  return "";
247  }
248 
252  public function deleteImage(): void
253  {
254  if ($this->id) {
255  $storage = new ilFSStoragePortfolio($this->id);
256  $storage->delete();
257 
258  $this->setImage("");
259  }
260  }
261 
265  public static function initStorage(
266  int $a_id,
267  string $a_subdir = null
268  ): string {
269  $storage = new ilFSStoragePortfolio($a_id);
270  $storage->create();
271 
272  $path = $storage->getAbsolutePath() . "/";
273 
274  if ($a_subdir) {
275  $path .= $a_subdir . "/";
276 
277  if (!is_dir($path) && !mkdir($path) && !is_dir($path)) {
278  throw new \RuntimeException(sprintf('Directory "%s" was not created', $path));
279  }
280  }
281 
282  return $path;
283  }
284 
288  public function uploadImage(
289  array $a_upload
290  ): bool {
291  if (!$this->id) {
292  return false;
293  }
294 
295  $this->deleteImage();
296 
297  // #10074
298  $clean_name = preg_replace("/[^a-zA-Z0-9\_\.\-]/", "", $a_upload["name"]);
299 
300  $path = self::initStorage($this->id);
301  $original = "org_" . $this->id . "_" . $clean_name;
302  $thumb = "thb_" . $this->id . "_" . $clean_name;
303  $processed = $this->id . "_" . $clean_name;
304 
305  if (ilFileUtils::moveUploadedFile($a_upload["tmp_name"], $original, $path . $original)) {
306  chmod($path . $original, 0770);
307 
308  $prfa_set = new ilSetting("prfa");
309  /* as banner height should overflow, we only handle width
310  $dimensions = $prfa_set->get("banner_width")."x".
311  $prfa_set->get("banner_height");
312  */
313  $dimensions = $prfa_set->get("banner_width");
314 
315  // take quality 100 to avoid jpeg artefacts when uploading jpeg files
316  // taking only frame [0] to avoid problems with animated gifs
317  $original_file = ilShellUtil::escapeShellArg($path . $original);
318  $thumb_file = ilShellUtil::escapeShellArg($path . $thumb);
319  $processed_file = ilShellUtil::escapeShellArg($path . $processed);
320  ilShellUtil::execConvert($original_file . "[0] -geometry 100x100 -quality 100 JPEG:" . $thumb_file);
322  $original_file . "[0] -geometry " . $dimensions . " -quality 100 JPEG:" . $processed_file
323  );
324 
325  $this->setImage($processed);
326 
327  return true;
328  }
329  return false;
330  }
331 
332 
333  //
334  // TRANSMOGRIFIER
335  //
336 
343  protected static function cloneBasics(
344  ilObjPortfolioBase $a_source,
345  ilObjPortfolioBase $a_target
346  ): void {
347  global $DIC;
348 
349  // copy portfolio properties
350  $a_target->setPublicComments($a_source->hasPublicComments());
351  $a_target->setProfilePicture($a_source->hasProfilePicture());
352  $a_target->setFontColor($a_source->getFontColor());
353  $a_target->setBackgroundColor($a_source->getBackgroundColor());
354  $a_target->setImage($a_source->getImage());
355  $a_target->update();
356 
357  // banner/images
358  $source_dir = $a_source->initStorage($a_source->getId());
359  $target_dir = $a_target->initStorage($a_target->getId());
360  ilFSStoragePortfolio::_copyDirectory($source_dir, $target_dir);
361 
362  // container settings
363  foreach (ilContainer::_getContainerSettings($a_source->getId()) as $keyword => $value) {
364  ilContainer::_writeContainerSetting($a_target->getId(), $keyword, $value);
365  }
366 
367  // style
368  $content_style_domain = $DIC
369  ->contentStyle()
370  ->domain()
371  ->styleForObjId($a_source->getId());
372  $content_style_domain->cloneTo($a_target->getId());
373  }
374 
378  public static function clonePagesAndSettings(
379  ilObjPortfolioBase $a_source,
380  ilObjPortfolioBase $a_target,
381  ?array $a_recipe = null,
382  bool $copy_all = false
383  ): void {
384  global $DIC;
385 
386  $lng = $DIC->language();
387  $ilUser = $DIC->user();
388 
389  $source_id = $a_source->getId();
390  $target_id = $a_target->getId();
391 
392  if ($a_source instanceof ilObjPortfolioTemplate &&
393  $a_target instanceof ilObjPortfolio) {
394  $direction = "t2p";
395  } elseif ($a_source instanceof ilObjPortfolio &&
396  $a_target instanceof ilObjPortfolioTemplate) {
397  $direction = "p2t";
398  } else {
399  return;
400  }
401 
402  self::cloneBasics($a_source, $a_target);
403 
404  // copy advanced metadata
406  ilAdvancedMDValues::_cloneValues($copy_id, $a_source->getId(), $a_target->getId());
407 
408  // copy selection of global optional sets
410  $a_target->getId(),
411  'pfpg',
412  ilAdvancedMDRecord::getObjRecSelection($a_source->getId(), 'pfpg')
413  );
414 
415  // fix metadata record type assignment
416  // e.g. if portfolio is created from template
417  // we need to change this from prtt to prtf
419  ilObject::_lookupType($a_source->getId()),
420  $a_target->getId(),
421  "pfpg",
422  false
423  ) as $rec) {
424  /*
425  * BT 35494: reset assignement of the newly cloned local records,
426  * and only append what's needed to global ones
427  */
428  $target_type = ilObject::_lookupType($a_target->getId());
429  if ($rec->getParentObject() == $a_target->getId()) {
430  $rec->setAssignedObjectTypes(
431  [[
432  "obj_type" => $target_type,
433  "sub_type" => "pfpg",
434  "optional" => 0
435  ]
436  ]
437  );
438  } elseif (!$rec->isAssignedObjectType($target_type, 'pfpg')) {
439  $rec->appendAssignedObjectType(
440  $target_type,
441  "pfpg"
442  );
443  }
444  $rec->update();
445  }
446 
447  // personal skills
448  $pskills = array_keys(ilPersonalSkill::getSelectedUserSkills($ilUser->getId()));
449 
450  // copy pages
451  $blog_count = 0;
452  $page_map = array();
453  foreach (ilPortfolioPage::getAllPortfolioPages($source_id) as $page) {
454  $page_id = $page["id"];
455 
456  if ($direction === "t2p") {
457  $source_page = new ilPortfolioTemplatePage($page_id);
458  $target_page = new ilPortfolioPage();
459  } else {
460  $source_page = new ilPortfolioPage($page_id);
461  $target_page = new ilPortfolioTemplatePage();
462  }
463  $source_page->setPortfolioId($source_id);
464  $target_page->setPortfolioId($target_id);
465 
466  $page_type = $source_page->getType();
467  $page_title = $source_page->getTitle();
468 
469 
470 
471 
472  $page_recipe = null;
473  if (isset($a_recipe)) {
474  $page_recipe = $a_recipe[$page_id] ?? null;
475  }
476 
477  $valid = false;
478  switch ($page_type) {
479  // blog => blog template
481  if ($direction === "p2t") {
483  $page_title = $lng->txt("obj_blog") . " " . (++$blog_count);
484  $valid = true;
485  }
486  break;
487 
488  // blog template => blog (needs recipe)
490  if ($direction === "t2p" && (is_array($page_recipe) || $copy_all)) {
491  $page_type = ilPortfolioPage::TYPE_BLOG;
492  if ($copy_all) {
493  $page_title = self::createBlogInPersonalWorkspace($page_title);
494  $valid = true;
495  } elseif ($page_recipe[0] == "blog") {
496  switch ($page_recipe[1]) {
497  case "create":
498  $page_title = self::createBlogInPersonalWorkspace($page_recipe[2]);
499  $valid = true;
500  break;
501 
502  case "reuse":
503  $page_title = $page_recipe[2];
504  $valid = true;
505  break;
506 
507  case "ignore":
508  // do nothing
509  break;
510  }
511  }
512  }
513  break;
514 
515  // page editor
516  default:
517  $target_page->setXMLContent(
518  $source_page->copyXmlContent(
519  true,
520  $a_target->getId(),
521  $copy_id
522  )
523  );
524  $target_page->buildDom(true);
525 
526  // parse content / blocks
527 
528  if ($direction === "t2p") {
529  $dom = $target_page->getDom();
530  if ($dom instanceof php4DOMDocument) {
531  $dom = $dom->myDOMDocument;
532  }
533 
534  // update profile/consultation hours user id
535  self::updateDomNodes($dom, "//PageContent/Profile", "User", $ilUser->getId());
536  self::updateDomNodes($dom, "//PageContent/ConsultationHours", "User", $ilUser->getId());
537  self::updateDomNodes($dom, "//PageContent/MyCourses", "User", $ilUser->getId());
538 
539  // skills
540  $xpath = new DOMXPath($dom);
541  $nodes = $xpath->query("//PageContent/Skills");
542  foreach ($nodes as $node) {
543  $skill_id = $node->getAttribute("Id");
544 
545  // existing personal skills
546  if (in_array($skill_id, $pskills)) {
547  $node->setAttribute("User", $ilUser->getId());
548  }
549  // new skill
550  elseif ($copy_all || in_array($skill_id, $a_recipe["skills"])) {
551  ilPersonalSkill::addPersonalSkill($ilUser->getId(), $skill_id);
552 
553  $node->setAttribute("User", $ilUser->getId());
554  }
555  // remove skill
556  else {
557  $page_element = $node->parentNode;
558  $page_element->parentNode->removeChild($page_element);
559  }
560  }
561  }
562 
563  $valid = true;
564  break;
565  }
566 
567  if ($valid) {
568  // #12038 - update xml from dom
569  $target_page->setXMLContent($target_page->getXMLFromDom());
570 
571  $target_page->setType($page_type);
572  $target_page->setTitle($page_title);
573  $target_page->create(false);
574 
575  if ($page_type === ilPortfolioPage::TYPE_PAGE) {
576  $target_page->update(); // handle mob usages!
577  }
578  $page_map[$source_page->getId()] = $target_page->getId();
579  }
580  }
581  ilPortfolioPage::updateInternalLinks($page_map, $a_target);
582  }
583 
584  protected static function updateDomNodes(
585  DOMDocument $a_dom,
586  string $a_xpath,
587  string $a_attr_id,
588  string $a_attr_value
589  ): void {
590  $xpath_temp = new DOMXPath($a_dom);
591  $nodes = $xpath_temp->query($a_xpath);
592  foreach ($nodes as $node) {
593  $node->setAttribute($a_attr_id, $a_attr_value);
594  }
595  }
596 
597  protected static function createBlogInPersonalWorkspace(string $a_title): int
598  {
599  global $DIC;
600 
601  $ilUser = $DIC->user();
602 
603  static $ws_access = null;
604 
605  $blog = new ilObjBlog();
606  $blog->setType("blog");
607  $blog->setTitle($a_title);
608  $blog->create();
609 
610  if (!$ws_access) {
611  $tree = new ilWorkspaceTree($ilUser->getId());
612 
613  // #13235
614  if (!$tree->getRootId()) {
615  $tree->createTreeForUser($ilUser->getId());
616  }
617 
618  $ws_access = new ilWorkspaceAccessHandler($tree);
619  }
620 
621  $tree = $ws_access->getTree();
622  $node_id = $tree->insertObject($tree->getRootId(), $blog->getId());
623  $ws_access->setPermissions($tree->getRootId(), $node_id);
624 
625  return $blog->getId();
626  }
627 
631  public function fixLinksOnTitleChange(array $a_title_changes): void
632  {
633  foreach (ilPortfolioPage::getAllPortfolioPages($this->getId()) as $port_page) {
634  if ($this->getType() === "prtt") {
635  $page = new ilPortfolioTemplatePage($port_page["id"]);
636  } else {
637  $page = new ilPortfolioPage($port_page["id"]);
638  }
639  if ($page->renameLinksOnTitleChange($a_title_changes)) {
640  $page->update(true, true);
641  }
642  }
643  }
644 }
static getAllPortfolioPages(int $a_portfolio_id)
Get pages of portfolio.
setProfilePicture(bool $a_status)
ILIAS Notes Service $notes
$target_type
Definition: goto.php:51
txt(string $a_topic, string $a_default_lang_fallback_mod="")
gets the text for a given topic if the topic is not in the list, the topic itself with "-" will be re...
deleteImage()
remove existing file
static initStorage(int $a_id, string $a_subdir=null)
Init file system storage.
$valid
ilTree $tree
static saveObjRecSelection(int $a_obj_id, string $a_sub_type="", array $a_records=null, bool $a_delete_before=true)
Save repository object record selection.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$target_id
Definition: goto.php:52
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static createBlogInPersonalWorkspace(string $a_title)
static _getSelectedRecordsByObject(string $a_obj_type, int $a_id, string $a_sub_type="", bool $is_ref_id=true)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static escapeShellArg(string $a_arg)
setBackgroundColor(string $a_value)
Set background color, e.g.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$path
Definition: ltiservices.php:32
setImage(string $a_value)
Set banner image.
static cloneBasics(ilObjPortfolioBase $a_source, ilObjPortfolioBase $a_target)
Clone basic settings.
global $DIC
Definition: feed.php:28
static getObjRecSelection(int $a_obj_id, string $a_sub_type="")
Get repository object record selection.
uploadImage(array $a_upload)
Upload new image file.
static clonePagesAndSettings(ilObjPortfolioBase $a_source, ilObjPortfolioBase $a_target, ?array $a_recipe=null, bool $copy_all=false)
Build template from portfolio and vice versa.
static lookupOnline(int $a_id)
ilLanguage $lng
static updateInternalLinks(array $a_copied_nodes, ilObjPortfolioBase $a_target_obj)
Update internal links, after multiple pages have been copied.
ilDBInterface $db
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _allocateCopyId()
Allocate a copy for further entries.
static getSelectedUserSkills(int $a_user_id)
static moveUploadedFile(string $a_file, string $a_name, string $a_target, bool $a_raise_errors=true, string $a_mode="move_uploaded")
move uploaded file
static updateDomNodes(DOMDocument $a_dom, string $a_xpath, string $a_attr_id, string $a_attr_value)
__construct(int $a_id=0, bool $a_reference=true)
doReadCustom(array $a_row)
May be overwritten by derived classes.
static _writeContainerSetting(int $a_id, string $a_keyword, string $a_value)
getImage()
Get banner image.
static _cloneValues(int $copy_id, int $a_source_id, int $a_target_id, ?string $a_sub_type=null, ?int $a_source_sub_id=null, ?int $a_target_sub_id=null)
Clone Advanced Meta Data.
static addPersonalSkill(int $a_user_id, int $a_skill_node_id)
__construct(Container $dic, ilPlugin $plugin)
$ilUser
Definition: imgupload.php:34
fixLinksOnTitleChange(array $a_title_changes)
Update internal portfolio links on title change.
doCreate(bool $clone_mode=false)
doUpdateCustom(array &$a_fields)
May be overwritte by derived classes.
getImageFullPath(bool $a_as_thumb=false)
Get banner image incl.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _lookupType(int $id, bool $reference=false)
static _copyDirectory(string $a_sdir, string $a_tdir)
static _getContainerSettings(int $a_id)
static execConvert(string $args)
execute convert command