1: <?php
2: /**
3: * This file is part of GameQ.
4: *
5: * GameQ is free software; you can redistribute it and/or modify
6: * it under the terms of the GNU Lesser General Public License as published by
7: * the Free Software Foundation; either version 3 of the License, or
8: * (at your option) any later version.
9: *
10: * GameQ is distributed in the hope that it will be useful,
11: * but WITHOUT ANY WARRANTY; without even the implied warranty of
12: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13: * GNU Lesser General Public License for more details.
14: *
15: * You should have received a copy of the GNU Lesser General Public License
16: * along with this program. If not, see <http://www.gnu.org/licenses/>.
17: */
18:
19: namespace GameQ\Filters;
20:
21: use Closure;
22: use GameQ\Helpers\Arr;
23: use GameQ\Server;
24:
25: /**
26: * Class Strip Colors
27: *
28: * This Filter is responsible for removing
29: * color codes from the provided result.
30: *
31: * @package GameQ\Filters
32: */
33: class Stripcolors extends Base
34: {
35: /**
36: * Determines if data should be persisted for unit testing.
37: *
38: * @var bool
39: */
40: protected $writeTestData = false;
41:
42: /**
43: * Apply this filter
44: *
45: * @SuppressWarnings(PHPMD.CyclomaticComplexity)
46: *
47: * @param array $result
48: * @param \GameQ\Server $server
49: *
50: * @return array
51: */
52: public function apply(array $result, Server $server)
53: {
54: // Prevent working on empty results
55: if (! empty($result)) {
56: // Handle unit test data generation
57: if ($this->writeTestData) {
58: // Initialize potential data for unit testing
59: $unitTestData = [];
60:
61: // Add the initial result to the unit test data
62: $unitTestData['raw'][$server->id()] = $result;
63: }
64:
65: // Determine the executor defined for the current Protocol
66: if ($executor = $this->getExecutor($server)) {
67: // Apply the executor to the result recursively
68: $result = Arr::recursively($result, function (&$value) use ($executor) {
69: // The executor may only be applied to strings
70: if (is_string($value)) {
71: // Strip the colors and update the value by reference
72: $value = $executor($value);
73: } elseif (! is_array($value)) {
74: $value = (string) $value; // TODO: Remove this in the next major version.
75: }
76: });
77: }
78:
79: // Handle unit test data generation
80: if ($this->writeTestData) {
81: // Add the filtered result to the unit test data
82: $unitTestData['filtered'][$server->id()] = $result;
83:
84: // Persist the collected data to the tests directory
85: file_put_contents(
86: sprintf(
87: '%s/../../../tests/Filters/Providers/Stripcolors\%s_1.json',
88: __DIR__,
89: $server->protocol()->getProtocol()
90: ),
91: json_encode($unitTestData, JSON_UNESCAPED_UNICODE | JSON_PARTIAL_OUTPUT_ON_ERROR)
92: );
93: }
94: }
95:
96: // Return the filtered result
97: return $result;
98: }
99:
100: /**
101: * Strip color codes from quake based games.
102: *
103: * @param string $string
104: */
105: protected function stripQuake($string)
106: {
107: return preg_replace('#(\^.)#', '', $string);
108: }
109:
110: /**
111: * Strip color codes from Source based games.
112: *
113: * @param string $string
114: */
115: protected function stripSource($string)
116: {
117: return strip_tags($string);
118: }
119:
120: /**
121: * Strip color codes from Unreal based games.
122: *
123: * @param string $string
124: */
125: protected function stripUnreal($string)
126: {
127: return preg_replace('/\x1b.../', '', $string);
128: }
129:
130: /**
131: * This helper determines the correct executor to
132: * be used with the current Protocl instance.
133: *
134: * @SuppressWarnings(PHPMD.CyclomaticComplexity)
135: *
136: * @return null|Closure<string>
137: */
138: protected function getExecutor(Server $server)
139: {
140: // Determine the correct executor for the current Protocol instance
141: switch ($server->protocol()->getProtocol()) {
142: // Strip Protocols using Quake color tags
143: case 'quake2':
144: case 'quake3':
145: case 'doom3':
146: case 'gta5m':
147: return [$this, 'stripQuake'];
148:
149: // Strip Protocols using Unreal color tags
150: case 'unreal2':
151: case 'ut3':
152: case 'gamespy3': // not sure if gamespy3 supports ut colors but won't hurt
153: case 'gamespy2':
154: return [$this, 'stripUnreal'];
155:
156: // Strip Protocols using Source color tags
157: case 'source':
158: return [$this, 'stripSource'];
159:
160: default:
161: return null;
162: }
163: }
164: }
165: