CWIS Developer Documentation
SPTRecommender.php
Go to the documentation of this file.
1 <?PHP
2 #
3 # FILE: SPTRecommender.php
4 #
5 # Part of the Collection Workflow Integration System (CWIS)
6 # Copyright 2011-2013 Edward Almasy and Internet Scout Research Group
7 # http://scout.wisc.edu/cwis/
8 #
9 
10 class SPTRecommender extends Recommender {
11 
12  function SPTRecommender()
13  {
14  # set up recommender configuration values for SPT
15  $ItemTableName = "Resources";
16  $ItemIdFieldName = "ResourceId";
17  $RatingTableName = "ResourceRatings";
18  $UserIdFieldName = "UserId";
19  $RatingFieldName = "Rating";
20 
21  # build field info from SPT metadata schema
22  $this->Schema = new MetadataSchema();
23  $Fields = $this->Schema->GetFields();
24  foreach ($Fields as $Field)
25  {
26  if ($Field->Enabled() && $Field->IncludeInKeywordSearch())
27  {
28  $FieldName = $Field->Name();
29  $FieldInfo[$FieldName]["DBFieldName"] = $Field->DBFieldName();
30  $FieldInfo[$FieldName]["Weight"] = $Field->SearchWeight();
31  switch ($Field->Type())
32  {
37  $FieldInfo[$FieldName]["FieldType"] =
39  break;
40 
44  $FieldInfo[$FieldName]["FieldType"] =
46  break;
47 
50  $FieldInfo[$FieldName]["FieldType"] =
52  break;
53 
55  $FieldInfo[$FieldName]["FieldType"] =
56  Recommender::CONTENTFIELDTYPE_DATERANGE;
57  break;
58 
60  $FieldInfo[$FieldName]["FieldType"] =
62  break;
63 
65  # (for images we use their alt text)
66  $FieldInfo[$FieldName]["FieldType"] =
68  break;
69 
71  # (for files we use the file name)
72  $FieldInfo[$FieldName]["FieldType"] =
74  break;
75  }
76  }
77  }
78 
79  # create our own schema object and tell it to cache values
80  $this->Schema = new MetadataSchema();
81  $this->Schema->CacheData(TRUE);
82 
83  # create a database connection for recommender to use
84  $DB = new Database();
85 
86  # pass configuration info to real recommender object
89  $FieldInfo);
90  }
91 
92  # overloaded version of method to retrieve field values from DB
93  function GetFieldValue($ItemId, $FieldName)
94  {
95  static $Resources;
96 
97  # if resource not already loaded
98  if (!isset($Resources[$ItemId]))
99  {
100  # get resource object
101  $Resources[$ItemId] = new Resource($ItemId);
102 
103  # if cached resource limit exceeded
104  if (count($Resources) > 100)
105  {
106  # dump oldest resource
107  reset($Resources);
108  list($DumpedItemId, $DumpedResources) = each($Resources);
109  unset($Resources[$DumpedItemId]);
110  }
111  }
112 
113  # retrieve field value from resource object and return to caller
114  $FieldValue = $Resources[$ItemId]->Get($FieldName);
115  return $FieldValue;
116  }
117 
118  function QueueUpdateForItem($ItemId,
120  {
121  $Item = new Resource($ItemId);
122  $TaskDescription = "Update recommender data for"
123  ." <a href=\"r".$ItemId."\"><i>"
124  .$Item->GetMapped("Title")."</i></a>";
125  $GLOBALS["AF"]->QueueUniqueTask(array(__CLASS__, "RunUpdateForItem"),
126  array(intval($ItemId), 0), $TaskPriority);
127  }
128 
129  static function RunUpdateForItem($SourceItemId, $StartingIndex)
130  {
131  # check that resource still exists
132  $RFactory = new ResourceFactory();
133  if (!$RFactory->ItemExists($SourceItemId)) { return; }
134 
135  # load recommender engine
136  static $Recommender;
137  if (!isset($Recommender)) { $Recommender = new SPTRecommender(); }
138 
139  # if starting update for source item
140  if ($StartingIndex == 0)
141  {
142  # clear data for item
143  $Recommender->DropItem($SourceItemId);
144  }
145 
146  # load array of item IDs
147  $TargetItemIds = $Recommender->GetItemIds();
148  $TargetCount = count($TargetItemIds);
149 
150  # while not last item ID and not out of time
151  for ($Index = $StartingIndex; $Index < $TargetCount; $Index++)
152  {
153  # if target ID points to non-temporary entry
154  if ($TargetItemIds[$Index] >= 0)
155  {
156  # update correlation for source item and current item
157  $StartTime = microtime(TRUE);
158  $Recommender->UpdateContentCorrelation(
159  $SourceItemId, $TargetItemIds[$Index]);
160  $ExecutionTime = microtime(TRUE) - $StartTime;
161 
162  # bail out if out of memory or not enough time for another update
163  if (($GLOBALS["AF"]->GetSecondsBeforeTimeout() < ($ExecutionTime * 2))
164  || ($GLOBALS["AF"]->GetFreeMemory() < 8000000))
165  {
166  break;
167  }
168  }
169  }
170 
171  # if all correlations completed for source item
172  if ($Index >= $TargetCount)
173  {
174  # periodically prune correlations if enough time remaining
175  if (($GLOBALS["AF"]->GetSecondsBeforeTimeout() > 20)
176  && (rand(1, 10) == 1))
177  {
178  $Recommender->PruneCorrelations();
179  }
180  }
181  else
182  {
183  # requeue updates for remaining items
184  $Item = new Resource($SourceItemId);
185  $TaskDescription = "Update recommender data for"
186  ." <a href=\"r".$SourceItemId."\"><i>"
187  .$Item->GetMapped("Title")."</i></a>";
188  $GLOBALS["AF"]->QueueUniqueTask(array(__CLASS__, "RunUpdateForItem"),
189  array((int)$SourceItemId, $Index),
191  }
192  }
193 
194 
195  # ---- PRIVATE INTERFACE -------------------------------------------------
196 
197  private $Schema;
198 
199 }
Metadata schema (in effect a Factory class for MetadataField).
const PRIORITY_LOW
Lower priority.
const CONTENTFIELDTYPE_DATE
Definition: Recommender.php:18
SQL database abstraction object with smart query caching.
QueueUpdateForItem($ItemId, $TaskPriority=ApplicationFramework::PRIORITY_BACKGROUND)
GetFieldValue($ItemId, $FieldName)
const CONTENTFIELDTYPE_NUMERIC
Definition: Recommender.php:16
const MDFTYPE_CONTROLLEDNAME
PHP
Definition: OAIClient.php:39
static RunUpdateForItem($SourceItemId, $StartingIndex)
const CONTENTFIELDTYPE_TEXT
Definition: Recommender.php:15
Recommender(&$DB, $ItemTableName, $RatingTableName, $ItemIdFieldName, $UserIdFieldName, $RatingFieldName, $ContentFields)
Definition: Recommender.php:22
Represents a "resource" in CWIS.
Definition: Resource.php:13
Factory for Resource objects.
const PRIORITY_BACKGROUND
Lowest priority.