Overview

Namespaces

  • Peach
    • DF
    • DT
    • Http
      • Body
      • Header
    • Markup
    • Util

Classes

  • Peach\DF\Base64Codec
  • Peach\DF\CodecChain
  • Peach\DF\JsonCodec
  • Peach\DF\SerializationCodec
  • Peach\DF\Utf8Codec
  • Peach\DT\AbstractTime
  • Peach\DT\Clock
  • Peach\DT\Date
  • Peach\DT\Datetime
  • Peach\DT\DefaultClock
  • Peach\DT\FixedClock
  • Peach\DT\FormatWrapper
  • Peach\DT\HttpDateFormat
  • Peach\DT\OffsetClock
  • Peach\DT\ShiftFormat
  • Peach\DT\SimpleFormat
  • Peach\DT\TimeEquator
  • Peach\DT\Timestamp
  • Peach\DT\TimeWrapper
  • Peach\DT\UnixTimeFormat
  • Peach\DT\Util
  • Peach\DT\W3cDatetimeFormat
  • Peach\Http\Body
  • Peach\Http\Body\CodecRenderer
  • Peach\Http\Body\StringRenderer
  • Peach\Http\DefaultEndpoint
  • Peach\Http\Header\CookieItem
  • Peach\Http\Header\CookieOptions
  • Peach\Http\Header\HttpDate
  • Peach\Http\Header\NoField
  • Peach\Http\Header\QualityValues
  • Peach\Http\Header\Raw
  • Peach\Http\Header\SetCookie
  • Peach\Http\Header\Status
  • Peach\Http\Request
  • Peach\Http\Response
  • Peach\Http\Util
  • Peach\Markup\AbstractHelper
  • Peach\Markup\AbstractRenderer
  • Peach\Markup\BaseHelper
  • Peach\Markup\BreakControlWrapper
  • Peach\Markup\Builder
  • Peach\Markup\Code
  • Peach\Markup\Comment
  • Peach\Markup\ContainerElement
  • Peach\Markup\Context
  • Peach\Markup\DebugBuilder
  • Peach\Markup\DebugContext
  • Peach\Markup\DefaultBreakControl
  • Peach\Markup\DefaultBuilder
  • Peach\Markup\DefaultContext
  • Peach\Markup\Element
  • Peach\Markup\EmptyElement
  • Peach\Markup\HelperObject
  • Peach\Markup\HtmlHelper
  • Peach\Markup\Indent
  • Peach\Markup\MinimalBreakControl
  • Peach\Markup\NameBreakControl
  • Peach\Markup\NameValidator
  • Peach\Markup\NodeList
  • Peach\Markup\None
  • Peach\Markup\SgmlRenderer
  • Peach\Markup\Text
  • Peach\Markup\XmlRenderer
  • Peach\Util\AbstractMapEntry
  • Peach\Util\ArrayMap
  • Peach\Util\ArrayMapEntry
  • Peach\Util\Arrays
  • Peach\Util\DefaultComparator
  • Peach\Util\DefaultEquator
  • Peach\Util\HashMap
  • Peach\Util\HashMapEntry
  • Peach\Util\Strings
  • Peach\Util\Values

