1<?php
2/**
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
17 *
18 * @file
19 * @ingroup Parser
20 */
21
22/**
23 * @ingroup Parser
24 *
25 * @property int $startPos
26 */
27class PPDStackElement {
28	/**
29	 * @var string Opening character (\n for heading)
30	 */
31	public $open;
32
33	/**
34	 * @var string Matching closing character
35	 */
36	public $close;
37
38	/**
39	 * @var string Saved prefix that may affect later processing,
40	 *  e.g. to differentiate `-{{{{` and `{{{{` after later seeing `}}}`.
41	 */
42	public $savedPrefix = '';
43
44	/**
45	 * @var int Number of opening characters found (number of "=" for heading)
46	 */
47	public $count;
48
49	/**
50	 * @var PPDPart[] Array of PPDPart objects describing pipe-separated parts.
51	 */
52	public $parts;
53
54	/**
55	 * @var bool True if the open char appeared at the start of the input line.
56	 *  Not set for headings.
57	 */
58	public $lineStart;
59
60	public $partClass = PPDPart::class;
61
62	public function __construct( $data = [] ) {
63		$class = $this->partClass;
64		$this->parts = [ new $class ];
65
66		foreach ( $data as $name => $value ) {
67			$this->$name = $value;
68		}
69	}
70
71	public function &getAccum() {
72		return $this->parts[count( $this->parts ) - 1]->out;
73	}
74
75	public function addPart( $s = '' ) {
76		$class = $this->partClass;
77		$this->parts[] = new $class( $s );
78	}
79
80	/**
81	 * @return PPDPart
82	 */
83	public function getCurrentPart() {
84		return $this->parts[count( $this->parts ) - 1];
85	}
86
87	/**
88	 * @return array
89	 */
90	public function getFlags() {
91		$partCount = count( $this->parts );
92		$findPipe = $this->open != "\n" && $this->open != '[';
93		return [
94			'findPipe' => $findPipe,
95			'findEquals' => $findPipe && $partCount > 1 && !isset( $this->parts[$partCount - 1]->eqpos ),
96			'inHeading' => $this->open == "\n",
97		];
98	}
99
100	/**
101	 * Get the output string that would result if the close is not found.
102	 *
103	 * @param bool|int $openingCount
104	 * @return string
105	 */
106	public function breakSyntax( $openingCount = false ) {
107		if ( $this->open == "\n" ) {
108			$s = $this->savedPrefix . $this->parts[0]->out;
109		} else {
110			if ( $openingCount === false ) {
111				$openingCount = $this->count;
112			}
113			$s = substr( $this->open, 0, -1 );
114			$s .= str_repeat(
115				substr( $this->open, -1 ),
116				$openingCount - strlen( $s )
117			);
118			$s = $this->savedPrefix . $s;
119			$first = true;
120			foreach ( $this->parts as $part ) {
121				if ( $first ) {
122					$first = false;
123				} else {
124					$s .= '|';
125				}
126				$s .= $part->out;
127			}
128		}
129		return $s;
130	}
131}
132