Search:

CWIS Developers Documentation

  • Main Page
  • Classes
  • Files
  • File List
  • File Members

ResourceFactory.php

Go to the documentation of this file.
00001 <?PHP
00002 #
00003 #   FILE:  ResourceFactory.php
00004 #
00005 #   METHODS PROVIDED:
00006 #       ResourceFactory()
00007 #           - constructor
00008 #       DuplicateResource($ResourceId)
00009 #           - create duplicate resource and return to caller
00010 #       (SEE ALSO:  ItemFactory.php)
00011 #
00012 #   AUTHOR:  Edward Almasy
00013 #
00014 #   Part of the Collection Workflow Integration System (CWIS)
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 }

CWIS logo doxygen
Copyright 2010 Internet Scout