1<?php
2
3namespace Gettext;
4
5/**
6 * Static class with merge contants.
7 */
8final class Merge
9{
10    const ADD = 1;
11    const REMOVE = 2;
12
13    const HEADERS_ADD = 4;
14    const HEADERS_REMOVE = 8;
15    const HEADERS_OVERRIDE = 16;
16
17    const LANGUAGE_OVERRIDE = 32;
18    const DOMAIN_OVERRIDE = 64;
19    const TRANSLATION_OVERRIDE = 128;
20
21    const COMMENTS_OURS = 256;
22    const COMMENTS_THEIRS = 512;
23
24    const EXTRACTED_COMMENTS_OURS = 1024;
25    const EXTRACTED_COMMENTS_THEIRS = 2048;
26
27    const FLAGS_OURS = 4096;
28    const FLAGS_THEIRS = 8192;
29
30    const REFERENCES_OURS = 16384;
31    const REFERENCES_THEIRS = 32768;
32
33    const DEFAULTS = 5; //1 + 4
34
35    /**
36     * Merge the flags of two translations.
37     *
38     * @param Translation $from
39     * @param Translation $to
40     * @param int         $options
41     */
42    public static function mergeFlags(Translation $from, Translation $to, $options = self::DEFAULTS)
43    {
44        if ($options & self::FLAGS_THEIRS) {
45            $to->deleteFlags();
46        }
47
48        if (!($options & self::FLAGS_OURS)) {
49            foreach ($from->getFlags() as $flag) {
50                $to->addFlag($flag);
51            }
52        }
53    }
54
55    /**
56     * Merge the extracted comments of two translations.
57     *
58     * @param Translation $from
59     * @param Translation $to
60     * @param int         $options
61     */
62    public static function mergeExtractedComments(Translation $from, Translation $to, $options = self::DEFAULTS)
63    {
64        if ($options & self::EXTRACTED_COMMENTS_THEIRS) {
65            $to->deleteExtractedComments();
66        }
67
68        if (!($options & self::EXTRACTED_COMMENTS_OURS)) {
69            foreach ($from->getExtractedComments() as $comment) {
70                $to->addExtractedComment($comment);
71            }
72        }
73    }
74
75    /**
76     * Merge the comments of two translations.
77     *
78     * @param Translation $from
79     * @param Translation $to
80     * @param int         $options
81     */
82    public static function mergeComments(Translation $from, Translation $to, $options = self::DEFAULTS)
83    {
84        if ($options & self::COMMENTS_THEIRS) {
85            $to->deleteComments();
86        }
87
88        if (!($options & self::COMMENTS_OURS)) {
89            foreach ($from->getComments() as $comment) {
90                $to->addComment($comment);
91            }
92        }
93    }
94
95    /**
96     * Merge the references of two translations.
97     *
98     * @param Translation $from
99     * @param Translation $to
100     * @param int         $options
101     */
102    public static function mergeReferences(Translation $from, Translation $to, $options = self::DEFAULTS)
103    {
104        if ($options & self::REFERENCES_THEIRS) {
105            $to->deleteReferences();
106        }
107
108        if (!($options & self::REFERENCES_OURS)) {
109            foreach ($from->getReferences() as $reference) {
110                $to->addReference($reference[0], $reference[1]);
111            }
112        }
113    }
114
115    /**
116     * Merge the translations of two translations.
117     *
118     * @param Translation $from
119     * @param Translation $to
120     * @param int         $options
121     */
122    public static function mergeTranslation(Translation $from, Translation $to, $options = self::DEFAULTS)
123    {
124        $override = (boolean) ($options & self::TRANSLATION_OVERRIDE);
125
126        if (!$to->hasTranslation() || ($from->hasTranslation() && $override)) {
127            $to->setTranslation($from->getTranslation());
128        }
129
130        if (!$to->hasPlural() || ($from->hasPlural() && $override)) {
131            $to->setPlural($from->getPlural());
132        }
133
134        if (!$to->hasPluralTranslations() || ($from->hasPluralTranslations() && $override)) {
135            $to->setPluralTranslations($from->getPluralTranslations());
136        }
137    }
138
139    /**
140     * Merge the translations of two translations.
141     *
142     * @param Translations $from
143     * @param Translations $to
144     * @param int          $options
145     */
146    public static function mergeTranslations(Translations $from, Translations $to, $options = self::DEFAULTS)
147    {
148        if ($options & self::REMOVE) {
149            $filtered = [];
150
151            foreach ($to as $entry) {
152                if ($from->find($entry)) {
153                    $filtered[$entry->getId()] = $entry;
154                }
155            }
156
157            $to->exchangeArray($filtered);
158        }
159
160        foreach ($from as $entry) {
161            if (($existing = $to->find($entry))) {
162                $existing->mergeWith($entry, $options);
163            } elseif ($options & self::ADD) {
164                $to[] = $entry->getClone();
165            }
166        }
167    }
168
169    /**
170     * Merge the headers of two translations.
171     *
172     * @param Translations $from
173     * @param Translations $to
174     * @param int          $options
175     */
176    public static function mergeHeaders(Translations $from, Translations $to, $options = self::DEFAULTS)
177    {
178        if ($options & self::HEADERS_REMOVE) {
179            foreach (array_keys($to->getHeaders()) as $name) {
180                if ($from->getHeader($name) === null) {
181                    $to->deleteHeader($name);
182                }
183            }
184        }
185
186        foreach ($from->getHeaders() as $name => $value) {
187            $current = $to->getHeader($name);
188
189            if (empty($current)) {
190                if ($options & self::HEADERS_ADD) {
191                    $to->setHeader($name, $value);
192                }
193                continue;
194            }
195
196            if (empty($value)) {
197                continue;
198            }
199
200            switch ($name) {
201                case Translations::HEADER_LANGUAGE:
202                case Translations::HEADER_PLURAL:
203                    if ($options & self::LANGUAGE_OVERRIDE) {
204                        $to->setHeader($name, $value);
205                    }
206                    break;
207
208                case Translations::HEADER_DOMAIN:
209                    if ($options & self::DOMAIN_OVERRIDE) {
210                        $to->setHeader($name, $value);
211                    }
212                    break;
213
214                default:
215                    if ($options & self::HEADERS_OVERRIDE) {
216                        $to->setHeader($name, $value);
217                    }
218            }
219        }
220    }
221}
222