1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\Intl\DateFormatter\DateFormat;
13
14/**
15 * Parser and formatter for month format.
16 *
17 * @author Igor Wiedler <igor@wiedler.ch>
18 *
19 * @internal
20 */
21class MonthTransformer extends Transformer
22{
23    protected static $months = [
24        'January',
25        'February',
26        'March',
27        'April',
28        'May',
29        'June',
30        'July',
31        'August',
32        'September',
33        'October',
34        'November',
35        'December',
36    ];
37
38    /**
39     * Short months names (first 3 letters).
40     */
41    protected static $shortMonths = [];
42
43    /**
44     * Flipped $months array, $name => $index.
45     */
46    protected static $flippedMonths = [];
47
48    /**
49     * Flipped $shortMonths array, $name => $index.
50     */
51    protected static $flippedShortMonths = [];
52
53    public function __construct()
54    {
55        if (0 === \count(self::$shortMonths)) {
56            self::$shortMonths = array_map(function ($month) {
57                return substr($month, 0, 3);
58            }, self::$months);
59
60            self::$flippedMonths = array_flip(self::$months);
61            self::$flippedShortMonths = array_flip(self::$shortMonths);
62        }
63    }
64
65    /**
66     * {@inheritdoc}
67     */
68    public function format(\DateTime $dateTime, $length)
69    {
70        $matchLengthMap = [
71            1 => 'n',
72            2 => 'm',
73            3 => 'M',
74            4 => 'F',
75        ];
76
77        if (isset($matchLengthMap[$length])) {
78            return $dateTime->format($matchLengthMap[$length]);
79        }
80
81        if (5 === $length) {
82            return substr($dateTime->format('M'), 0, 1);
83        }
84
85        return $this->padLeft($dateTime->format('m'), $length);
86    }
87
88    /**
89     * {@inheritdoc}
90     */
91    public function getReverseMatchingRegExp($length)
92    {
93        switch ($length) {
94            case 1:
95                $regExp = '\d{1,2}';
96                break;
97            case 3:
98                $regExp = implode('|', self::$shortMonths);
99                break;
100            case 4:
101                $regExp = implode('|', self::$months);
102                break;
103            case 5:
104                $regExp = '[JFMASOND]';
105                break;
106            default:
107                $regExp = '\d{1,'.$length.'}';
108                break;
109        }
110
111        return $regExp;
112    }
113
114    /**
115     * {@inheritdoc}
116     */
117    public function extractDateOptions($matched, $length)
118    {
119        if (!is_numeric($matched)) {
120            if (3 === $length) {
121                $matched = self::$flippedShortMonths[$matched] + 1;
122            } elseif (4 === $length) {
123                $matched = self::$flippedMonths[$matched] + 1;
124            } elseif (5 === $length) {
125                // IntlDateFormatter::parse() always returns false for MMMMM or LLLLL
126                $matched = false;
127            }
128        } else {
129            $matched = (int) $matched;
130        }
131
132        return [
133            'month' => $matched,
134        ];
135    }
136}
137