Interfaces

  • Peach\DF\Codec
  • Peach\DT\Format
  • Peach\DT\Time
  • Peach\Http\BodyRenderer
  • Peach\Http\Endpoint
  • Peach\Http\HeaderField
  • Peach\Http\MultiHeaderField
  • Peach\Http\SingleHeaderField
  • Peach\Markup\BreakControl
  • Peach\Markup\Component
  • Peach\Markup\Container
  • Peach\Markup\Helper
  • Peach\Markup\Node
  • Peach\Markup\Renderer
  • Peach\Util\Comparable
  • Peach\Util\Comparator
  • Peach\Util\Equator
  • Peach\Util\Map
  • Peach\Util\MapEntry
  • Overview
  • Namespace
  • Class
  1: <?php
  2: /*
  3:  * Copyright (c) 2014 @trashtoy
  4:  * https://github.com/trashtoy/
  5:  * 
  6:  * Permission is hereby granted, free of charge, to any person obtaining a copy of
  7:  * this software and associated documentation files (the "Software"), to deal in
  8:  * the Software without restriction, including without limitation the rights to use,
  9:  * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
 10:  * Software, and to permit persons to whom the Software is furnished to do so,
 11:  * subject to the following conditions:
 12:  * 
 13:  * The above copyright notice and this permission notice shall be included in all
 14:  * copies or substantial portions of the Software.
 15:  * 
 16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 18:  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 19:  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 20:  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 21:  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 22:  */
 23: /**
 24:  * PHP class file.
 25:  * @auhtor trashtoy
 26:  * @since  2.0.0
 27:  */
 28: namespace Peach\Markup;
 29: use Peach\Util\Strings;
 30: 
 31: /**
 32:  * 与えられたノードを HTML や XML などの文字列に変換するクラスです.
 33:  */
 34: class DefaultContext extends Context
 35: {
 36:     /**
 37:      * マークアップ時の改行やインデント処理を担当します.
 38:      * @var Indent
 39:      */
 40:     private $indent;
 41:     
 42:     /**
 43:      * タグの出力方式 (空要素や boolean 属性などの扱い) を制御します.
 44:      * @var Renderer
 45:      */
 46:     private $renderer;
 47:     
 48:     /**
 49:      * 開始タグの直後に改行するかどうかの判定を行います.
 50:      * @var BreakControl
 51:      */
 52:     private $breakControl;
 53:     
 54:     /**
 55:      * TRUE の場合はノードの前後にインデントと改行を付加します.
 56:      * @var bool
 57:      */
 58:     private $isIndentMode;
 59:     
 60:     /**
 61:      * TRUE の場合はコメントの内部を処理している状態とみなします.
 62:      * コメントの内部にあるコメントは無視するようになります.
 63:      * @var bool
 64:      */
 65:     private $isCommentMode;
 66:     
 67:     /**
 68:      * handle() メソッド実行時の処理結果が格納されます.
 69:      * @var string
 70:      */
 71:     private $result;
 72:     
 73:     /**
 74:      * 指定された Renderer, Indent, BreakControl オブジェクトを使って
 75:      * マークアップを行う DefaultContext オブジェクトを構築します.
 76:      * 
 77:      * @param Renderer     $renderer
 78:      * @param Indent       $indent
 79:      * @param BreakControl $breakControl
 80:      */
 81:     public function __construct(Renderer $renderer, Indent $indent = null, BreakControl $breakControl = null)
 82:     {
 83:         if (!isset($indent)) {
 84:             $indent = new Indent();
 85:         }
 86:         if (!isset($breakControl)) {
 87:             $breakControl = DefaultBreakControl::getInstance();
 88:         }
 89:         $this->renderer      = $renderer;
 90:         $this->indent        = $indent;
 91:         $this->breakControl  = $breakControl;
 92:         $this->isIndentMode  = true;
 93:         $this->isCommentMode = false;
 94:         $this->result        = "";
 95:     }
 96:     
 97:     /**
 98:      * コメントノードを読み込みます.
 99:      * @param Comment $comment
100:      */
101:     public function handleComment(Comment $comment)
102:     {
103:         if ($this->isCommentMode) {
104:             $this->formatChildNodes($comment);
105:             return;
106:         }
107:         
108:         $this->isCommentMode = true;
109:         $prefix = $this->escapeEndComment($comment->getPrefix());
110:         $suffix = $this->escapeEndComment($comment->getSuffix());
111:         $this->result .= $this->indent() . "<!--{$prefix}";
112:         if ($this->isIndentMode) {
113:             if ($this->checkBreakModeInComment($comment)) {
114:                 $breakCode = $this->breakCode();
115:                 $this->result .= $breakCode;
116:                 $this->formatChildNodes($comment);
117:                 $this->result .= $breakCode;
118:                 $this->result .= $this->indent();
119:             } else {
120:                 $this->isIndentMode = false;
121:                 $this->formatChildNodes($comment);
122:                 $this->isIndentMode = true;
123:             }
124:         } else {
125:             $this->formatChildNodes($comment);
126:         }
127:         $this->result .= "{$suffix}-->";
128:         $this->isCommentMode = false;
129:     }
130:     
131:     /**
132:      * コメントノードを 1 行 ("<--foobar-->") で記述するか改行するかの判定を行います.
133:      * 
134:      * @param  Comment $comment
135:      * @return bool
136:      */
137:     private function checkBreakModeInComment(Comment $comment)
138:     {
139:         $nodes = $comment->getChildNodes();
140:         switch (count($nodes)) {
141:             case 0:
142:                 return false;
143:             case 1:
144:                 $node = $nodes[0];
145:                 if ($node instanceof Comment) {
146:                     return $this->checkBreakModeInComment($node);
147:                 }
148:                 
149:                 return ($node instanceof Element);
150:             default:
151:                 return true;
152:         }
153:     }
154:     
155:     /**
156:      * Text ノードを読み込みます.
157:      * @param Text $text
158:      */
159:     public function handleText(Text $text) {
160:         $this->result .= $this->indent() . $this->escape($text->getText());
161:     }
162:     
163:     /**
164:      * Code を読み込みます.
165:      * @param Code $code
166:      */
167:     public function handleCode(Code $code)
168:     {
169:         $text   = $code->getText();
170:         if (!strlen($text)) {
171:             return;
172:         }
173:         
174:         $lines  = Strings::getLines($text);
175:         $indent = $this->indent();
176:         $this->result .= $indent;
177:         $this->result .= implode($this->breakCode() . $indent, $lines);
178:     }
179:     
180:     /**
181:      * EmptyElement を読み込みます.
182:      * @param EmptyElement $element
183:      * @see Context::handleEmptyElement()
184:      */
185:     public function handleEmptyElement(EmptyElement $element) {
186:         $this->result .= $this->indent() . $this->renderer->formatEmptyTag($element);
187:     }
188:     
189:     /**
190:      * ContainerElement を読み込みます.
191:      * @param ContainerElement $element
192:      * @see Context::handleContainerElement()
193:      */
194:     public function handleContainerElement(ContainerElement $element)
195:     {
196:         $this->result .= $this->indent() . $this->renderer->formatStartTag($element);
197:         if ($this->isIndentMode) {
198:             if ($this->breakControl->breaks($element)) {
199:                 $this->result .= $this->indent->stepUp();
200:                 $this->result .= $this->formatChildNodes($element);
201:                 $this->result .= $this->breakCode();
202:                 $this->result .= $this->indent->stepDown();
203:             } else {
204:                 $this->isIndentMode = false;
205:                 $this->formatChildNodes($element);
206:                 $this->isIndentMode = true;
207:             }
208:         } else {
209:            $this->formatChildNodes($element);
210:         }
211:         $this->result .= $this->renderer->formatEndTag($element);
212:     }
213:     
214:     /**
215:      * NodeList を変換します.
216:      * @param NodeList $node
217:      */
218:     public function handleNodeList(NodeList $node)
219:     {
220:         $this->formatChildNodes($node);
221:     }
222:     
223:     /**
224:      * マークアップされたコードを返します.
225:      * @return string
226:      */
227:     public function getResult()
228:     {
229:         return $this->result;
230:     }
231:     
232:     /**
233:      * 指定されたコンテナの子ノードを書式化します.
234:      * 各子ノードの出力結果の末尾には, 改行コードで連結されます. (インデントモードが ON の場合)
235:      * 末尾の子ノードの出力結果の後ろに改行コードは付きません.
236:      * 
237:      * @param Container $container
238:      */
239:     private function formatChildNodes(Container $container)
240:     {
241:         $nextBreak  = "";
242:         $breakCode  = $this->breakCode();
243:         $childNodes = $container->getChildNodes();
244:         foreach ($childNodes as $child) {
245:             $this->result .= $nextBreak;
246:             $this->handle($child);
247:             $nextBreak = $breakCode;
248:         }
249:     }
250:     
251:     /**
252:      * None を処理します. 何もせずに終了します.
253:      * 
254:      * @param None $none
255:      */
256:     public function handleNone(None $none)
257:     {
258:     }
259:     
260:     /**
261:      * インデントモードが ON の場合は空白文字, OFF の場合は空文字列を返します.
262:      * @return string
263:      */
264:     private function indent()
265:     {
266:         return $this->isIndentMode ? $this->indent->indent() : "";
267:     }
268:     
269:     /**
270:      * インデントモードが ON の場合は改行コード, OFF の場合は空文字列を返します.
271:      * @return string
272:      */
273:     private function breakCode()
274:     {
275:         return $this->isIndentMode ? $this->indent->breakCode() : "";
276:     }
277:     
278:     /**
279:      * 予期しないインデントを回避するため, 改行コードを文字参照に置き換えます.
280:      * @param  string $text
281:      * @return string
282:      */
283:     private function escape($text)
284:     {
285:         return preg_replace("/\\r\\n|\\r|\\n/", "&#xa;", htmlspecialchars($text));
286:     }
287:     
288:     /**
289:      * 意図しないタイミングでコメントノードが終了するのを防ぐため, "-->" を文字参照に置き換えます.
290:      * @param  string $text
291:      * @return string
292:      */
293:     private function escapeEndComment($text)
294:     {
295:         return str_replace("-->", "--&gt;", $text);
296:     }
297: }
298: 
PEACH2 API documentation generated by ApiGen