FeedController::setup()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 17
rs 9.7
cc 2
nc 2
nop 0
1
<?php
2
3
namespace Alpha\Controller;
4
5
use Alpha\Util\Logging\Logger;
6
use Alpha\Util\Logging\LogProviderFile;
7
use Alpha\Util\Feed\RSS2;
8
use Alpha\Util\Feed\RSS;
9
use Alpha\Util\Feed\Atom;
10
use Alpha\Util\Http\Request;
11
use Alpha\Util\Http\Response;
12
use Alpha\Util\Config\ConfigProvider;
13
use Alpha\Exception\ResourceNotFoundException;
14
use Alpha\Exception\IllegalArguementException;
15
use Alpha\Model\Article;
16
17
/**
18
 * Controller for viewing news feeds.
19
 *
20
 * @since 1.0
21
 *
22
 * @author John Collins <[email protected]>
23
 * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
24
 * @copyright Copyright (c) 2018, John Collins (founder of Alpha Framework).
25
 * All rights reserved.
26
 *
27
 * <pre>
28
 * Redistribution and use in source and binary forms, with or
29
 * without modification, are permitted provided that the
30
 * following conditions are met:
31
 *
32
 * * Redistributions of source code must retain the above
33
 *   copyright notice, this list of conditions and the
34
 *   following disclaimer.
35
 * * Redistributions in binary form must reproduce the above
36
 *   copyright notice, this list of conditions and the
37
 *   following disclaimer in the documentation and/or other
38
 *   materials provided with the distribution.
39
 * * Neither the name of the Alpha Framework nor the names
40
 *   of its contributors may be used to endorse or promote
41
 *   products derived from this software without specific
42
 *   prior written permission.
43
 *
44
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
45
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
46
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
47
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
48
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
49
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
50
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
51
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
52
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
54
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
55
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
56
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
57
 * </pre>
58
 */
