<?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.
    */
    public function __construct($FieldId = NULL)
    {
        # set up item factory base class
        parent::__construct("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.
    */
    public 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.
    */
    public 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) ).")"
                : "";

        # mark all search elements as required
        $SearchString = preg_replace("%\S+%", "+\$0", $SearchString);

        $QueryString =
                "SELECT ClassificationId, ClassificationName"
                ." FROM Classifications"
                ." WHERE LastAssigned IS NOT NULL"
                .(($this->FieldId !== NULL) ? " AND FieldId = "
                        .intval($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)
    {
        # only recalculate the counts if the classification appears valid
        try
        {
            $Classification = new Classification($Id);
        }
        catch (Exception $e)
        {
            return;
        }

        $Classification->RecalcResourceCount();
    }

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

    private $FieldId;
}
