thinreports-php/thinreports-php

View on GitHub
src/Thinreports/Layout.php

Summary

Maintainability
A
50 mins
Test Coverage
<?php

/*
 * This file is part of the Thinreports PHP package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Thinreports;

use Thinreports\Exception;
use Thinreports\Item;
use Thinreports\Page\Page;

class Layout
{
    const FILE_EXT_NAME = 'tlf';
    const COMPATIBLE_VERSION_RANGE_START = '>= 0.8.2';
    const COMPATIBLE_VERSION_RANGE_END   = '< 0.9.0';

    /**
     * @param string $filename
     * @return self
     * @throws Exception\StandardException
     */
    static public function loadFile($filename)
    {
        if (pathinfo($filename, PATHINFO_EXTENSION) != self::FILE_EXT_NAME) {
            $filename .= '.' . self::FILE_EXT_NAME;
        }

        if (!file_exists($filename)) {
            throw new Exception\StandardException('Layout File Not Found', $filename);
        }

        return new self($filename, self::parse(file_get_contents($filename, true)));
    }

    /**
     * @access private
     *
     * @param string $file_content
     * @return array
     * @throws Exception\IncompatibleLayout
     */
    static public function parse($file_content)
    {
        $format = json_decode($file_content, true);

        if (!self::isCompatible($format['version'])) {
            $rules = array(
                self::COMPATIBLE_VERSION_RANGE_START,
                self::COMPATIBLE_VERSION_RANGE_END
            );
            throw new Exception\IncompatibleLayout($format['version'], $rules);
        }

        $item_formats = self::extractItemFormats($format['svg']);
        self::cleanFormat($format);

        return array(
            'format' => $format,
            'item_formats' => $item_formats
        );
    }

    /**
     * @access private
     *
     * @param string $layout_format
     * @return array
     */
    static public function extractItemFormats($layout_format)
    {
        preg_match_all('/<!--SHAPE(.*?)SHAPE-->/',
            $layout_format, $matched_items, PREG_SET_ORDER);

        $item_formats = array();

        foreach ($matched_items as $matched_item) {
            $item_format_json = $matched_item[1];
            $item_format = json_decode($item_format_json, true);

            if ($item_format['type'] === 's-list') {
                continue;
            }
            if ($item_format['type'] === Item\PageNumberItem::TYPE_NAME) {
                self::setPageNumberUniqueId($item_format);
            }

            $item_formats[$item_format['id']] = $item_format;
        }

        return $item_formats;
    }

    /**
     * @access private
     *
     * @param array $format
     */
    static public function cleanFormat(&$format)
    {
        $format['svg'] = preg_replace('/<!\-\-.*?\-\->/', '', $format['svg']);
        unset($format['state']);
    }

    /**
     * @access private
     *
     * @param string $layout_version
     * @return boolean
     */
    static public function isCompatible($layout_version)
    {
        $rules = array(
            self::COMPATIBLE_VERSION_RANGE_START,
            self::COMPATIBLE_VERSION_RANGE_END
        );

        foreach ($rules as $rule) {
            list($operator, $version) = explode(' ', $rule);

            if (!version_compare($layout_version, $version, $operator)) {
                return false;
            }
        }
        return true;
    }

    /**
     * @access private
     *
     * @param array $item_format
     */
    static public function setPageNumberUniqueId(array &$item_format)
    {
        if (empty($item_format['id'])) {
            $item_format['id'] = Item\PageNumberItem::generateUniqueId();
        }
    }

    private $format;
    private $item_foramts = array();
    private $identifier;

    /**
     * @param string $filename
     * @param array $deinition array('format' => array, 'item_formats' => array)
     */
    public function __construct($filename, array $definition)
    {
        $this->filename = $filename;
        $this->format = $definition['format'];
        $this->item_formats = $definition['item_formats'];
        $this->identifier = md5($this->format['svg']);
    }

    /**
     * @return string
     */
    public function getFilename()
    {
        return $this->filename;
    }

    /**
     * @return string
     */
    public function getReportTitle()
    {
        return $this->format['config']['title'];
    }

    /**
     * @return string
     */
    public function getPagePaperType()
    {
        return $this->format['config']['page']['paper-type'];
    }

    /**
     * @return string[]|null
     */
    public function getPageSize()
    {
        if ($this->isUserPaperType()) {
            $page = $this->format['config']['page'];
            return array($page['width'], $page['height']);
        } else {
            return null;
        }
    }

    /**
     * @return boolean
     */
    public function isPortraitPage()
    {
        return $this->format['config']['page']['orientation'] === 'portrait';
    }

    /**
     * @return boolean
     */
    public function isUserPaperType()
    {
        return $this->format['config']['page']['paper-type'] === 'user';
    }

    /**
     * @access private
     *
     * @return string
     */
    public function getLastVersion()
    {
        return $this->format['version'];
    }

    /**
     * @access private
     *
     * @return string
     */
    public function getSVG()
    {
        return $this->format['svg'];
    }

    /**
     * @access private
     *
     * @param string $id
     * @return boolean
     */
    public function hasItem($id)
    {
        return array_key_exists($id, $this->item_formats);
    }

    /**
     * @access private
     *
     * @param Page $owner
     * @param string $id
     * @return Item\AbstractItem
     * @throws Exception\StandardException
     */
    public function createItem(Page $owner, $id)
    {
        if (!$this->hasItem($id)) {
            throw new Exception\StandardException('Item Not Found', $id);
        }

        $item_format = $this->item_formats[$id];

        switch ($item_format['type']) {
            case 's-tblock':
                return new Item\TextBlockItem($owner, $item_format);
                break;
            case 's-iblock':
                return new Item\ImageBlockItem($owner, $item_format);
                break;
            case 's-pageno';
                return new Item\PageNumberItem($owner, $item_format);
                break;
            default:
                return new Item\BasicItem($owner, $item_format);
                break;
        }
    }

    /**
     * @access private
     *
     * @return string
     */
    public function getIdentifier()
    {
        return $this->identifier;
    }

    /**
     * @access private
     *
     * @return array
     */
    public function getFormat()
    {
        return $this->format;
    }

    /**
     * @access private
     *
     * @return array
     */
    public function getItemFormats()
    {
        return $this->item_formats;
    }
}