59
class FeedController extends Controller implements ControllerInterface
60
{
61
    /**
62
     * The name of the Record to render as a feed.
63
     *
64
     * @var string
65
     *
66
     * @since 1.0
67
     */
68
    private $ActiveRecordType;
69
70
    /**
71
     * The type of feed to render (RSS, RSS2 or Atom).
72
     *
73
     * @var string
74
     *
75
     * @since 1.0
76
     */
77
    private $type;
78
79
    /**
80
     * The title of the feed.
81
     *
82
     * @var string
83
     *
84
     * @since 1.0
85
     */
86
    protected $title;
87
88
    /**
89
     * The description of the feed.
90
     *
91
     * @var string
92
     *
93
     * @since 1.0
94
     */
95
    protected $description;
96
97
    /**
98
     * The Record to feed field mappings.
99
     *
100
     * @var array
101
     *
102
     * @since 1.0
103
     */
104
    protected $fieldMappings;
105
106
    /**
107
     * The Record field name to sort the feed by (descending), default is ID.
108
     *
109
     * @var string
110
     *
111
     * @since 1.0
112
     */
113
    private $sortBy = 'ID';
114
115
    /**
116
     * Trace logger.
117
     *
118
     * @var \Alpha\Util\Logging\Logger
119
     *
120
     * @since 1.0
121
     */
122
    private static $logger = null;
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
123
124
    /**
125
     * constructor to set up the object.
126
     *
127
     * @since 1.0
128
     */
129
    public function __construct()
130
    {
131
        self::$logger = new Logger('FeedController');
132
        self::$logger->debug('>>__construct()');
133
134
        // ensure that the super class constructor is called, indicating the rights group
135
        parent::__construct('Public');
136
137
        self::$logger->debug('<<__construct');
138
    }
139
140
    /**
141
     * Handle GET requests.
142
     *
143
     * @param \Alpha\Util\Http\Request $request
144
     *
145
     * @return \Alpha\Util\Http\Response
146
     *
147
     * @since 1.0
148
     *
149
     * @throws \Alpha\Exception\ResourceNotFoundException
150
     */
151
    public function doGET($request)
152
    {
153
        self::$logger->debug('>>doGET($request=['.var_export($request, true).'])');
154
155
        $config = ConfigProvider::getInstance();
156
157
        $params = $request->getParams();
158
159
        $response = new Response(200);
160
161
        try {
162
            if (isset($params['ActiveRecordType'])) {
163
                $ActiveRecordType = urldecode($params['ActiveRecordType']);
164
            } else {
165
                throw new IllegalArguementException('ActiveRecordType not specified to generate feed!');
166
            }
167
168
            if (isset($params['type'])) {
169
                $type = $params['type'];
170
            } else {
171
                throw new IllegalArguementException('No feed type specified to generate feed!');
172
            }
173
174
            if (class_exists($ActiveRecordType)) {
175
                $this->ActiveRecordType = $ActiveRecordType;
176
            } else {
177
                throw new IllegalArguementException('No ActiveRecord available to render!');
178
            }
179
            $this->type = $type;
180
181
            $this->setup();
182
183
            $feed = null;
184
            
185
            switch ($type) {
186
                case 'RSS2':
187
                    $feed = new RSS2($this->ActiveRecordType, $this->title, str_replace('&', '&amp;', $request->getURI()), $this->description);
188
                    $feed->setFieldMappings($this->fieldMappings[0], $this->fieldMappings[1], $this->fieldMappings[2], $this->fieldMappings[3]);
189
                    $response->setHeader('Content-Type', 'application/rss+xml');
190
                break;
191
                case 'RSS':
192
                    $feed = new RSS($this->ActiveRecordType, $this->title, str_replace('&', '&amp;', $request->getURI()), $this->description);
193
                    $feed->setFieldMappings($this->fieldMappings[0], $this->fieldMappings[1], $this->fieldMappings[2], $this->fieldMappings[3]);
194
                    $response->setHeader('Content-Type', 'application/rss+xml');
195
                break;
196
                case 'Atom':
197
                    $feed = new Atom($this->ActiveRecordType, $this->title, str_replace('&', '&amp;', $request->getURI()), $this->description);
198
                    $feed->setFieldMappings($this->fieldMappings[0], $this->fieldMappings[1], $this->fieldMappings[2], $this->fieldMappings[3],
199
                        $this->fieldMappings[4]);
200
                    if ($config->get('feeds.atom.author') != '') {
201
                        $feed->addAuthor($config->get('feeds.atom.author'));
202
                    }
203
                    $response->setHeader('Content-Type', 'application/atom+xml');
204
                break;
205
            }
206
207
            // now add the twenty last items (from newest to oldest) to the feed, and render
208
            $feed->loadRecords(20, $this->sortBy);
209
            $response->setBody($feed->render());
210
211
            // log the request for this news feed
212
            $feedLog = new LogProviderFile();
213
            $feedLog->setPath($config->get('app.file.store.dir').'logs/feeds.log');
214
            $feedLog->writeLine(array($this->ActiveRecordType, $this->type, date('Y-m-d H:i:s'), $request->getUserAgent(), $request->getIP()));
215
        } catch (IllegalArguementException $e) {
216
            self::$logger->error($e->getMessage());
217
            throw new ResourceNotFoundException($e->getMessage());
218
        }
219
220
        self::$logger->debug('<<doGet');
221
222
        return $response;
223
    }
224
225
    /**
226
     * setup the feed title, field mappings and description based on common Record types.
227
     */
228
    protected function setup()
229
    {
230
        self::$logger->debug('>>setup()');
231
232
        $config = ConfigProvider::getInstance();
233
234
        $bo = new $this->ActiveRecordType();
235
236
        if ($bo instanceof Article) {
237
            $this->title = 'Latest articles from '.$config->get('app.title');
238
            $this->description = 'News feed containing all of the details on the latest articles published on '.$config->get('app.title').'.';
239
            $this->fieldMappings = array('title', 'URL', 'description', 'created_ts', 'ID');
240
            $this->sortBy = 'created_ts';
241
        }
242
243
        self::$logger->debug('<<setup');
244
    }
245
}
246