<?PHP
#
#   FILE:  ClassificationFactory.php
#
#   Part of the Collection Workflow Integration System (CWIS)
#   Copyright 2004-2013 Edward Almasy and Internet Scout Research Group
#   http://scout.wisc.edu/cwis/
#

/**
* Factory for producing and manipulating Classification objects.
* @see ItemFactory
*/
class ClassificationFactory extends ItemFactory {

    # ---- PUBLIC INTERFACE --------------------------------------------------

    /**
    * Class constructor.
    * @param int $FieldId ID of metadata field for classification.
    */
    function ClassificationFactory($FieldId = NULL)
    {
        # set up item factory base class
        $this->ItemFactory("Classification", "Classifications",
                "ClassificationId", "ClassificationName", FALSE,
                ($FieldId ? "FieldId = ".intval($FieldId) : NULL));
        $this->FieldId = (!is_null($FieldId)) ? intval($FieldId) : NULL;
    }

    /**
    * Get IDs of all children of specified classification.
    * @param int $ClassId ID of classification.
    * @return array IDs of all child classifications.
    */
    function GetChildIds($ClassId)
    {
        static $DB;

        # retrieve IDs of all children
        if (!isset($DB)) {  $DB = new Database();  }
        $DB->Query("SELECT ClassificationId FROM Classifications"
                ." WHERE ParentId = ".intval($ClassId));
        $ChildIds = $DB->FetchColumn("ClassificationId");

        # for each child
        $Ids = $ChildIds;
        foreach ($Ids as $Id)
        {
            # retrieve IDs of any children of child
            $ChildChildIds = $this->GetChildIds($Id);

            # add retrieved IDs to child ID list
            $ChildIds = array_merge($ChildIds, $ChildChildIds);
        }

        # return child ID list to caller
        return $ChildIds;
    }

    /**
    * Queue tasks to recalculate resource counts for all classifications.
    */
    public function RecalculateAllResourceCounts()
    {
        # queue a task to recalculate the resource counts for each
        # classification
        foreach ($this->GetItemIds() as $Id)
        {
            $GLOBALS["AF"]->QueueUniqueTask(
                array(__CLASS__, "RecalculateResourceCount"),
                array(intval($Id)),
                ApplicationFramework::PRIORITY_BACKGROUND,
                "Recalculate the resource counts for a classification");
        }
    }

    /**
    * Retrieve recently used items matching a search string.
    * @param string $SearchString String to match
    * @param int $NumberOfResults Number of results to return.  (OPTIONAL,
    *       defaults to 5)
    * @param array $IdExclusions List of IDs of items to exclude.
    * @param array $ValueExclusions List of names of items to exclude.
    * @return array List of item names, with item IDs for index.
    */
    function FindMatchingRecentlyUsedValues($SearchString, $NumberOfResults=5,
                                            $IdExclusions=array(), $ValueExclusions=array() )
    {
        # return no results if empty search string passed in
        if (!strlen(trim($SearchString))) {  return array();  }

        $IdExclusionSql = (count($IdExclusions)>0) ?
            "AND ClassificationId NOT IN ("
            .implode(',',array_map('intval',$IdExclusions)).")" :
            "";

        $ValueExclusionSql = (count($ValueExclusions)>0)?
            "AND ClassificationName NOT IN ("
            .implode(',', array_map(
                         function($v){ return "'".addslashes($v)."'"; }, $ValueExclusions) ).")" :
            "";

        $QueryString =
            "SELECT ClassificationId, ClassificationName FROM Classifications "
            ."WHERE FieldId=".$this->FieldId
            ." AND MATCH(ClassificationName) AGAINST ('".addslashes(trim($SearchString))."' IN BOOLEAN MODE)"
            ." ".$IdExclusionSql
            ." ".$ValueExclusionSql
            ." ORDER BY LastAssigned DESC LIMIT ".$NumberOfResults;

        $this->DB->Query($QueryString);

        $Names = $this->DB->FetchColumn("ClassificationName", "ClassificationId");

        return $Names;
    }

    /**
    * Callback to recalculate the resource count for a single classification by
    * its ID.
    * @param int $Id ID of the classification for which to recalculate the
    *      count.
    */
    public static function RecalculateResourceCount($Id)
    {
        $Classification = new Classification($Id);

        # only recalculate the counts if the classification is valid
        if ($Classification->Status() == Classification::CLASSSTAT_OK)
        {
            $Classification->RecalcResourceCount();
        }
    }

    # ---- PRIVATE INTERFACE -------------------------------------------------

    private $FieldId;
}
