railpage/railpagecore

View on GitHub
lib/Locos/Date.php

Summary

Maintainability
D
2 days
Test Coverage
<?php

/**
 * Date / event object for a locomotive
 * @since   Version 3.8.7
 * @package Railpage
 * @author  Michael Greenhill
 */

namespace Railpage\Locos;

use DateTime;
use Exception;
use Railpage\Url;
use Railpage\Debug;
use Railpage\Glossary\Glossary;
use Railpage\ContentUtility;

/**
 * Date class
 */
class Date extends Locos {

    /**
     * Date ID
     * @var int $id
     */

    public $id;

    /**
     * Date
     * @var \DateTime $Date
     */

    public $Date;

    /**
     * Optional end date for this event
     * @since Version 3.9.1
     * @var \DateTime $DateEnd
     */

    public $DateEnd;

    /**
     * Date type
     * @var string $action
     */

    public $action;

    /**
     * Date type id
     * @var int $action_id
     */

    public $action_id;

    /**
     * Descriptive text
     * @var string $text
     */

    public $text;

    /**
     * Rich descriptive text
     * @var string $rich_text
     */

    public $rich_text;

    /**
     * Metadata
     * @var array $meta
     */

    public $meta;

    /**
     * Memcached / Redis cache key
     * @since Version 3.10.0
     * @var string $mckey
     */

    public $mckey;

    /**
     * Locomotive object
     * @var Locomotive $Loco
     */

    public $Loco;

    /**
     * URL object
     * @since Version 3.10.
     * @var \Railpage\Url $url
     */

    public $url;

    /**
     * Locomotive ID
     * To be superseded by $this->Loco
     * @since Version 3.10.0
     * @var int $loco_id
     */

    public $loco_id;

    /**
     * Constructor
     *
     * @param int $id
     */

    public function __construct($id = null) {

        $timer = Debug::getTimer();

        parent::__construct();

        if ($id = filter_var($id, FILTER_VALIDATE_INT)) {
            $this->id = $id;
            $this->populate();
        }

        Debug::logEvent(__METHOD__, $timer);

    }

    /**
     * Populate this object
     * @since Version 3.9.1
     * @return void
     */

    private function populate() {

        $this->mckey = sprintf("railpage.locos.date=%d", $this->id);
        $update = false;

        if (!$row = $this->Redis->fetch($this->mckey)) {

            $row = $this->db->fetchRow('SELECT d.*, dt.* FROM loco_unit_date AS d INNER JOIN loco_date_type AS dt ON d.loco_date_id = dt.loco_date_id WHERE d.date_id = ?', $this->id);

            $this->Redis->save($this->mckey, $row, strtotime("+1 year"));
        }

        if ($row === false) {
            return;
        }

        $this->text = $row['text'];
        $this->rich_text = $row['text'];
        $this->meta = json_decode($row['meta'], true);
        $this->action = $row['loco_date_text'];
        $this->action_id = $row['loco_date_id'];
        $this->loco_id = $row['loco_unit_id'];

        $this->loadLoco();

        if ($row['timestamp'] == "0000-00-00") {
            $this->Date = new DateTime();
            $this->Date->setTimestamp($row['date']);

            $update = true;
        } else {
            $this->Date = new DateTime($row['timestamp']);
        }

        if (isset( $row['date_end'] ) && !is_null($row['date_end'])) {
            $this->DateEnd = new DateTime($row['date_end']);
        }

        /**
         * Create the rich text entry
         */

        $this->createRichText();

        /**
         * Update this object if required
         */

        if ($update) {
            $this->commit();
        }
    }

    /**
     * Create the rich text entry
     * @since Version 3.9.1
     * @return void
     */

    private function createRichText() {

        if (!is_array($this->meta) || count($this->meta) === 0) {
            return;
        }

        foreach ($this->meta as $key => $data) {
            $this->rich_text .= "\n<strong>" . ucfirst($key) . ": </strong>";

            switch ($key) {

                case "livery" :
                    #$this->rich_text .= "[url=/flickr?tag=railpage:livery=" . $data['id'] . "]" . $data['name'] . "[/url]";
                    $this->rich_text .= "<a data-livery-id=\"" . $data['id'] . "\" data-livery-name=\"" . $data['name'] . "\" href='#' class='rp-modal-livery'>" . $data['name'] . "</a>";
                    break;

                case "owner" :
                    $Operator = new Operator($data['id']);
                    $this->rich_text .= "[url=" . $Operator->url_owner . "]" . $Operator->name . "[/url]";
                    break;

                case "operator" :
                    $Operator = new Operator($data['id']);
                    $this->rich_text .= "[url=" . $Operator->url_operator . "]" . $Operator->name . "[/url]";
                    break;

                case "position" :
                    if (!isset( $data['title'] ) || empty( $data['title'] )) {
                        $data['title'] = "Location";
                    }

                    $this->rich_text .= "<a data-lat=\"" . $data['lat'] . "\" data-lon=\"" . $data['lon'] . "\" data-zoom=\"" . $data['zoom'] . "\" data-title=\"" . $data['title'] . "\" data-toggle='modal' href='#' class='rp-modal-map'>Click to view</a>";
                    break;
            }
        }

        return;

    }


