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