185 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			185 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
/**
 | 
						|
 * This file is part of the Peast package
 | 
						|
 *
 | 
						|
 * (c) Marco Marchiò <marco.mm89@gmail.com>
 | 
						|
 *
 | 
						|
 * For the full copyright and license information refer to the LICENSE file
 | 
						|
 * distributed with this source code
 | 
						|
 */
 | 
						|
namespace Peast\Selector;
 | 
						|
 | 
						|
use Peast\Syntax\Node\Node;
 | 
						|
 | 
						|
/**
 | 
						|
 * Selector matches class
 | 
						|
 * 
 | 
						|
 * @author Marco Marchiò <marco.mm89@gmail.com>
 | 
						|
 */
 | 
						|
class Matches
 | 
						|
{
 | 
						|
    /**
 | 
						|
     * Matches array
 | 
						|
     *
 | 
						|
     * @var array
 | 
						|
     */
 | 
						|
    protected $matches;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Class constructor
 | 
						|
     *
 | 
						|
     * @param array $matches Matches
 | 
						|
     */
 | 
						|
    public function __construct($matches = array())
 | 
						|
    {
 | 
						|
        $this->matches = $matches;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Adds a new match
 | 
						|
     *
 | 
						|
     * @param Node $node
 | 
						|
     * @param Node|null $parent
 | 
						|
     */
 | 
						|
    public function addMatch(Node $node, $parent = null)
 | 
						|
    {
 | 
						|
        $this->matches[] = array($node, $parent);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the matches
 | 
						|
     *
 | 
						|
     * @returns array
 | 
						|
     */
 | 
						|
    public function getMatches()
 | 
						|
    {
 | 
						|
        return $this->matches;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the matched nodes
 | 
						|
     *
 | 
						|
     * @return array
 | 
						|
     */
 | 
						|
    public function getNodes() {
 | 
						|
        return array_map(function ($m) {
 | 
						|
            return $m[0];
 | 
						|
        }, $this->matches);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Filters the matches using the given function, if it returns
 | 
						|
     * a false value the match will be removed. The function will
 | 
						|
     * receive the node and its parent as arguments.
 | 
						|
     *
 | 
						|
     * @param callable $fn Filter function
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function filter(callable $fn)
 | 
						|
    {
 | 
						|
        $newMatches = array();
 | 
						|
        foreach ($this->matches as $match) {
 | 
						|
            if ($fn($match[0], $match[1])) {
 | 
						|
                $newMatches[] = $match;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        $this->matches = $newMatches;
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Replaces all the matches with the result of the given function.
 | 
						|
     * The function will receive the node and its parent as arguments
 | 
						|
     * and must return an array of matches
 | 
						|
     *
 | 
						|
     * @param callable $fn Map function
 | 
						|
     *
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function map(callable $fn)
 | 
						|
    {
 | 
						|
        $newMatches = array();
 | 
						|
        foreach ($this->matches as $match) {
 | 
						|
            $res = $fn($match[0], $match[1]);
 | 
						|
            if ($res) {
 | 
						|
                $newMatches = array_merge($newMatches, $res);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        $this->matches = $newMatches;
 | 
						|
        return $this->unique();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Merges the current object with the other given Matches objects
 | 
						|
     *
 | 
						|
     * @param Matches[] $matchesArr Array of Matches to merge
 | 
						|
     *
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function merge($matchesArr)
 | 
						|
    {
 | 
						|
        foreach ($matchesArr as $matches) {
 | 
						|
            foreach ($matches->getMatches() as $match) {
 | 
						|
                $this->addMatch($match[0], $match[1]);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return $this->unique();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Remove all duplicated matches
 | 
						|
     *
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function unique()
 | 
						|
    {
 | 
						|
        $newMatches = array();
 | 
						|
        $newNodes = array();
 | 
						|
        foreach ($this->matches as $match) {
 | 
						|
            if (!in_array($match[0], $newNodes, true)) {
 | 
						|
                $newMatches[] = $match;
 | 
						|
                $newNodes[] = $match[0];
 | 
						|
            }
 | 
						|
        }
 | 
						|
        $this->matches = $newMatches;
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns a clone of the current object
 | 
						|
     *
 | 
						|
     * @return Matches
 | 
						|
     */
 | 
						|
    public function createClone()
 | 
						|
    {
 | 
						|
        return new self($this->matches);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the number of matches
 | 
						|
     *
 | 
						|
     * @return int
 | 
						|
     */
 | 
						|
    public function count()
 | 
						|
    {
 | 
						|
        return count($this->matches);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the match at the given index
 | 
						|
     *
 | 
						|
     * @param int $index Index
 | 
						|
     *
 | 
						|
     * @return array
 | 
						|
     *
 | 
						|
     * @throws \Exception
 | 
						|
     */
 | 
						|
    public function get($index)
 | 
						|
    {
 | 
						|
        $index = (int) $index;
 | 
						|
        if (!isset($this->matches[$index])) {
 | 
						|
            throw new \Exception("Invalid index $index");
 | 
						|
        }
 | 
						|
        return $this->matches[$index];
 | 
						|
    }
 | 
						|
} |