CWIS Developer Documentation

- Home
- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

Folder.php
Go to the documentation of this file.
1 <?PHP
2 #
3 # FILE: Folder.php
4 #
5 # Part of the Collection Workflow Information System (CWIS)
6 # Copyright 2012-2013 Edward Almasy and Internet Scout Research Group
7 # http://scout.wisc.edu/cwis/
8 #
9
17 class Folder
18 {
19
20 # ---- PUBLIC INTERFACE --------------------------------------------------
21 /*@(*/
23
29 public function __construct($FolderId)
30 {
31 # create our own DB handle
32 $this->DB = new Database();
33
34 # store folder ID
35 $this->Id = intval($FolderId);
36
37 # attempt to load in folder info
38 $this->DB->Query("SELECT * FROM Folders WHERE FolderId = ".$this->Id);
39 $Record = $this->DB->FetchRow();
40
41 # if folder was not found
42 if ($Record === FALSE)
43 {
44 # bail out with exception
45 throw new Exception("Unknown Folder ID (".$FolderId.").");
46 }
47
48 # save folder info
49 $this->OwnerId = $Record["OwnerId"];
50 $this->FolderName = $Record["FolderName"];
51 $this->NormalizedName = $Record["NormalizedName"];
52 $this->FolderNote = $Record["FolderNote"];
53 $this->IsShared = $Record["IsShared"];
54 $this->ContentType = $Record["ContentType"];
55 $this->UpdateValueCache = $Record;
56
57 # load list of resources in folder from database
58 $this->DB->Query("SELECT ItemId, ItemTypeId, ItemNote FROM FolderItemInts"
59 ." WHERE FolderId = ".$this->Id);
60
61 # create internal cache for item notes
62 $this->ItemNoteCache = array();
63 while ($Record = $this->DB->FetchRow())
64 {
65 $Index = self::GetCacheIndex($Record["ItemId"], $Record["ItemTypeId"]);
66 $this->ItemNoteCache[$Index] = $Record["ItemNote"];
67 }
68
69 # load item ordering
70 if ($this->ContentType == self::MIXEDCONTENT)
71 {
72 $this->OrderList = new PersistentDoublyLinkedList(
73 "FolderItemInts", "ItemId", "FolderId = ".$this->Id, "ItemTypeId");
74 }
75 else
76 {
77 $this->OrderList = new PersistentDoublyLinkedList(
78 "FolderItemInts", "ItemId", "FolderId = ".$this->Id);
79 }
80
81 # be sure that a NormalizedName is set
82 $this->NormalizedName();
83 }
84
88 public function Delete()
89 {
90 # take folder out of global folder order
91 $Factory = new FolderFactory();
92 $Factory->RemoveItemFromOrder($this->Id);
93
94 # remove resource listings from DB
95 $this->DB->Query("DELETE FROM FolderItemInts WHERE FolderId = ".$this->Id);
96
97 # remove folder listing from DB
98 $this->DB->Query("DELETE FROM Folders WHERE FolderId = ".$this->Id);
99 }
100
101 /*@)*/ /* Setup/Initialization */
102 # ------------------------------------------------------------------------
103 /*@(*/
104
109 public function Id()
110 {
111 return $this->Id;
112 }
113
120 public function Name($NewValue = DB_NOVALUE)
121 {
122 if ($NewValue != DB_NOVALUE)
123 {
124 $this->NormalizedName(self::NormalizeFolderName($NewValue));
125 }
126 return $this->UpdateValue("FolderName", $NewValue);
127 }
128
136 public function NormalizedName($NewValue = DB_NOVALUE)
137 {
138 $Name = $this->UpdateValue("NormalizedName", $NewValue);
139 # attempt to generate and set new normalized name if none found
140 if (!strlen($Name))
141 {
142 $Name = $this->UpdateValue("NormalizedName",
143 self::NormalizeFolderName($this->Name()));
144 }
145 return $Name;
146 }
147
153 public static function NormalizeFolderName($Name)
154 {
155 return preg_replace("/[^a-z0-9]/", "", strtolower($Name));
156 }
157
164 public function IsShared($NewValue = DB_NOVALUE)
165 {
166 return $this->UpdateValue("IsShared", $NewValue);
167 }
168
174 public function OwnerId($NewValue = DB_NOVALUE)
175 {
176 if ($NewValue !== DB_NOVALUE) { unset($this->OwnerId); }
177 return intval($this->UpdateValue("OwnerId", $NewValue));
178 }
179
185 public function Note($NewValue = DB_NOVALUE)
186 {
187 return $this->UpdateValue("FolderNote", $NewValue);
188 }
189
190 /*@)*/ /* Attribute Setting/Retrieval */
191 # ------------------------------------------------------------------------
192 /*@(*/
193
206 public function InsertItemBefore($TargetItemOrItemId, $NewItemOrItemId,
207 $TargetItemType = NULL, $NewItemType = NULL)
208 {
209 $this->AddItem($NewItemOrItemId, $NewItemType);
210 $this->OrderList->InsertBefore($TargetItemOrItemId, $NewItemOrItemId,
211 self::GetItemTypeId($TargetItemType),
212 self::GetItemTypeId($NewItemType));
213 }
214
226 public function InsertItemAfter($TargetItemOrItemId, $NewItemOrItemId,
227 $TargetItemType = NULL, $NewItemType = NULL)
228 {
229 $this->AddItem($NewItemOrItemId, $NewItemType);
230 $this->OrderList->InsertAfter($TargetItemOrItemId, $NewItemOrItemId,
231 self::GetItemTypeId($TargetItemType),
232 self::GetItemTypeId($NewItemType));
233 }
234
242 public function PrependItem($ItemOrItemId, $ItemType = NULL)
243 {
244 $this->AddItem($ItemOrItemId, $ItemType);
245 $this->OrderList->Prepend($ItemOrItemId, self::GetItemTypeId($ItemType));
246 }
247
255 public function AppendItem($ItemOrItemId, $ItemType = NULL)
256 {
257 $this->AddItem($ItemOrItemId, $ItemType);
258 $this->OrderList->Append($ItemOrItemId, self::GetItemTypeId($ItemType));
259 }
260
267 public function AppendItems($ItemsOrItemIds, $ItemTypes = NULL)
268 {
269 # convert ItemTypes to an array if it wasn't one
270 if (!is_array($ItemTypes))
271 {
272 $NewItemTypes = array();
273 foreach ($ItemsOrItemIds as $Id)
274 {
275 $NewItemTypes[] = $ItemTypes;
276 }
277 $ItemTypes = $NewItemTypes;
278 }
279
280 # get items ids
281 $ItemIds = array();
282 foreach ($ItemsOrItemIds as $ItemOrId)
283 {
284 $ItemIds[] = is_object($ItemOrId) ? $ItemOrId->Id() : $ItemOrId;
285 }
286
287 # add all the itmes to our folder
288 foreach ($ItemIds as $Index => $ItemId)
289 {
290 $this->AddItem($ItemId, $ItemTypes[$Index]);
291 }
292
293 # and add them to our ordering list
294 if ($this->ContentType == self::MIXEDCONTENT)
295 {
296 $ItemTypeIds = array();
297 foreach ($ItemTypes as $ItemType)
298 {
299 $ItemTypeIds[] = self::GetItemTypeId($ItemType);
300 }
301
302 $this->OrderList->Append($ItemIds, $ItemTypeIds);
303 }
304 else
305 {
306 $this->OrderList->Append($ItemIds);
307 }
308 }
309
322 public function GetItemIds($Offset = NULL, $Length = NULL)
323 {
324 # retrieve item ordered list of type IDs
325 $ItemIds = $this->OrderList->GetIds();
326
327 # if this is a mixed-item-type folder
328 if ($this->ContentType == self::MIXEDCONTENT)
329 {
330 # convert item type IDs to corresponding type names
331 $NewItemIds = array();
332 foreach ($ItemIds as $ItemInfo)
333 {
334 $NewItemIds[] = array(
335 "ID" => $ItemInfo["ID"],
336 "Type" => self::GetItemTypeName($ItemInfo["Type"]),
337 );
338 }
339 $ItemIds = $NewItemIds;
340 }
341
342 # prune results to subset if requested
343 if ($Offset !== NULL)
344 {
345 if ($Length !== NULL)
346 {
347 $ItemIds = array_slice($ItemIds, $Offset, $Length);
348 }
349 else
350 {
351 $ItemIds = array_slice($ItemIds, $Offset);
352 }
353 }
354
355 # return list of item type IDs (and possibly types) to caller
356 return $ItemIds;
357 }
358
365 public function GetItemCount()
366 {
367 return $this->OrderList->GetCount();
368 }
369
376 public function RemoveItem($ItemId, $ItemType = NULL)
377 {
378 # if resource is in folder
379 if ($this->ContainsItem($ItemId, $ItemType))
380 {
381 # remove item from item order
382 $ItemTypeId = self::GetItemTypeId($ItemType);
383 $this->OrderList->Remove($ItemId, $ItemTypeId);
384
385 # remove resource from folder locally
386 unset($this->ItemNoteCache[self::GetCacheIndex($ItemId, $ItemTypeId)]);
387
388 # remove resource from folder in DB
389 $this->DB->Query("DELETE FROM FolderItemInts"
390 ." WHERE FolderId = ".intval($this->Id)
391 ." AND ItemId = ".intval($ItemId)
392 ." AND ItemTypeId = "
393 .($ItemTypeId === NULL ? -1 : intval($ItemTypeId)));
394 }
395 }
396
404 public function NoteForItem($ItemId, $NewValue = DB_NOVALUE, $ItemType = NULL)
405 {
406 $ItemTypeId = self::GetItemTypeId($ItemType);
407 $Index = self::GetCacheIndex($ItemId, $ItemTypeId);
408 $DummyCache = array("ItemNote" => $this->ItemNoteCache[$Index]);
409
410 $Value = $this->DB->UpdateValue("FolderItemInts", "ItemNote", $NewValue,
411 "FolderId = ".intval($this->Id)
412 ." AND ItemId = ".intval($ItemId)
413 ." AND ItemTypeId = "
414 .($ItemTypeId === NULL ? -1 : intval($ItemTypeId)),
415 $DummyCache);
416
417 $this->ItemNoteCache[self::GetCacheIndex($ItemId, $ItemTypeId)] = $Value;
418
419 return $Value;
420 }
421
429 public function ContainsItem($ItemId, $ItemType = NULL)
430 {
431 $ItemTypeId = self::GetItemTypeId($ItemType);
432 return array_key_exists(self::GetCacheIndex($ItemId, $ItemTypeId),
433 $this->ItemNoteCache) ? TRUE : FALSE;
434 }
435
436 /*@)*/ /* Item Operations */
437
438 # ---- PRIVATE INTERFACE -------------------------------------------------
439
440 private $DB;
441 private $Id;
442
443 # folder attributes - these much match field names in Folders DB table
444 private $OwnerId;
445 private $FolderName;
446 private $NormalizedName;
447 private $FolderNote;
448 private $IsShared;
449 private $ContentType;
450
451 private $ItemNoteCache;
452 private $OrderList;
453 private $UpdateValueCache;
454
455 # item type IDs (indexed by normalized type name)
456 static private $ItemTypeIds;
457 # item type names (indexed by type ID)
458 static private $ItemTypeNames;
459
460 # content type that indicates folder contains mixed content types
461 const MIXEDCONTENT = -1;
462
470 public static function GetItemTypeId($TypeName)
471 {
472 # return NULL if TypeName is NULL.
473 if ($TypeName === NULL) { return NULL; }
474
475 # make sure item type map is loaded
476 self::LoadItemTypeMap();
477
478 # normalize item type name
479 $NormalizedTypeName = strtoupper(
480 preg_replace("/[^a-zA-Z0-9]/", "", $TypeName));
481
482 # if name not already mapped
483 if (!array_key_exists($NormalizedTypeName, self::$ItemTypeIds))
484 {
485 # add name to database
486 static $DB;
487 if (!isset($DB)) { $DB = new Database(); }
488 $DB->Query("INSERT INTO FolderContentTypes SET"
489 ." TypeName = '".addslashes($TypeName)."',"
490 ." NormalizedTypeName = '".addslashes($NormalizedTypeName)."'");
491
492 # add name to cached mappings
493 $NewTypeId = $DB->LastInsertId();
494 self::$ItemTypeIds[$NormalizedTypeName] = $NewTypeId;
495 self::$ItemTypeNames[$NewTypeId] = $TypeName;
496 }
497
498 # return item type ID to caller
499 return self::$ItemTypeIds[$NormalizedTypeName];
500 }
508 private static function GetItemTypeName($TypeId)
509 {
510 # make sure item type map is loaded
511 self::LoadItemTypeMap();
512
513 # if ID not present in mappings
514 if (!array_key_exists($TypeId, self::$ItemTypeNames))
515 {
516 # return null value
517 return NULL;
518 }
519 else
520 {
521 # return item type name to caller
522 return self::$ItemTypeNames[$TypeId];
523 }
524 }
525
530 private static function LoadItemTypeMap()
531 {
532 # if name-to-number item type map not already loaded
533 if (!isset(self::$ItemTypeIds))
534 {
535 # load item type map from database
536 $DB = new Database();
537 $DB->Query("SELECT * FROM FolderContentTypes");
538 self::$ItemTypeIds = array();
539 self::$ItemTypeNames = array();
540 while ($Row = $DB->FetchRow())
541 {
542 self::$ItemTypeIds[$Row["NormalizedTypeName"]] = $Row["TypeId"];
543 self::$ItemTypeNames[$Row["TypeId"]] = $Row["TypeName"];
544 }
545 }
546 }
547
553 private function AddItem($ItemOrItemId, $ItemType)
554 {
555 # convert item to ID if necessary
556 $ItemId = is_object($ItemOrItemId)
557 ? $ItemOrItemId->Id() : $ItemOrItemId;
558
559 # convert item type to item type ID
560 $ItemTypeId = self::GetItemTypeId($ItemType);
561
562 # convert null item type to "no type" value used in database
563 if ($ItemTypeId === NULL) { $ItemTypeId = -1; }
564
565 # if resource is not already in folder
566 if (!$this->ContainsItem($ItemId, $ItemType))
567 {
568 # add resource to folder locally
569 $this->ItemNoteCache[self::GetCacheIndex($ItemId, $ItemTypeId)] = NULL;
570
571 # add resource to folder in DB
572 $this->DB->Query("INSERT INTO FolderItemInts SET"
573 ." FolderId = ".intval($this->Id)
574 .", ItemId = ".intval($ItemId)
575 .", ItemTypeId = "
576 .($ItemTypeId === NULL ? -1 : intval($ItemTypeId)));
577 }
578 }
579
586 private static function GetCacheIndex($ItemId, $ItemTypeId)
587 {
588 $ItemTypeId = ($ItemTypeId === NULL) ? -1 : $ItemTypeId;
589 return intval($ItemTypeId).":".intval($ItemId);
590 }
591
599 private function UpdateValue($FieldName, $NewValue)
600 {
601 $this->$FieldName = $this->DB->UpdateValue("Folders", $FieldName, $NewValue,
602 "FolderId = ".$this->Id, $this->UpdateValueCache);
603 return $this->$FieldName;
604 }
605 }
Folder\NormalizedName
NormalizedName($NewValue=DB_NOVALUE)
Get/set normalized version of folder name.
Definition: Folder.php:136
Folder\MIXEDCONTENT
const MIXEDCONTENT
Definition: Folder.php:461
Folder\AppendItem
AppendItem($ItemOrItemId, $ItemType=NULL)
Add item to folder as the last item.
Definition: Folder.php:255
Folder\NoteForItem
NoteForItem($ItemId, $NewValue=DB_NOVALUE, $ItemType=NULL)
Get/set note text for specific item within folder.
Definition: Folder.php:404
Folder\Id
Id()
Get folder ID.
Definition: Folder.php:109
Database
SQL database abstraction object with smart query caching.
Definition: Database.php:22
Folder\IsShared
IsShared($NewValue=DB_NOVALUE)
Get/set whether folder is publically-viewable.
Definition: Folder.php:164
FolderFactory
Factory object for Folder class, used to retrieve and manage Folders and groups of Folders...
Definition: FolderFactory.php:14
Folder
Folder object used to create and manage groups of items.
Definition: Folder.php:17
Folder\RemoveItem
RemoveItem($ItemId, $ItemType=NULL)
Remove item from folder, if present.
Definition: Folder.php:376
Folder\NormalizeFolderName
static NormalizeFolderName($Name)
Convert folder name to normalized form (lower-case alphanumeric only).
Definition: Folder.php:153
PHP
PHP
Definition: RSSClient--Test.php:12
Folder\InsertItemAfter
InsertItemAfter($TargetItemOrItemId, $NewItemOrItemId, $TargetItemType=NULL, $NewItemType=NULL)
Insert item into folder after specified item.
Definition: Folder.php:226
Folder\Note
Note($NewValue=DB_NOVALUE)
Get/set note text for folder.
Definition: Folder.php:185
DB_NOVALUE
const DB_NOVALUE
Definition: Database.php:1738
Folder\GetItemCount
GetItemCount()
Get number of items in folder.
Definition: Folder.php:365
Folder\AppendItems
AppendItems($ItemsOrItemIds, $ItemTypes=NULL)
Add multiple items to the folder at the end.
Definition: Folder.php:267
Folder\GetItemTypeId
static GetItemTypeId($TypeName)
Definition: Folder.php:470
Folder\ContainsItem
ContainsItem($ItemId, $ItemType=NULL)
Check whether specified item is contained in folder.
Definition: Folder.php:429
Folder\InsertItemBefore
InsertItemBefore($TargetItemOrItemId, $NewItemOrItemId, $TargetItemType=NULL, $NewItemType=NULL)
Insert item into folder before specified item.
Definition: Folder.php:206
PersistentDoublyLinkedList
Persistent doubly-linked-list data structure, with its data stored in a specified database table...
Definition: PersistentDoublyLinkedList.php:21
Folder\OwnerId
OwnerId($NewValue=DB_NOVALUE)
Get/set user ID of folder owner.
Definition: Folder.php:174
Folder\Delete
Delete()
Delete folder.
Definition: Folder.php:88
Folder\__construct
__construct($FolderId)
Object constructor – load an existing folder.
Definition: Folder.php:29
Folder\PrependItem
PrependItem($ItemOrItemId, $ItemType=NULL)
Add item to folder as the first item.
Definition: Folder.php:242
Folder\GetItemIds
GetItemIds($Offset=NULL, $Length=NULL)
Retrieve array of IDs of items in folder, in the order that they appear in the folder.
Definition: Folder.php:322
Folder\Name
Name($NewValue=DB_NOVALUE)
Get/set folder name.
Definition: Folder.php:120