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 # ---- PUBLIC INTERFACE --------------------------------------------------
20 /*@(*/
22
28 function Folder($FolderId)
29 {
30 # create our own DB handle
31 $this->DB = new Database();
32
33 # store folder ID
34 $this->Id = intval($FolderId);
35
36 # attempt to load in folder info
37 $this->DB->Query("SELECT * FROM Folders WHERE FolderId = ".$this->Id);
38 $Record = $this->DB->FetchRow();
39
40 # if folder was not found
41 if ($Record === FALSE)
42 {
43 # bail out with exception
44 throw new Exception("Unknown Folder ID (".$FolderId.").");
45 }
46
47 # save folder info
48 $this->OwnerId = $Record["OwnerId"];
49 $this->FolderName = $Record["FolderName"];
50 $this->NormalizedName = $Record["NormalizedName"];
51 $this->FolderNote = $Record["FolderNote"];
52 $this->IsShared = $Record["IsShared"];
53 $this->ContentType = $Record["ContentType"];
54 $this->UpdateValueCache = $Record;
55
56 # load list of resources in folder from database
57 $this->DB->Query("SELECT ItemId, ItemTypeId, ItemNote FROM FolderItemInts"
58 ." WHERE FolderId = ".$this->Id);
59
60 # create internal cache for item notes
61 $this->ItemNoteCache = array();
62 while ($Record = $this->DB->FetchRow())
63 {
64 $Index = self::GetCacheIndex($Record["ItemId"], $Record["ItemTypeId"]);
65 $this->ItemNoteCache[$Index] = $Record["ItemNote"];
66 }
67
68 # load item ordering
69 if ($this->ContentType == self::MIXEDCONTENT)
70 {
71 $this->OrderList = new PersistentDoublyLinkedList(
72 "FolderItemInts", "ItemId", "FolderId = ".$this->Id, "ItemTypeId");
73 }
74 else
75 {
76 $this->OrderList = new PersistentDoublyLinkedList(
77 "FolderItemInts", "ItemId", "FolderId = ".$this->Id);
78 }
79 }
80
84 function Delete()
85 {
86 # take folder out of global folder order
87 $Factory = new FolderFactory();
88 $Factory->RemoveItemFromOrder($this->Id);
89
90 # remove resource listings from DB
91 $this->DB->Query("DELETE FROM FolderItemInts WHERE FolderId = ".$this->Id);
92
93 # remove folder listing from DB
94 $this->DB->Query("DELETE FROM Folders WHERE FolderId = ".$this->Id);
95 }
96
97 /*@)*/ /* Setup/Initialization */
98 # ------------------------------------------------------------------------
99 /*@(*/
100
105 function Id()
106 {
107 return $this->Id;
108 }
109
115 function Name($NewValue = DB_NOVALUE)
116 {
117 if ($NewValue != DB_NOVALUE)
118 {
119 $this->NormalizedName(self::NormalizeFolderName($NewValue));
120 }
121 return $this->UpdateValue("FolderName", $NewValue);
122 }
123
131 function NormalizedName($NewValue = DB_NOVALUE)
132 {
133 $Name = $this->UpdateValue("NormalizedName", $NewValue);
134 # attempt to generate and set new normalized name if none found
135 if (!strlen($Name))
136 {
137 $Name = $this->UpdateValue("NormalizedName",
138 self::NormalizeFolderName($this->Name()));
139 }
140 return $Name;
141 }
142
148 static function NormalizeFolderName($Name)
149 {
150 return preg_replace("/[^a-z0-9]/", "", strtolower($Name));
151 }
152
159 function IsShared($NewValue = DB_NOVALUE)
160 {
161 return $this->UpdateValue("IsShared", $NewValue);
162 }
163
169 function OwnerId($NewValue = DB_NOVALUE)
170 {
171 if ($NewValue !== DB_NOVALUE) { unset($this->Owner); }
172 return intval($this->UpdateValue("OwnerId", $NewValue));
173 }
174
180 function Note($NewValue = DB_NOVALUE)
181 {
182 return $this->UpdateValue("FolderNote", $NewValue);
183 }
184
185 /*@)*/ /* Attribute Setting/Retrieval */
186 # ------------------------------------------------------------------------
187 /*@(*/
188
201 function InsertItemBefore($TargetItemOrItemId, $NewItemOrItemId,
202 $TargetItemType = NULL, $NewItemType = NULL)
203 {
204 $this->AddItem($NewItemOrItemId, $NewItemType);
205 $this->OrderList->InsertBefore($TargetItemOrItemId, $NewItemOrItemId,
206 self::GetItemTypeId($TargetItemType),
207 self::GetItemTypeId($NewItemType));
208 }
209
221 function InsertItemAfter($TargetItemOrItemId, $NewItemOrItemId,
222 $TargetItemType = NULL, $NewItemType = NULL)
223 {
224 $this->AddItem($NewItemOrItemId, $NewItemType);
225 $this->OrderList->InsertAfter($TargetItemOrItemId, $NewItemOrItemId,
226 self::GetItemTypeId($TargetItemType),
227 self::GetItemTypeId($NewItemType));
228 }
229
237 function PrependItem($ItemOrItemId, $ItemType = NULL)
238 {
239 $this->AddItem($ItemOrItemId, $ItemType);
240 $this->OrderList->Prepend($ItemOrItemId, self::GetItemTypeId($ItemType));
241 }
242
250 function AppendItem($ItemOrItemId, $ItemType = NULL)
251 {
252 $this->AddItem($ItemOrItemId, $ItemType);
253 $this->OrderList->Append($ItemOrItemId, self::GetItemTypeId($ItemType));
254 }
255
262 function AppendItems($ItemsOrItemIds, $ItemTypes = NULL)
263 {
264 # convert ItemTypes to an array if it wasn't one
265 if (!is_array($ItemTypes))
266 {
267 $NewItemTypes = array();
268 foreach ($ItemsOrItemIds as $Id)
269 {
270 $NewItemTypes[] = $ItemTypes;
271 }
272 $ItemTypes = $NewItemTypes;
273 }
274
275 # get items ids
276 $ItemIds = array();
277 foreach ($ItemsOrItemIds as $ItemOrId)
278 {
279 $ItemIds[] = is_object($ItemOrId) ? $ItemOrId->Id() : $ItemOrId;
280 }
281
282 # add all the itmes to our folder
283 foreach ($ItemIds as $Index => $ItemId)
284 {
285 $this->AddItem( $ItemId, $ItemTypes[ $Index ] );
286 }
287
288 # and add them to our ordering list
289 $this->OrderList->Append($ItemIds, $ItemTypes);
290 }
291
299 function GetItemIds()
300 {
301 # retrieve item ordered list of type IDs
302 $ItemIds = $this->OrderList->GetIds();
303
304 # if this is a mixed-item-type folder
305 if ($this->ContentType == self::MIXEDCONTENT)
306 {
307 # convert item type IDs to corresponding type names
308 $NewItemIds = array();
309 foreach ($ItemIds as $ItemInfo)
310 {
311 $NewItemIds[] = array(
312 "ID" => $ItemInfo["ID"],
313 "Type" => self::GetItemTypeName($ItemInfo["Type"]),
314 );
315 }
316 $ItemIds = $NewItemIds;
317 }
318
319 # return list of item type IDs (and possibly types) to caller
320 return $ItemIds;
321 }
322
329 function GetItemCount()
330 {
331 return $this->OrderList->GetCount();
332 }
333
340 function RemoveItem($ItemId, $ItemType = NULL)
341 {
342 # if resource is in folder
343 if ($this->ContainsItem($ItemId, $ItemType))
344 {
345 # remove item from item order
346 $ItemTypeId = self::GetItemTypeId($ItemType);
347 $this->OrderList->Remove($ItemId, $ItemTypeId);
348
349 # remove resource from folder locally
350 unset($this->ItemNoteCache[self::GetCacheIndex($ItemId, $ItemTypeId)]);
351
352 # remove resource from folder in DB
353 $this->DB->Query("DELETE FROM FolderItemInts"
354 ." WHERE FolderId = ".intval($this->Id)
355 ." AND ItemId = ".intval($ItemId)
356 ." AND ItemTypeId = ".intval($ItemTypeId));
357 }
358 }
359
367 function NoteForItem($ItemId, $NewValue = DB_NOVALUE, $ItemType = NULL)
368 {
369 $ItemTypeId = self::GetItemTypeId($ItemType);
370 $Index = self::GetCacheIndex($ItemId, $ItemTypeId);
371 $DummyCache = array("ItemNote" => $this->ItemNoteCache[$Index]);
372
373 $Value = $this->DB->UpdateValue("FolderItemInts", "ItemNote", $NewValue,
374 "FolderId = ".intval($this->Id)
375 ." AND ItemId = ".intval($ItemId)
376 ." AND ItemTypeId = ".intval($ItemTypeId),
377 $DummyCache);
378
379 $this->ItemNoteCache[self::GetCacheIndex($ItemId, $ItemTypeId)] = $Value;
380
381 return $Value;
382 }
383
390 function ContainsItem($ItemId, $ItemType = NULL)
391 {
392 $ItemTypeId = self::GetItemTypeId($ItemType);
393 return array_key_exists(self::GetCacheIndex($ItemId, $ItemTypeId),
394 $this->ItemNoteCache) ? TRUE : FALSE;
395 }
396
397 /*@)*/ /* Item Operations */
398
399 # ---- PRIVATE INTERFACE -------------------------------------------------
400
401 private $DB;
402 private $Id;
403
404 # folder attributes - these much match field names in Folders DB table
405 private $OwnerId;
406 private $FolderName;
407 private $NormalizedName;
408 private $FolderNote;
409 private $IsShared;
410 private $ContentType;
411
412 private $ItemNoteCache;
413 private $OrderList;
414 private $UpdateValueCache;
415
416 # item type IDs (indexed by normalized type name)
417 static private $ItemTypeIds;
418 # item type names (indexed by type ID)
419 static private $ItemTypeNames;
420
421 # content type that indicates folder contains mixed content types
422 const MIXEDCONTENT = -1;
423
431 static function GetItemTypeId($TypeName)
432 {
433 # return "no type" ID if null passed in
434 if ($TypeName === NULL) { return -1; }
435
436 # make sure item type map is loaded
437 self::LoadItemTypeMap();
438
439 # normalize item type name
440 $NormalizedTypeName = strtoupper(
441 preg_replace("/[^a-zA-Z0-9]/", "", $TypeName));
442
443 # if name not already mapped
444 if (!array_key_exists($NormalizedTypeName, self::$ItemTypeIds))
445 {
446 # add name to database
447 if (!isset($DB)) { $DB = new Database(); }
448 $DB->Query("INSERT INTO FolderContentTypes SET"
449 ." TypeName = '".addslashes($TypeName)."',"
450 ." NormalizedTypeName = '".addslashes($NormalizedTypeName)."'");
451
452 # add name to cached mappings
453 $NewTypeId = $DB->LastInsertId();
454 self::$ItemTypeIds[$NormalizedTypeName] = $NewTypeId;
455 self::$ItemTypeNames[$NewTypeId] = $TypeName;
456 }
457
458 # return item type ID to caller
459 return self::$ItemTypeIds[$NormalizedTypeName];
460 }
468 private static function GetItemTypeName($TypeId)
469 {
470 # make sure item type map is loaded
471 self::LoadItemTypeMap();
472
473 # if ID not present in mappings
474 if (!array_key_exists($TypeId, self::$ItemTypeNames))
475 {
476 # return null value
477 return NULL;
478 }
479 else
480 {
481 # return item type name to caller
482 return self::$ItemTypeNames[$TypeId];
483 }
484 }
485
490 private static function LoadItemTypeMap()
491 {
492 # if name-to-number item type map not already loaded
493 if (!isset(self::$ItemTypeIds))
494 {
495 # load item type map from database
496 $DB = new Database();
497 $DB->Query("SELECT * FROM FolderContentTypes");
498 self::$ItemTypeIds = array();
499 self::$ItemTypeNames = array();
500 while ($Row = $DB->FetchRow())
501 {
502 self::$ItemTypeIds[$Row["NormalizedTypeName"]] = $Row["TypeId"];
503 self::$ItemTypeNames[$Row["TypeId"]] = $Row["TypeName"];
504 }
505 }
506 }
507
513 private function AddItem($ItemOrItemId, $ItemType)
514 {
515 # convert item to ID if necessary
516 $ItemId = is_object($ItemOrItemId)
517 ? $ItemOrItemId->Id() : $ItemOrItemId;
518
519 # convert item type to item type ID
520 $ItemTypeId = self::GetItemTypeId($ItemType);
521
522 # convert null item type to "no type" value used in database
523 if ($ItemTypeId === NULL) { $ItemTypeId = -1; }
524
525 # if resource is not already in folder
526 if (!$this->ContainsItem($ItemId, $ItemType))
527 {
528 # add resource to folder locally
529 $this->ItemNoteCache[self::GetCacheIndex($ItemId, $ItemTypeId)] = NULL;
530
531 # add resource to folder in DB
532 $this->DB->Query("INSERT INTO FolderItemInts SET"
533 ." FolderId = ".intval($this->Id)
534 .", ItemId = ".intval($ItemId)
535 .", ItemTypeId = ".intval($ItemTypeId));
536 }
537 }
538
545 private static function GetCacheIndex($ItemId, $ItemTypeId)
546 {
547 $ItemTypeId = ($ItemTypeId === NULL) ? -1 : $ItemTypeId;
548 return intval($ItemTypeId).":".intval($ItemId);
549 }
550
558 private function UpdateValue($FieldName, $NewValue)
559 {
560 $this->$FieldName = $this->DB->UpdateValue("Folders", $FieldName, $NewValue,
561 "FolderId = ".$this->Id, $this->UpdateValueCache);
562 return $this->$FieldName;
563 }
564 }
Folder\NormalizedName
NormalizedName($NewValue=DB_NOVALUE)
Get/set normalized version of folder name.
Definition: Folder.php:131
Folder\MIXEDCONTENT
const MIXEDCONTENT
Definition: Folder.php:422
Folder\AppendItem
AppendItem($ItemOrItemId, $ItemType=NULL)
Add item to folder as the last item.
Definition: Folder.php:250
Folder\NoteForItem
NoteForItem($ItemId, $NewValue=DB_NOVALUE, $ItemType=NULL)
Get/set note text for specific item within folder.
Definition: Folder.php:367
Folder\Id
Id()
Get folder ID.
Definition: Folder.php:105
Database
SQL database abstraction object with smart query caching.
Definition: Axis--Database.php:22
Folder\IsShared
IsShared($NewValue=DB_NOVALUE)
Get/set whether folder is publically-viewable.
Definition: Folder.php:159
DB_NOVALUE
const DB_NOVALUE
Definition: Axis--Database.php:1331
Folder\GetItemIds
GetItemIds()
Retrieve array of IDs of items in folder, in the order that they appear in the folder.
Definition: Folder.php:299
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:340
Folder\NormalizeFolderName
static NormalizeFolderName($Name)
Convert folder name to normalized form (lower-case alphanumeric only).
Definition: Folder.php:148
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:221
Folder\Note
Note($NewValue=DB_NOVALUE)
Get/set note text for folder.
Definition: Folder.php:180
Folder\GetItemCount
GetItemCount()
Get number of items in folder.
Definition: Folder.php:329
Folder\AppendItems
AppendItems($ItemsOrItemIds, $ItemTypes=NULL)
Add multiple items to the folder at the end.
Definition: Folder.php:262
Folder\GetItemTypeId
static GetItemTypeId($TypeName)
Definition: Folder.php:431
Folder\ContainsItem
ContainsItem($ItemId, $ItemType=NULL)
Check whether specified item is contained in folder.
Definition: Folder.php:390
Folder\Folder
Folder($FolderId)
Object constructor – load an existing folder.
Definition: Folder.php:28
Folder\InsertItemBefore
InsertItemBefore($TargetItemOrItemId, $NewItemOrItemId, $TargetItemType=NULL, $NewItemType=NULL)
Insert item into folder before specified item.
Definition: Folder.php:201
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:169
Folder\Delete
Delete()
Delete folder.
Definition: Folder.php:84
Folder\PrependItem
PrependItem($ItemOrItemId, $ItemType=NULL)
Add item to folder as the first item.
Definition: Folder.php:237
Folder\Name
Name($NewValue=DB_NOVALUE)
Get/set folder name.
Definition: Folder.php:115