    /**
     * Validate changes to this object
     * @return boolean
     * @throws \Exception if $this->date is not an instance of \DateTime
     * @throws \Exception if $this->action_id is empty or not an integer
     * @throws \Exception if $this->Loco is not an instance of \Railpage\Locos\Locomotive
     */

    public function validate() {

        if (is_null($this->Loco) && filter_var($this->id, FILTER_VALIDATE_INT)) {
            $this->loadLoco();
        }

        if (!$this->Date instanceof DateTime) {
            throw new Exception("\$this->Date is not an instance of DateTime");
        }

        if (!filter_var($this->action_id)) {
            throw new Exception("\$this->action_id cannot be empty");
        }

        if (!$this->Loco instanceof Locomotive) {
            throw new Exception("\$this->Loco is not an instance of Railpage\Locos\Locomotive");
        }
        
        if (is_null($this->text)) {
            $this->text = "";
        }

        if (!empty( $this->meta )) {
            foreach ($this->meta as $k => $v) {
                $this->meta[$k] = $this->stripEmptyMeta($v);

                /*
                if (is_array($v)) {
                    foreach ($v as $l1k => $l1v) {
                        if (is_array($l1v)) {
                            foreach ($l1v as $l2k => $l2v) {
                                if (empty($this->meta[$k][$l2k])) {
                                    unset($this->meta[$k][$l2k]);
                                }
                            }
                        }

                        if (empty($this->meta[$k][$l1k])) {
                            unset($this->meta[$k][$l1k]);
                        }
                    }
                }
                */

                if (empty( $this->meta[$k] )) {
                    unset( $this->meta[$k] );
                }
            }
        }

        return true;
    }

    /**
     * Filter the meta data
     * @since Version 3.9.1
     *
     * @param array $array
     *
     * @return array
     */

    private function stripEmptyMeta($array) {

        if (!is_array($array)) {
            return $array;
        }

        foreach ($array as $key => $val) {
            if (is_array($val)) {
                $array[$key] = $this->stripEmptyMeta($val);
            }

            if (empty( $array[$key] )) {
                unset( $array[$key] );
                continue;
            }
        }

        return $array;

    }

    /**
     * Commit changes to this locomotive
     * @since Version 3.9.1
     * @return \Railpage\Locos\Date
     */

    public function commit() {

        $this->validate();

        $data = array(
            "loco_unit_id" => $this->Loco->id,
            "loco_date_id" => $this->action_id,
            "date"         => $this->Date->getTimestamp(),
            "date_end"     => $this->DateEnd instanceof DateTime ? $this->DateEnd->format("Y-m-d") : NULL,
            "timestamp"    => $this->Date->format("Y-m-d"),
            "text"         => $this->text,
            "meta"         => json_encode($this->meta)
        );

        if (filter_var($this->id)) {

            $this->Redis->delete($this->mckey);

            $where = array(
                "date_id = ?" => $this->id
            );

            $this->db->update("loco_unit_date", $data, $where);
        } else {
            $this->db->insert("loco_unit_date", $data);
            $this->id = $this->db->lastInsertId();
        }

        if (isset( $this->Loco->meta['construction_cost'] )) {
            $this->Loco->meta['construction_cost_inflated'] = ContentUtility::convertCurrency($this->Loco->meta['construction_cost'], Utility\LocomotiveUtility::getConstructionDate($this->Loco));
            $this->Loco->commit();
        }

        return $this;
    }

    /**
     * Find the glossary entry for this date
     * @since Version 3.9.1
     * @return null|\Railpage\Glossary\Entry
     */

    public function getGlossary() {

        return (new Glossary)->lookupText($this->action);

    }

    /**
     * Load the locomotive associated with this date
     * @since Version 3.9.1
     * @return \Railpage\Locos\Date
     */

    public function loadLoco() {

        $this->Loco = Factory::CreateLocomotive($this->loco_id);

        $this->url = new Url($this->Loco->url);

        return $this;

    }

    /**
     * Get this as an array
     * @since Version 3.9.1
     * @return array
     */

    public function getArray() {

        if (!$this->Loco instanceof Locomotive) {
            $this->loadLoco();
        }

        $return = array(
            "id"       => $this->id,
            "loco"     => array(
                "id"     => $this->Loco->id,
                "number" => $this->Loco->number,
                "class"  => array(
                    "id"   => $this->Loco->Class->id,
                    "name" => $this->Loco->Class->name
                ),
            ),
            "date"     => $this->Date->format("Y-m-d"),
            "date_end" => $this->DateEnd instanceof DateTime ? $this->DateEnd->format("Y-m-d") : NULL,
            "text"     => $this->text,
            "meta"     => $this->meta
        );

        return $return;

    }
}