ResourceFactory.php

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