1<?php
2/*
3 * This file is part of PHPUnit.
4 *
5 * (c) Sebastian Bergmann <sebastian@phpunit.de>
6 *
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
9 */
10
11use SebastianBergmann\Diff\Differ;
12
13/**
14 * ...
15 */
16class PHPUnit_Framework_Constraint_StringMatches extends PHPUnit_Framework_Constraint_PCREMatch
17{
18    /**
19     * @var string
20     */
21    protected $string;
22
23    /**
24     * @param string $string
25     */
26    public function __construct($string)
27    {
28        parent::__construct($string);
29
30        $this->pattern = $this->createPatternFromFormat(
31            preg_replace('/\r\n/', "\n", $string)
32        );
33
34        $this->string = $string;
35    }
36
37    protected function failureDescription($other)
38    {
39        return 'format description matches text';
40    }
41
42    protected function additionalFailureDescription($other)
43    {
44        $from = preg_split('(\r\n|\r|\n)', $this->string);
45        $to   = preg_split('(\r\n|\r|\n)', $other);
46
47        foreach ($from as $index => $line) {
48            if (isset($to[$index]) && $line !== $to[$index]) {
49                $line = $this->createPatternFromFormat($line);
50
51                if (preg_match($line, $to[$index]) > 0) {
52                    $from[$index] = $to[$index];
53                }
54            }
55        }
56
57        $this->string = implode("\n", $from);
58        $other        = implode("\n", $to);
59
60        $differ = new Differ("--- Expected\n+++ Actual\n");
61
62        return $differ->diff($this->string, $other);
63    }
64
65    protected function createPatternFromFormat($string)
66    {
67        $string = str_replace(
68            [
69            '%e',
70            '%s',
71            '%S',
72            '%a',
73            '%A',
74            '%w',
75            '%i',
76            '%d',
77            '%x',
78            '%f',
79            '%c'
80            ],
81            [
82            '\\' . DIRECTORY_SEPARATOR,
83            '[^\r\n]+',
84            '[^\r\n]*',
85            '.+',
86            '.*',
87            '\s*',
88            '[+-]?\d+',
89            '\d+',
90            '[0-9a-fA-F]+',
91            '[+-]?\.?\d+\.?\d*(?:[Ee][+-]?\d+)?',
92            '.'
93            ],
94            preg_quote($string, '/')
95        );
96
97        return '/^' . $string . '$/s';
98    }
99}
100