summaryrefslogtreecommitdiff
path: root/framework/Web/Services/TFeedService.php
blob: 75775f49d1938f3d184cb5c329a7540ae87b7c3c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
<?php
/**
 * TFeedService and TFeed class file
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @author Knut Urdalen <knut.urdalen@gmail.com>
 * @link http://www.pradosoft.com
 * @copyright Copyright &copy; 2005-2014 PradoSoft
 * @license http://www.pradosoft.com/license/
 * @version $Id$
 * @package System.Web.Services
 */

/**
 * TFeedService class
 *
 * TFeedService provides to end-users feed content.
 *
 * TFeedService manages a set of feeds. The service parameter, referring
 * to the ID of the feed, specifies which feed content to be provided to end-users.
 *
 * To use TFeedService, configure it in application configuration as follows,
 * <code>
 *  <service id="feed" class="System.Web.Services.TFeedService">
 *    <feed id="ch1" class="Path.To.FeedClass1" .../>
 *    <feed id="ch2" class="Path.To.FeedClass2" .../>
 *    <feed id="ch3" class="Path.To.FeedClass3" .../>
 *  </service>
 * </code>
 * where each &lt;feed&gt; element specifies a feed identified by its "id" value (case-sensitive).
 *
 * PHP configuration style:
 * <code>
 * array(
 *   'feed' => array(
 *	   'ch1' => array(
 *       'class' => 'Path.To.FeedClass1',
 *       'properties' => array(
 *          ...
 *        ),
 *   ),
 * )
 * </code>
 *
 * The class attribute indicates which PHP class will provide the actual feed
 * content. Note, the class must implement {@link IFeedContentProvider} interface.
 * Other initial properties for the feed class may also be specified in the
 * corresponding &lt;feed&gt; element.
 *
 * To retrieve the feed content identified by "ch2", use the URL
 * <code>/path/to/index.php?feed=ch2</code>
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @author Knut Urdalen <knut.urdalen@gmail.com>
 * @author Carl G. Mathisen <carlgmathisen@gmail.com>
 * @package System.Web.Services
 * @since 3.1
 */
class TFeedService extends TService
{
	private $_feeds=array();

	/**
	 * Initializes this module.
	 * This method is required by the IModule interface.
	 * @param mixed configuration for this module, can be null
	 */
	public function init($config)
	{
		if($this->getApplication()->getConfigurationType()==TApplication::CONFIG_TYPE_PHP)
		{
			if(is_array($config))
			{
				foreach($config as $id => $feed)
					$this->_feeds[$id] = $feed;
			}
		}
		else
		{
			foreach($config->getElementsByTagName('feed') as $feed)
			{
				if(($id=$feed->getAttributes()->remove('id'))!==null)
					$this->_feeds[$id]=$feed;
				else
					throw new TConfigurationException('feedservice_id_required');
			}
		}
	}

	/**
	 * @return string the requested feed path
	 */
	protected function determineRequestedFeedPath()
	{
		return $this->getRequest()->getServiceParameter();
	}

	/**
	 * Runs the service.
	 * This method is invoked by application automatically.
	 */
	public function run()
	{
		$id=$this->getRequest()->getServiceParameter();
		if(isset($this->_feeds[$id]))
		{
			$feedConfig=$this->_feeds[$id];
			$properties = array();
			$feed = null;
			if($this->getApplication()->getConfigurationType()==TApplication::CONFIG_TYPE_PHP)
			{
				if(isset($feedConfig['class']))
				{
					$feed=Prado::createComponent($feedConfig['class']);
					if($service instanceof IFeedContentProvider)
						$properties=isset($feedConfig['properties'])?$feedConfig['properties']:array();
					else
						throw new TConfigurationException('jsonservice_response_type_invalid',$id);
				}
				else
					throw new TConfigurationException('jsonservice_class_required',$id);
			}
			else
			{
				$properties=$feedConfig->getAttributes();
				if(($class=$properties->remove('class'))!==null)
				{
					$feed=Prado::createComponent($class);
					if(!($feed instanceof IFeedContentProvider))
						throw new TConfigurationException('feedservice_feedtype_invalid',$id);
				}
				else
					throw new TConfigurationException('feedservice_class_required',$id);
			}

			// init feed properties
			foreach($properties as $name=>$value)
				$feed->setSubproperty($name,$value);
			$feed->init($feedConfig);

			$content=$feed->getFeedContent();
		    //$this->getResponse()->setContentType('application/rss+xml');
		    $this->getResponse()->setContentType($feed->getContentType());
		    $this->getResponse()->write($content);
		}
		else
			throw new THttpException(404,'feedservice_feed_unknown',$id);
	}
}

/**
 * IFeedContentProvider interface.
 *
 * IFeedContentProvider interface must be implemented by a feed class who
 * provides feed content.
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @author Knut Urdalen <knut.urdalen@gmail.com>
 * @package System.Web.Services
 * @since 3.1
 */
interface IFeedContentProvider
{
	/**
	 * Initializes the feed content provider.
	 * This method is invoked (before {@link getFeedContent})
	 * when the feed provider is requested by a user.
	 * @param TXmlElement configurations specified within the &lt;feed&gt; element
	 * corresponding to this feed provider when configuring {@link TFeedService}.
	 */
	public function init($config);
	/**
	 * @return string feed content in proper XML format
	 */
	public function getFeedContent();
	/**
	 * Sets the content type of the feed content to be sent.
	 * Some examples are:
	 * RSS 1.0 feed: application/rdf+xml
	 * RSS 2.0 feed: application/rss+xml or application/xml or text/xml
	 * ATOM feed: application/atom+xml
	 * @return string the content type for the feed content.
	 * @since 3.1.1
	 */
	public function getContentType();
}