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 }