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 __construct()
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
87  parent::__construct($DB, $ItemTableName, $RatingTableName,
88  $ItemIdFieldName, $UserIdFieldName, $RatingFieldName,
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,
119  $TaskPriority = ApplicationFramework::PRIORITY_BACKGROUND)
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 and pare down to those in same schema as source item
147  $TargetItemIds = $Recommender->GetItemIds();
148  $SourceSchemaIds = $RFactory->GetItemIds();
149  $TargetItemIds = array_values(array_intersect(
150  $TargetItemIds, $SourceSchemaIds));
151  $TargetCount = count($TargetItemIds);
152 
153  # while not last item ID and not out of time
154  for ($Index = $StartingIndex; $Index < $TargetCount; $Index++)
155  {
156  # if target ID points to non-temporary entry
157  if ($TargetItemIds[$Index] >= 0)
158  {
159  # update correlation for source item and current item
160  $StartTime = microtime(TRUE);
161  $Recommender->UpdateContentCorrelation(
162  $SourceItemId, $TargetItemIds[$Index]);
163  $ExecutionTime = microtime(TRUE) - $StartTime;
164 
165  # clear all caches if memory has run low
166  if ($GLOBALS["AF"]->GetFreeMemory() < 8000000)
167  {
168  Database::Caching(FALSE);
169  Database::Caching(TRUE);
170  self::ClearCaches();
171  if (function_exists("gc_collect_cycles"))
172  {
173  gc_collect_cycles();
174  }
175  }
176 
177  # bail out if out of memory or not enough time for another update
178  if (($GLOBALS["AF"]->GetSecondsBeforeTimeout() < ($ExecutionTime * 2))
179  || ($GLOBALS["AF"]->GetFreeMemory() < 8000000))
180  {
181  break;
182  }
183  }
184  }
185 
186  # if all correlations completed for source item
187  if ($Index >= $TargetCount)
188  {
189  # periodically prune correlations if enough time remaining
190  if (($GLOBALS["AF"]->GetSecondsBeforeTimeout() > 20)
191  && (rand(1, 10) == 1))
192  {
193  $Recommender->PruneCorrelations();
194  }
195  }
196  else
197  {
198  # requeue updates for remaining items
199  $Item = new Resource($SourceItemId);
200  $TaskDescription = "Update recommender data for"
201  ." <a href=\"r".$SourceItemId."\"><i>"
202  .$Item->GetMapped("Title")."</i></a>";
203  $GLOBALS["AF"]->QueueUniqueTask(array(__CLASS__, "RunUpdateForItem"),
204  array((int)$SourceItemId, $Index),
205  ApplicationFramework::PRIORITY_LOW);
206  }
207  }
208 
209 
210  # ---- PRIVATE INTERFACE -------------------------------------------------
211 
212  private $Schema;
213 
214 }
static Caching($NewSetting=NULL)
Get or set whether query result caching is currently enabled.
Metadata schema (in effect a Factory class for MetadataField).
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
static RunUpdateForItem($SourceItemId, $StartingIndex)
const CONTENTFIELDTYPE_TEXT
Definition: Recommender.php:15
Represents a "resource" in CWIS.
Definition: Resource.php:13
Factory for Resource objects.