1<?php
2/**
3 * The Horde_SyncMl_Command class provides a base class for handling all
4 * <SyncBody> commands.
5 *
6 * A SyncML command is a protocol primitive. Each SyncML command specifies to a
7 * recipient an individual operation that is to be performed.
8 *
9 * The Horde_SyncMl_Command objects are hooked into the XML parser of the
10 * Horde_SyncMl_ContentHandler class and are reponsible for parsing a single
11 * command inside the SyncBody section of a SyncML message. All actions that
12 * must be executed for a single SyncML command are handled by these objects,
13 * by means of the handleCommand() method.
14 *
15 * Copyright 2003-2016 Horde LLC (http://www.horde.org/)
16 *
17 * See the enclosed file COPYING for license information (LGPL). If you
18 * did not receive this file, see http://www.horde.org/licenses/lgpl21.
19 *
20 * @author  Anthony Mills <amills@pyramid6.com>
21 * @author  Jan Schneider <jan@horde.org>
22 * @package SyncMl
23 */
24class Horde_SyncMl_Command
25{
26    /**
27     * Name of the command, like 'Put'.
28     *
29     * Must be overwritten by a sub class.
30     *
31     * @var string
32     */
33    protected $_cmdName;
34
35    /**
36     * The command ID (<CmdID>).
37     *
38     * @var integer
39     */
40    protected $_cmdID;
41
42    /**
43     * Stack for holding the XML elements during creation of the object from
44     * the XML event flow.
45     *
46     * @var array
47     */
48    protected $_stack = array();
49
50    /**
51     * Buffer for the parsed character data.
52     *
53     * @var string
54     */
55    protected $_chars = '';
56
57    /**
58     * A Horde_SyncMl_XmlOutput instance responsible for generating the output.
59     *
60     * @var Horde_SyncMl_XmlOutput
61     */
62    protected $_outputHandler;
63
64    /**
65     * Constructor.
66     *
67     * @param Horde_SyncMl_XmlOutput $outputHandler  A Horde_SyncMl_XmlOutput object.
68     */
69    public function __construct(&$outputHandler)
70    {
71        $this->_outputHandler = &$outputHandler;
72    }
73
74    /**
75     * Start element handler for the XML parser, delegated from
76     * Horde_SyncMl_ContentHandler::startElement().
77     *
78     * @param string $uri      The namespace URI of the element.
79     * @param string $element  The element tag name.
80     * @param array $attrs     A hash with the element's attributes.
81     */
82    public function startElement($uri, $element, $attrs)
83    {
84        $this->_stack[] = $element;
85    }
86
87    /**
88     * End element handler for the XML parser, delegated from
89     * Horde_SyncMl_ContentHandler::endElement().
90     *
91     * @param string $uri      The namespace URI of the element.
92     * @param string $element  The element tag name.
93     */
94    public function endElement($uri, $element)
95    {
96        if (count($this->_stack) == 2 &&
97            $element == 'CmdID') {
98            $this->_cmdID = intval(trim($this->_chars));
99        }
100
101        if (strlen($this->_chars)) {
102            $this->_chars = '';
103        }
104
105        array_pop($this->_stack);
106    }
107
108    /**
109     * Character data handler for the XML parser, delegated from
110     * Horde_SyncMl_ContentHandler::characters().
111     *
112     * @param string $str  The data string.
113     */
114    public function characters($str)
115    {
116        $this->_chars .= $str;
117    }
118
119    /**
120     * Returns the command name this instance is reponsible for.
121     *
122     * @return string  The command name this object is handling.
123     */
124    public function getCommandName()
125    {
126        return $this->_cmdName;
127    }
128
129    /**
130     * This method is supposed to implement the actual business logic of the
131     * command once the XML parsing is complete.
132     *
133     * @abstract
134     */
135    public function handleCommand($debug = false)
136    {
137    }
138
139    /**
140     * Attempts to return a concrete Horde_SyncMl_Command instance based on
141     * $command.
142     *
143     * @param string $command                  The type of the concrete
144     *                                         Horde_SyncMl_Comment subclass to
145     *                                         return.
146     * @param Horde_SyncMl_XmlOutput $outputHandler  A Horde_SyncMl_XmlOutput object.
147     *
148     * @return Horde_SyncMl_Command  The newly created concrete Horde_SyncMl_Command
149     *                         instance, or false on error.
150     */
151    public function &factory($command, &$outputHandler)
152    {
153        $command = basename($command);
154        $class = 'Horde_SyncMl_Command_' . $command;
155        if (class_exists($class)) {
156            $cmd = new $class($outputHandler);
157        } else {
158            $msg = 'Class definition of ' . $class . ' not found.';
159            $GLOBALS['backend']->logMessage($msg, __FILE__, __LINE__, 'ERR');
160            $cmd = PEAR::raiseError($msg);
161        }
162
163        return $cmd;
164    }
165}
166