jkphl/micrometa

View on GitHub
src/Micrometa/Infrastructure/Factory/MicroformatsFactory.php

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
<?php

/**
 * micrometa
 *
 * @category   Jkphl
 * @package    Jkphl\Micrometa
 * @subpackage Jkphl\Micrometa\Infrastructure
 * @author     Joschi Kuphal <joschi@kuphal.net> / @jkphl
 * @copyright  Copyright © 2018 Joschi Kuphal <joschi@kuphal.net> / @jkphl
 * @license    http://opensource.org/licenses/MIT The MIT License (MIT)
 */

/***********************************************************************************
 *  The MIT License (MIT)
 *
 *  Copyright © 2018 Joschi Kuphal <joschi@kuphal.net> / @jkphl
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy of
 *  this software and associated documentation files (the "Software"), to deal in
 *  the Software without restriction, including without limitation the rights to
 *  use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 *  the Software, and to permit persons to whom the Software is furnished to do so,
 *  subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 *  FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 *  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 *  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 *  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 ***********************************************************************************/

namespace Jkphl\Micrometa\Infrastructure\Factory;

/**
 * Microformats factory
 *
 * @package    Jkphl\Micrometa
 * @subpackage Jkphl\Micrometa\Infrastructure
 */
class MicroformatsFactory
{
    /**
     * Microformats 2 profile URI
     *
     * @var string
     * @link http://microformats.org/wiki/microformats-2#
     */
    const MF2_PROFILE_URI = 'http://microformats.org/profile/';

    /**
     * Refine an item
     *
     * @param array $item Item
     *
     * @return \stdClass Refined Microformats item
     */
    protected static function createItem(array $item)
    {
        $microformatItem = ['type' => self::createTypes($item['type']), 'lang' => null];
        self::processProperties($item, $microformatItem);
        self::processValue($item, $microformatItem);
        self::processChildren($item, $microformatItem);

        return (object)$microformatItem;
    }

    /**
     * Refine the item types
     *
     * @param array $types Types
     *
     * @return array Refined types
     */
    protected static function createTypes(array $types)
    {
        return array_map(
            function($type) {
                return (object)['profile' => self::MF2_PROFILE_URI, 'name' => $type];
            },
            $types
        );
    }

    /**
     * Process the item properties
     *
     * @param array $item            Item
     * @param array $microformatItem Refined Microformats item
     */
    protected static function processProperties(array $item, array &$microformatItem)
    {
        // Create the properties (if any)
        if (isset($item['properties']) && is_array($item['properties'])) {
            $microformatItem['properties'] = self::createProperties($item['properties'], $microformatItem['lang']);
        }
    }

    /**
     * Refine the item properties
     *
     * @param array $properties Properties
     * @param string $lang      Item language
     *
     * @return array Refined properties
     */
    protected static function createProperties(array $properties, &$lang)
    {
        // Extract the language (if present)
        $properties = self::createLanguage($properties, $lang);

        $mfProperties = [];
        foreach ($properties as $propertyName => $propertyValues) {
            // Process property values
            if (is_array($propertyValues)) {
                $mfProperties[] = (object)[
                    'profile' => self::MF2_PROFILE_URI,
                    'name'    => $propertyName,
                    'values'  => self::createProperty($propertyValues)
                ];
            }
        }

        return $mfProperties;
    }

    /**
     * Extract a language value from a value list
     *
     * @param array $values Value list
     * @param string $lang  Language
     *
     * @return array Remaining values
     */
    protected static function createLanguage(array $values, &$lang)
    {
        // If this is an alternate values list
        if (isset($values['lang'])) {
            if (is_string($values['lang'])) {
                $lang = trim($values['lang']) ?: null;
            }
            unset($values['lang']);
        }

        return $values;
    }

    /**
     * Refine the item property values
     *
     * @param array $propertyValues Property values
     *
     * @return array Refined property values
     */
    protected static function createProperty(array $propertyValues)
    {
        return array_map(
            function($propertyValue) {
                if (is_array($propertyValue)) {
                    return isset($propertyValue['type']) ?
                        self::createItem($propertyValue) : self::tagLanguage($propertyValue);
                }

                return $propertyValue;
            },
            $propertyValues
        );
    }

    /**
     * Tag values with a language (if possible)
     *
     * @param array $values Values
     *
     * @return array Language tagged values
     */
    protected static function tagLanguage(array $values)
    {
        $lang   = null;
        $values = self::createLanguage($values, $lang);

        return $lang ? array_map(function($value) use ($lang) {
            return (object)['value' => $value, 'lang' => $lang];
        }, $values) : $values;
    }

    /**
     * Process the item value
     *
     * @param array $item            Item
     * @param array $microformatItem Refined Microformats item
     */
    protected static function processValue(array $item, array &$microformatItem)
    {
        if (isset($item['value'])) {
            $microformatItem['value'] = self::createValue($item['value']);
        }
    }

    /**
     * Refine the item value
     *
     * @param string $value Value
     *
     * @return string Refined value
     */
    protected static function createValue($value)
    {
        return $value;
    }

    /**
     * Process the nested item children
     *
     * @param array $item            Item
     * @param array $microformatItem Refined Microformats item
     */
    protected static function processChildren(array $item, array &$microformatItem)
    {
        if (isset($item['children']) && is_array($item['children'])) {
            $microformatItem['children'] = self::createFromParserResult($item['children']);
        }
    }

    /**
     * Refine and convert the Microformats parser result
     *
     * @param array $items Items
     *
     * @return array Refined items
     */
    public static function createFromParserResult(array $items)
    {
        return array_map([self::class, 'createItem'], $items);
    }
}