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