SPTRecommender.php
Go to the documentation of this file.00001 <?PHP
00002 #
00003 # FILE: SPTRecommender.php
00004 #
00005 # Part of the Collection Workflow Integration System (CWIS)
00006 # Copyright 2011 Edward Almasy and Internet Scout Project
00007 # http://scout.wisc.edu/
00008 #
00009
00010 class SPTRecommender extends Recommender {
00011
00012 function SPTRecommender()
00013 {
00014 # set up recommender configuration values for SPT
00015 $ItemTableName = "Resources";
00016 $ItemIdFieldName = "ResourceId";
00017 $RatingTableName = "ResourceRatings";
00018 $UserIdFieldName = "UserId";
00019 $RatingFieldName = "Rating";
00020
00021 # build field info from SPT metadata schema
00022 $this->Schema = new MetadataSchema();
00023 $Fields = $this->Schema->GetFields();
00024 foreach ($Fields as $Field)
00025 {
00026 if ($Field->Enabled() && $Field->IncludeInKeywordSearch())
00027 {
00028 $FieldName = $Field->Name();
00029 $FieldInfo[$FieldName]["DBFieldName"] = $Field->DBFieldName();
00030 $FieldInfo[$FieldName]["Weight"] = $Field->SearchWeight();
00031 switch ($Field->Type())
00032 {
00033 case MetadataSchema::MDFTYPE_TEXT:
00034 case MetadataSchema::MDFTYPE_PARAGRAPH:
00035 case MetadataSchema::MDFTYPE_USER:
00036 case MetadataSchema::MDFTYPE_URL:
00037 $FieldInfo[$FieldName]["FieldType"] =
00038 Recommender::CONTENTFIELDTYPE_TEXT;
00039 break;
00040
00041 case MetadataSchema::MDFTYPE_TREE:
00042 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
00043 case MetadataSchema::MDFTYPE_OPTION:
00044 $FieldInfo[$FieldName]["FieldType"] =
00045 Recommender::CONTENTFIELDTYPE_TEXT;
00046 break;
00047
00048 case MetadataSchema::MDFTYPE_NUMBER:
00049 case MetadataSchema::MDFTYPE_FLAG:
00050 $FieldInfo[$FieldName]["FieldType"] =
00051 Recommender::CONTENTFIELDTYPE_NUMERIC;
00052 break;
00053
00054 case MetadataSchema::MDFTYPE_DATE:
00055 $FieldInfo[$FieldName]["FieldType"] =
00056 Recommender::CONTENTFIELDTYPE_DATERANGE;
00057 break;
00058
00059 case MetadataSchema::MDFTYPE_TIMESTAMP:
00060 $FieldInfo[$FieldName]["FieldType"] =
00061 Recommender::CONTENTFIELDTYPE_DATE;
00062 break;
00063
00064 case MetadataSchema::MDFTYPE_IMAGE:
00065 # (for images we use their alt text)
00066 $FieldInfo[$FieldName]["FieldType"] =
00067 Recommender::CONTENTFIELDTYPE_TEXT;
00068 break;
00069
00070 case MetadataSchema::MDFTYPE_FILE:
00071 # (for files we use the file name)
00072 $FieldInfo[$FieldName]["FieldType"] =
00073 Recommender::CONTENTFIELDTYPE_TEXT;
00074 break;
00075 }
00076 }
00077 }
00078
00079 # create our own schema object and tell it to cache values
00080 $this->Schema = new MetadataSchema();
00081 $this->Schema->CacheData(TRUE);
00082
00083 # create a database connection for recommender to use
00084 $DB = new SPTDatabase();
00085
00086 # pass configuration info to real recommender object
00087 $this->Recommender($DB, $ItemTableName, $RatingTableName,
00088 $ItemIdFieldName, $UserIdFieldName, $RatingFieldName,
00089 $FieldInfo);
00090 }
00091
00092 # overloaded version of method to retrieve field values from DB
00093 function GetFieldValue($ItemId, $FieldName)
00094 {
00095 static $Resources;
00096
00097 # if resource not already loaded
00098 if (!isset($Resources[$ItemId]))
00099 {
00100 # get resource object
00101 $Resources[$ItemId] = new Resource($ItemId);
00102
00103 # if cached resource limit exceeded
00104 if (count($Resources) > 100)
00105 {
00106 # dump oldest resource
00107 reset($Resources);
00108 list($DumpedItemId, $DumpedResources) = each($Resources);
00109 unset($Resources[$DumpedItemId]);
00110 }
00111 }
00112
00113 # retrieve field value from resource object and return to caller
00114 $FieldValue = $Resources[$ItemId]->Get($FieldName);
00115 return $FieldValue;
00116 }
00117
00118 function QueueUpdateForItem($ItemId,
00119 $Priority = ApplicationFramework::PRIORITY_LOW)
00120 {
00121 global $AF;
00122 $AF->QueueUniqueTask(array(__CLASS__, "RunUpdateForItem"),
00123 array(intval($ItemId), 0), $Priority);
00124 }
00125
00126 static function RunUpdateForItem($SourceItemId, $StartingIndex)
00127 {
00128 # check that resource still exists
00129 $RFactory = new ResourceFactory();
00130 if (!$RFactory->ItemExists($SourceItemId)) { return; }
00131
00132 # load recommender engine
00133 static $Recommender;
00134 if (!isset($Recommender)) { $Recommender = new SPTRecommender(); }
00135
00136 # if starting update for source item
00137 if ($StartingIndex == 0)
00138 {
00139 # clear data for item
00140 $Recommender->DropItem($SourceItemId);
00141 }
00142
00143 # load array of item IDs
00144 $TargetItemIds = $Recommender->GetItemIds();
00145 $TargetCount = count($TargetItemIds);
00146
00147 # while not last item ID and not out of time
00148 global $AF;
00149 for ($Index = $StartingIndex; ($Index < $TargetCount)
00150 && ($AF->GetSecondsBeforeTimeout() > 5); $Index++)
00151 {
00152 # if target ID points to non-temporary entry
00153 if ($TargetItemIds[$Index] >= 0)
00154 {
00155 # update correlation for source item and current item
00156 $Recommender->UpdateContentCorrelation(
00157 $SourceItemId, $TargetItemIds[$Index]);
00158 }
00159 }
00160
00161 # if all correlations completed for source item
00162 if ($Index >= $TargetCount)
00163 {
00164 # periodically prune correlations if enough time remaining
00165 if (($AF->GetSecondsBeforeTimeout() > 10) && (rand(1, 10) == 1))
00166 {
00167 $Recommender->PruneCorrelations();
00168 }
00169 }
00170 else
00171 {
00172 # requeue updates for remaining items
00173 $AF->QueueUniqueTask(array(__CLASS__, "RunUpdateForItem"),
00174 array($SourceItemId, $Index), ApplicationFramework::PRIORITY_MEDIUM);
00175 }
00176 }
00177
00178
00179 # ---- PRIVATE INTERFACE -------------------------------------------------
00180
00181 private $Schema;
00182
00183 }