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

/**
* Plugin for generating reports using data previously recorded by
* MetricsRecorder plugin.
*/
class MetricsReporter extends Plugin
{

    /**
    * Set the plugin attributes.  At minimum this method MUST set $this->Name
    * and $this->Version.  This is called when the plugin is initially loaded.
    */
    public function Register()
    {
        $this->Name = "Metrics Reporter";
        $this->Version = "1.1.2";
        $this->Description = "Generates usage and web metrics reports"
                ." from data recorded by the <i>Metrics Recorder</i> plugin.";
        $this->Author = "Internet Scout";
        $this->Url = "http://scout.wisc.edu/cwis/";
        $this->Email = "scout@scout.wisc.edu";
        $this->Requires = array(
                "CWISCore" => "2.2.3",
                "MetricsRecorder" => "1.1.3");
        $this->EnabledByDefault = TRUE;

        $this->CfgSetup["PrivsToExcludeFromCounts"] = array(
                "Type" => "Privileges",
                "Label" => "Exclude Users with",
                "AllowMultiple" => TRUE,
                "Help" => "Users with any of the selected privilege flags "
                        ." will be excluded from full record view counts,"
                        ." URL click counts, and other calculated metrics.",
                "Default" => array(
                        PRIV_SYSADMIN,
                        PRIV_RESOURCEADMIN,
                        PRIV_CLASSADMIN,
                        PRIV_NAMEADMIN,
                        PRIV_RELEASEADMIN,
                        PRIV_COLLECTIONADMIN),
                );
    }

    /**
    * Perform any work needed when the plugin is first installed (for example,
    * creating database tables).
    * @return string NULL if installation succeeded, otherwise a string containing
    *       an error message indicating why installation failed.
    */
    public function Install()
    {
        $DB = new Database();

        $DB->Query("CREATE TABLE IF NOT EXISTS MetricsReporter_Cache (
              Id VARCHAR(32),
              Page VARCHAR(32),
              Data LONGBLOB,
              LastUpdate TIMESTAMP DEFAULT NOW(),
              INDEX (Id, Page),
              INDEX (LastUpdate),
              UNIQUE (Id, Page) )");

        $DB->Query("CREATE TABLE IF NOT EXISTS MetricsReporter_SpamSearches ("
                   ."SearchKey VARCHAR(32), UNIQUE (SearchKey) )");
        return NULL;
    }

    /**
    * Perform any work needed when the plugin is upgraded to a new version
    * (for example, adding fields to database tables).
    * @param string $PreviousVersion The version number of this plugin that was
    *       previously installed.
    * @return string NULL if upgrade succeeded, otherwise a string containing
    *       an error message indicating why upgrade failed.
    */
    public function Upgrade($PreviousVersion)
    {
        $DB = new Database();

        if (version_compare($PreviousVersion, "1.1.0", "<"))
        {
            $DB->Query("CREATE TABLE IF NOT EXISTS MetricsReporter_Cache (
              Id VARCHAR(32),
              Page VARCHAR(32),
              Data LONGBLOB,
              LastUpdate TIMESTAMP DEFAULT NOW(),
              INDEX (Id, Page),
              INDEX (LastUpdate),
              UNIQUE (Id, Page) )");
        }

        if (version_compare($PreviousVersion, "1.1.2", "<"))
        {
            $DB->Query("CREATE TABLE IF NOT EXISTS MetricsReporter_SpamSearches ("
                       ."SearchKey VARCHAR(32), UNIQUE (SearchKey) )");
        }

        return NULL;
    }

    /**
    * Hook the events into the application framework.
    * @return Returns an array of events to be hooked into the application
    *      framework.
    */
    public function HookEvents()
    {
        return array(
                "EVENT_HOURLY" => "ExpireCache",
                "EVENT_COLLECTION_ADMINISTRATION_MENU" => "AddCollectionAdminMenuItems",
                "EVENT_USER_ADMINISTRATION_MENU" => "AddUserAdminMenuItems",
                );
    }


    # ---- HOOKED METHODS ----------------------------------------------------

    /**
    * Add entries to the Collection Administration menu.
    * @return array List of entries to add, with the label as the value and
    *       the page to link to as the index.
    */
    public function AddCollectionAdminMenuItems()
    {
        $Pages = array(
            "CollectionReports" => "Collection Usage Metrics",
            "SearchLog" => "View Search Log",
            "SearchLog&V=Frequency" => "View Search Frequency",
            );

        if ($GLOBALS["G_PluginManager"]->PluginEnabled("CalendarEvents") )
        {
            $Pages["EventReports"] = "Event Usage Metrics";
        }



        return $Pages;
    }

    /**
    * Add entries to the User Administration menu.
    * @return array List of entries to add, with label as the value
    *        and the page to link as the index.
    */
    public function AddUserAdminMenuItems()
    {
        return array(
            "UserReports" => "User Statistics" );
    }

    /**
    * Get a cached value.
    * @param string $Name Key to use when looking up value.
    */
    public function CacheGet($Name)
    {
        $DB = new Database();

        $DB->Query("SELECT Data FROM MetricsReporter_Cache "
                   ."WHERE Id='".md5($Name)."' AND "
                   ."Page='".md5($GLOBALS["AF"]->GetPageName())."'"
            );

        if ($DB->NumRowsSelected() == 0)
        {
            $Result = NULL;
        }
        else
        {
            $Row = $DB->FetchRow();
            $Result = unserialize(gzinflate(base64_decode($Row["Data"])));
        }

        return $Result;
    }

    /**
    * Store a value in the cache.
    * @param string $Name Key to use for later retrieval.
    * @param mixed $Data Value to store (must be serializable).
    */
    public function CachePut($Name, $Data)
    {
        $DB = new Database();

        $CacheId = md5($Name);
        $Page = md5($GLOBALS["AF"]->GetPageName());

        $DB->Query("LOCK TABLES MetricsReporter_Cache WRITE");
        $DB->Query("DELETE FROM MetricsReporter_Cache WHERE "
                   ."Id='".$CacheId."' AND "
                   ."Page='".$Page."'");
        $DB->Query("INSERT INTO MetricsReporter_Cache( Id, Page, Data ) "
                   ."VALUES ('".$CacheId."','".$Page."','"
                   .addslashes(base64_encode(gzdeflate(serialize($Data))))."') ");
        $DB->Query("UNLOCK TABLES");
    }

    /**
    * Clear all cache entries for the current page.
    */
    public function CacheClear()
    {
        $DB = new Database();
        $DB->Query("DELETE FROM MetricsReporter_Cache "
                   ."WHERE Page='".md5($GLOBALS["AF"]->GetPageName())."'" );
    }

    /**
    * Periodic task to expire old cache entries.
    */
    public function ExpireCache()
    {
        # Delete entries from the cache if they are older than 4 hours
        $DB = new Database();
        $DB->Query("DELETE FROM MetricsReporter_Cache "
                   ."WHERE NOW() - LastUpdate > 14400");
    }
}
