ResourceFactory.php
Go to the documentation of this file.00001 <?PHP
00002
00003 #
00004 # FILE: ResourceFactory.php
00005 #
00006 # METHODS PROVIDED:
00007 # ResourceFactory()
00008 # - constructor
00009 # DuplicateResource($ResourceId)
00010 # - create duplicate resource and return to caller
00011 # (SEE ALSO: ItemFactory.php)
00012 #
00013 # AUTHOR: Edward Almasy
00014 #
00015 # Copyright 2011 Internet Scout Project
00016 # http://scout.wisc.edu
00017 #
00018
00019 class ResourceFactory extends ItemFactory {
00020
00021 # ---- PUBLIC INTERFACE --------------------------------------------------
00022
00023 # object constructor
00024 function ResourceFactory()
00025 {
00026 # set up item factory base class
00027 $this->ItemFactory("Resource", "Resources", "ResourceId");
00028 }
00029
00030 # create duplicate resource and return to caller
00031 function DuplicateResource($ResourceId)
00032 {
00033 # create new target resource
00034 $DstResource = new Resource();
00035
00036 # load up resource to duplicate
00037 $SrcResource = new Resource($ResourceId);
00038
00039 # if resource to duplicate was found
00040 if ($SrcResource->Status() > 0)
00041 {
00042 # for each metadata field
00043 $Schema = new MetadataSchema();
00044 $Fields = $Schema->GetFields();
00045 foreach ($Fields as $Field)
00046 {
00047 # skip the cumulative rating field
00048 if ($Field->Name() != "Cumulative Rating")
00049 {
00050 $NewValue = $SrcResource->GetByField($Field, TRUE);
00051
00052 # clear default value from destination resource that is
00053 # set when creating a new resource
00054 $DstResource->ClearByField($Field);
00055
00056 # copy value from source resource to destination resource
00057 $DstResource->SetByField($Field, $NewValue);
00058 }
00059 }
00060 }
00061
00062 # return new resource to caller
00063 return $DstResource;
00064 }
00065
00066 # clear or change specific qualifier for all resources
00067 function ClearQualifier($ObjectOrId, $NewObjectOrId = NULL)
00068 {
00069 # sanitize qualifier ID or retrieve from object
00070 $QualifierId = is_object($ObjectOrId)
00071 ? $ObjectOrId->Id() : intval($ObjectOrId);
00072
00073 # if new qualifier passed in
00074 if ($NewObjectOrId !== NULL)
00075 {
00076 # sanitize qualifier ID to change to or retrieve it from object
00077 $NewQualifierIdVal = is_object($NewObjectOrId)
00078 ? $NewObjectOrId->Id() : intval($NewObjectOrId);
00079 }
00080 else
00081 {
00082 # qualifier should be cleared
00083 $NewQualifierIdVal = "NULL";
00084 }
00085
00086 # for each metadata field
00087 $Schema = new MetadataSchema();
00088 $Fields = $Schema->GetFields();
00089 foreach ($Fields as $Field)
00090 {
00091 # if field uses qualifiers and uses item-level qualifiers
00092 $QualColName = $Field->DBFieldName()."Qualifier";
00093 if ($Field->UsesQualifiers()
00094 && $Field->HasItemLevelQualifiers()
00095 && $this->DB->FieldExists("Resources", $QualColName))
00096 {
00097 # set all occurrences to new qualifier value
00098 $this->DB->Query("UPDATE Resources"
00099 ." SET ".$QualColName." = ".$NewQualifierIdVal.""
00100 ." WHERE ".$QualColName." = '".$QualifierId."'");
00101 }
00102 }
00103
00104 # clear or change qualifier association with controlled names
00105 # (NOTE: this should probably be done in a controlled name factory object)
00106 $this->DB->Query("UPDATE ControlledNames"
00107 ." SET QualifierId = ".$NewQualifierIdVal
00108 ." WHERE QualifierId = '".$QualifierId."'");
00109
00110 # clear or change qualifier association with classifications
00111 # (NOTE: this should probably be done in a classification factory object)
00112 $this->DB->Query("UPDATE Classifications"
00113 ." SET QualifierId = ".$NewQualifierIdVal
00114 ." WHERE QualifierId = '".$QualifierId."'");
00115 }
00116
00117 # return count of rated resources
00118 function GetRatedResourceCount()
00119 {
00120 $RatedResourceCount = $this->DB->Query(
00121 "SELECT COUNT(DISTINCT ResourceId) AS ResourceCount "
00122 ."FROM ResourceRatings", "ResourceCount");
00123 return $RatedResourceCount;
00124 }
00125
00126 # return count of users who have rated resources
00127 function GetRatedResourceUserCount()
00128 {
00129 $RatedResourceCount = $this->DB->Query(
00130 "SELECT COUNT(DISTINCT UserId) AS UserCount "
00131 ."FROM ResourceRatings", "UserCount");
00132 return $RatedResourceCount;
00133 }
00134
00135 # return recently released resources
00136 function GetRecentlyReleasedResources($Count = 10, $Offset = 0, $MaxDaysToGoBack = 90)
00137 {
00138 # assume that no resources will be found
00139 $Resources = array();
00140
00141 # calculate cutoff date for resources
00142 $CutoffDate = date("Y-m-d H:i:s", strtotime($MaxDaysToGoBack." days ago"));
00143
00144 # query for resource IDs
00145 $this->DB->Query("SELECT ResourceId FROM Resources WHERE"
00146 ." DateOfRecordRelease > '".$CutoffDate."'"
00147 ." AND ReleaseFlag = 1"
00148 ." AND ResourceId >= 0"
00149 ." ORDER BY DateOfRecordRelease DESC, DateOfRecordCreation DESC"
00150 ." LIMIT ".intval($Offset).", ".intval($Count));
00151 $ResourceIds = $this->DB->FetchColumn("ResourceId");
00152
00153 # for each resource ID found
00154 foreach ($ResourceIds as $ResourceId)
00155 {
00156 # load resource and add to list of found resources
00157 $Resources[$ResourceId] = new Resource($ResourceId);
00158 }
00159
00160 # return found resources to caller
00161 return $Resources;
00162 }
00163
00164 # return resources sorted by specified field
00165 function GetResourceIdsSortedBy($FieldName, $Ascending = TRUE, $Limit = NULL)
00166 {
00167 # assume no resources will be found
00168 $ResourceIds = array();
00169
00170 # get field
00171 $Schema = new MetadataSchema();
00172 $Field = $Schema->GetFieldByName($FieldName);
00173
00174 # if field was found
00175 if ($Field != NULL)
00176 {
00177 # construct query based on field type
00178 switch ($Field->Type())
00179 {
00180 case MetadataSchema::MDFTYPE_TEXT:
00181 case MetadataSchema::MDFTYPE_PARAGRAPH:
00182 case MetadataSchema::MDFTYPE_URL:
00183 $Count = $this->DB->Query("SELECT COUNT(*) AS ResourceCount"
00184 ." FROM Resources WHERE "
00185 .$Field->DBFieldName()." IS NOT NULL"
00186 ." AND LENGTH(LTRIM(RTRIM(".$Field->DBFieldName()."))) > 0",
00187 "ResourceCount");
00188 if ($Count > 1)
00189 {
00190 $Query = "SELECT ResourceId FROM Resources"
00191 ." ORDER BY ".$Field->DBFieldName()
00192 .($Ascending ? " ASC" : " DESC");
00193 }
00194 break;
00195
00196 case MetadataSchema::MDFTYPE_NUMBER:
00197 case MetadataSchema::MDFTYPE_TIMESTAMP:
00198 $Count = $this->DB->Query("SELECT COUNT(*) AS ResourceCount"
00199 ." FROM Resources WHERE "
00200 .$Field->DBFieldName()." IS NOT NULL",
00201 "ResourceCount");
00202 if ($Count > 1)
00203 {
00204 $Query = "SELECT ResourceId FROM Resources"
00205 ." ORDER BY ".$Field->DBFieldName()
00206 .($Ascending ? " ASC" : " DESC");
00207 }
00208 break;
00209
00210 case MetadataSchema::MDFTYPE_DATE:
00211 $Count = $this->DB->Query("SELECT COUNT(*) AS ResourceCount"
00212 ." FROM Resources WHERE "
00213 .$Field->DBFieldName()."Begin IS NOT NULL",
00214 "ResourceCount");
00215 if ($Count > 1)
00216 {
00217 $Query = "SELECT ResourceId FROM Resources"
00218 ." ORDER BY ".$Field->DBFieldName()."Begin"
00219 .($Ascending ? " ASC" : " DESC");
00220 }
00221 break;
00222 }
00223
00224 # if appropriate query was found
00225 if (isset($Query))
00226 {
00227 # if limited number of results were requested
00228 if ($Limit !== NULL)
00229 {
00230 # add limit to query
00231 $Query .= " LIMIT ".intval($Limit);
00232 }
00233
00234 # perform query and retrieve resource IDs
00235 $this->DB->Query($Query);
00236 $ResourceIds = $this->DB->FetchColumn("ResourceId");
00237 }
00238 }
00239
00240 # return resource IDs to caller
00241 return $ResourceIds;
00242 }
00243
00244 # get date/time of last resource modification (returned as Unix timestamp)
00245 function GetTimestampOfLastResourceModification($OnlyReleasedResources = TRUE)
00246 {
00247 $LastChangeDate = $this->DB->Query(
00248 "SELECT MAX(DateLastModified) AS LastChangeDate"
00249 ." FROM Resources".($OnlyReleasedResources ? " WHERE ReleaseFlag = 1" : ""),
00250 "LastChangeDate");
00251 return ($LastChangeDate ? strtotime($LastChangeDate) : NULL);
00252 }
00253
00254 # get list of possible field names for resources
00255 function GetPossibleFieldNames()
00256 {
00257 # retrieve field names from schema
00258 $FieldNames = array();
00259 $Schema = new MetadataSchema();
00260 $Fields = $Schema->GetFields();
00261 foreach ($Fields as $Field)
00262 {
00263 $FieldNames[$Field->Id()] = $Field->Name();
00264 }
00265
00266 # return field names to caller
00267 return $FieldNames;
00268 }
00269
00270 # find resources with values that match those specified
00271 # (index of $ValuesToMatch is field IDs)
00272 function GetMatchingResources($ValuesToMatch)
00273 {
00274 # start out assuming we won't find any resources
00275 $Resources = array();
00276
00277 # for each value
00278 $Schema = new MetadataSchema();
00279 $Fields = $Schema->GetFields(
00280 MetadataSchema::MDFTYPE_TEXT |
00281 MetadataSchema::MDFTYPE_PARAGRAPH |
00282 MetadataSchema::MDFTYPE_NUMBER | MetadataSchema::MDFTYPE_DATE |
00283 MetadataSchema::MDFTYPE_TIMESTAMP |
00284 MetadataSchema::MDFTYPE_FLAG | MetadataSchema::MDFTYPE_URL |
00285 MetadataSchema::MDFTYPE_POINT);
00286 $LinkingTerm = "";
00287 $Condition = "";
00288 foreach ($ValuesToMatch as $FieldId => $Value)
00289 {
00290 # if field can be used for comparison
00291 if (isset($Fields[$FieldId]))
00292 {
00293 # add comparison to condition
00294 $Condition .= $LinkingTerm.$Fields[$FieldId]->DBFieldName()
00295 ." = '".addslashes($Value)."'";
00296 $LinkingTerm = " AND ";
00297 }
00298 }
00299
00300 # if there were valid conditions
00301 if (strlen($Condition))
00302 {
00303 # build query statment
00304 $Query = "SELECT ResourceId FROM Resources WHERE ".$Condition;
00305
00306 # execute query to retrieve matching resource IDs
00307 $this->DB->Query($Query);
00308 $ResourceIds = $DB->FetchColumn("ResourceId");
00309
00310 # retrieve resource objects
00311 foreach ($ResourceIds as $Id)
00312 {
00313 $Resources[$Id] = new Resource($Id);
00314 }
00315 }
00316
00317 # return any resources found to caller
00318 return $Resources;
00319 }
00320
00321 # Functions for keeping per-field resource counts updated:
00322 function GetResourceCount($FieldId, $Value, $CountType="All")
00323 {
00324 if ($this->ResourceCount === NULL)
00325 {
00326 $this->DB->Query(
00327 "SELECT FieldId, ClassName, CountType, Count from ResourceCounts");
00328
00329 while ($Row = $this->DB->FetchRow())
00330 {
00331 $FieldId = $Row["FieldId"];
00332 $ClassName = $Row["ClassName"];
00333 $CountType = $Row["CountType"];
00334 $Count = $Row["Count"];
00335
00336 $this->ResourceCount[$FieldId][$ClassName][$CountType] = $Count;
00337 }
00338 }
00339
00340 if (time() - $this->ResourceCount[-1]["__LAST_UPDATED__"][""] > 1800 &&
00341 $this->ResourceCountTaskQueued === FALSE)
00342 {
00343 $this->QueueResourceCountUpdate();
00344 }
00345
00346 $Schema = new MetadataSchema();
00347 $Field = $Schema->GetField($FieldId);
00348
00349 if ($Field->Status() === MetadataSchema::MDFSTAT_OK &&
00350 ( $Field->Type() === MetadataSchema::MDFTYPE_OPTION ||
00351 $Field->Type() === MetadataSchema::MDFTYPE_CONTROLLEDNAME ) )
00352 {
00353 return isset($this->ResourceCount[$FieldId][$Value][$CountType]) ?
00354 $this->ResourceCount[$FieldId][$Value][$CountType] :
00355 0 ;
00356 }
00357 else
00358 {
00359 return NULL;
00360 }
00361 }
00362
00363 function QueueResourceCountUpdate()
00364 {
00365 global $AF;
00366
00367 # be sure that we're not a gigantic object when the task is queued
00368 $TmpResourceCount = $this->ResourceCount;
00369 $this->ResourceCount = NULL;
00370
00371 $AF->QueueUniqueTask(
00372 array($this,"UpdateResourceCountCallback"), array());
00373 $this->ResourceCountTaskQueued = TRUE;
00374 $this->ResourceCount = $TmpResourceCount;
00375 }
00376
00377 function UpdateResourceCountCallback()
00378 {
00379 $DB = new Database();
00380 $DB->Query(
00381 "CREATE TABLE ResourceCountsNew (FieldId INT, ClassName TEXT, CountType TEXT, Count INT);");
00382
00383 $Start = microtime(TRUE);
00384
00385 foreach ($this->ResourceCountConditions as $CountType => $CountCondition)
00386 {
00387 $DB->Query(
00388 "INSERT INTO ResourceCountsNew "
00389 ."SELECT FieldId, ControlledName AS ClassName,"
00390 . "'".$CountType."' AS CountType, Count(ResourceId) AS Count "
00391 . "FROM (SELECT * FROM ResourceNameInts WHERE ResourceId IN "
00392 . "(SELECT ResourceId FROM Resources "
00393 . (($CountCondition!==NULL)?"WHERE ".$CountCondition:"").")) AS T0 "
00394 . "JOIN ControlledNames USING(ControlledNameId) GROUP BY ControlledNameId;" );
00395 }
00396
00397 $Stop = microtime(TRUE);
00398
00399 $DB->Query(
00400 "INSERT INTO ResourceCountsNew VALUES (-1, '__LAST_UPDATED__', '', UNIX_TIMESTAMP()); ");
00401 $DB->Query(
00402 "INSERT INTO ResourceCountsNew VALUES (-2, '__UPDATE_RUNTIME__','',".($Stop-$Start).");");
00403 $DB->Query(
00404 "RENAME TABLE ResourceCounts TO ResourceCountsOld, ResourceCountsNew TO ResourceCounts; ");
00405 $DB->Query(
00406 "DROP TABLE ResourceCountsOld; ");
00407 }
00408
00409 # ---- PRIVATE INTERFACE -------------------------------------------------
00410
00411 private $ResourceCount = NULL;
00412 private $ResourceCountTaskQueued = FALSE;
00413 private $ResourceCountConditions = array("All" => NULL, "Released" => "ReleaseFlag=1");
00414 }
00415
00416 ?>