1: <?php
2:
3: /**
4: * Jyxo PHP Library
5: *
6: * LICENSE
7: *
8: * This source file is subject to the new BSD license that is bundled
9: * with this package in the file license.txt.
10: * It is also available through the world-wide-web at this URL:
11: * https://github.com/jyxo/php/blob/master/license.txt
12: */
13:
14: namespace Jyxo\Gettext;
15:
16: /**
17: * Parses Gettext PO files.
18: *
19: * @category Jyxo
20: * @package Jyxo\Gettext
21: * @subpackage Parser
22: * @copyright Copyright (c) 2005-2011 Jyxo, s.r.o.
23: * @license https://github.com/jyxo/php/blob/master/license.txt
24: * @author Matěj Humpál
25: */
26: class Parser implements \Iterator, \Countable
27: {
28:
29: /**
30: * Path to the parsed PO file.
31: *
32: * @var string
33: */
34: protected $file;
35:
36: /**
37: * PO file header (copyright and other information).
38: *
39: * @var string
40: */
41: protected $header;
42:
43: /**
44: * Fragments parsed from the PO file.
45: *
46: * @var array of \Jyxo\Gettext\Parser\Item
47: */
48: protected $items = array();
49:
50: /**
51: * Internal pointer to the fragments array.
52: *
53: * @var integer
54: */
55: protected $current = 0;
56:
57: /**
58: * Parser class name.
59: *
60: * Useful for subclassing.
61: *
62: * @var string
63: */
64: protected $itemClass = '\Jyxo\Gettext\Parser\Item';
65:
66: /**
67: * Header parser class name.
68: *
69: * Useful for subclassing.
70: *
71: * @var string
72: */
73: protected $headerClass = '\Jyxo\Gettext\Parser\Header';
74:
75: /**
76: * Constructor.
77: *
78: * Loads and parses the given file.
79: *
80: * @param string $file Path to the PO file.
81: */
82: public function __construct($file)
83: {
84: $this->parse($file);
85: }
86:
87: /**
88: * The actual parser.
89: *
90: * Walks through the file, splits it on empty lines and tries to parse each
91: * fragment using the defined parser class ({@link \Jyxo\Gettext\Parser\Item} by default).
92: *
93: * Does not work with the file header.
94: *
95: * @param string $file Path to the PO file
96: * @see \Jyxo\Gettext\Parser::$items
97: * @see \Jyxo\Gettext\Parser\Item
98: */
99: protected function parse($file)
100: {
101: $linenumber = 0;
102: $chunks = array();
103:
104: $file = file($file);
105: foreach ($file as $line) {
106: if ($line == "\n" || $line == "\r\n") {
107: ++$linenumber;
108: } else {
109: if (!array_key_exists($linenumber, $chunks)) {
110: $chunks[$linenumber] = '';
111: }
112: $chunks[$linenumber] .= $line;
113: }
114: }
115:
116: $header = array_shift($chunks);
117: $this->header = new $this->headerClass($header);
118:
119: foreach ($chunks as $chunk) {
120: try {
121: $this->items[] = new $this->itemClass($chunk);
122: } catch (\Jyxo\Gettext\Parser\Exception $e) {
123: // Do nothing, msgid is empty
124: }
125: }
126:
127: }
128:
129: /**
130: * {@link \Countable} interface method
131: *
132: * @return boolean
133: */
134: public function count()
135: {
136: return count($this->items);
137: }
138:
139: /**
140: * {@link \ArrayIterator} interface method.
141: *
142: * @return boolean
143: */
144: public function current()
145: {
146: return $this->items[$this->current];
147: }
148:
149: /**
150: * {@link \ArrayIterator} interface method.
151: *
152: * @return boolean
153: */
154: public function key()
155: {
156: return $this->current;
157: }
158:
159: /**
160: * {@link \ArrayIterator} interface method.
161: *
162: * @return boolean
163: */
164: public function next()
165: {
166: ++$this->current;
167: return $this->items[$this->current];
168: }
169:
170: /**
171: * {@link \ArrayIterator} interface method.
172: *
173: * @return boolean
174: */
175: public function rewind()
176: {
177: $this->current = 0;
178: return $this->items[$this->current];
179: }
180:
181: /**
182: * {@link \ArrayIterator} interface method.
183: *
184: * @return boolean
185: */
186: public function valid()
187: {
188: return isset($this->items[$this->current]);
189: }
190:
191: /**
192: * Method overloading.
193: *
194: * Makes getProperty methods available for retrieving property values
195: * Makes setProperty methods available for setting property values
196: *
197: * @param string $name Method name
198: * @param array $args Method parameters
199: * @return mixed Value of variable or \Jyxo\Gettext\Parser
200: * @throws \Jyxo\Gettext\Parser\Exception Non-existing method
201: */
202: public function __call($name, $args)
203: {
204: if (substr($name, 0, 3) == 'get' && $var = substr($name, 3)) {
205: $var = strtolower(substr($var, 0, 1)) . substr($var, 1);
206: if (!isset($this->$var)) {
207: throw new Parser\Exception(sprintf('Non-existing method %s::%s() called in %s, line %s', __CLASS__, $name, __FILE__, __LINE__));
208: }
209: return $this->$var;
210: } elseif (substr($name, 0, 3) == 'set' && $var = substr($name, 3)) {
211: $var = strtolower(substr($var, 0, 1)) . substr($var, 1);
212: if (!isset($this->$var)) {
213: throw new Parser\Exception(sprintf('Non-existing method %s::%s() called in %s, line %s', __CLASS__, $name, __FILE__, __LINE__));
214: }
215:
216: $this->$var = $args[0];
217: return $this;
218: }
219: }
220: }
221: