alphadevx /
alpha
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | |||
| 3 | namespace Alpha\Model; |
||
| 4 | |||
| 5 | use Alpha\Model\Type\SmallText; |
||
| 6 | use Alpha\Model\Type\DEnum; |
||
| 7 | use Alpha\Model\Type\Text; |
||
| 8 | use Alpha\Model\Type\LargeText; |
||
| 9 | use Alpha\Model\Type\Boolean; |
||
| 10 | use Alpha\Model\Type\Relation; |
||
| 11 | use Alpha\Util\Config\Configprovider; |
||
| 12 | use Alpha\Util\Logging\Logger; |
||
| 13 | use Alpha\Util\Service\ServiceFactory; |
||
| 14 | use Alpha\Exception\ValidationException; |
||
| 15 | use Alpha\Exception\FileNotFoundException; |
||
| 16 | use Alpha\Exception\AlphaException; |
||
| 17 | use Alpha\Controller\Front\FrontController; |
||
| 18 | |||
| 19 | /** |
||
| 20 | * An article class for the CMS. |
||
| 21 | * |
||
| 22 | * @since 1.0 |
||
| 23 | * |
||
| 24 | * @author John Collins <[email protected]> |
||
| 25 | * @license http://www.opensource.org/licenses/bsd-license.php The BSD License |
||
| 26 | * @copyright Copyright (c) 2018, John Collins (founder of Alpha Framework). |
||
| 27 | * All rights reserved. |
||
| 28 | * |
||
| 29 | * <pre> |
||
| 30 | * Redistribution and use in source and binary forms, with or |
||
| 31 | * without modification, are permitted provided that the |
||
| 32 | * following conditions are met: |
||
| 33 | * |
||
| 34 | * * Redistributions of source code must retain the above |
||
| 35 | * copyright notice, this list of conditions and the |
||
| 36 | * following disclaimer. |
||
| 37 | * * Redistributions in binary form must reproduce the above |
||
| 38 | * copyright notice, this list of conditions and the |
||
| 39 | * following disclaimer in the documentation and/or other |
||
| 40 | * materials provided with the distribution. |
||
| 41 | * * Neither the name of the Alpha Framework nor the names |
||
| 42 | * of its contributors may be used to endorse or promote |
||
| 43 | * products derived from this software without specific |
||
| 44 | * prior written permission. |
||
| 45 | * |
||
| 46 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND |
||
| 47 | * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, |
||
| 48 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||
| 49 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||
| 50 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR |
||
| 51 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||
| 52 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
||
| 53 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||
| 54 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||
| 55 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||
| 56 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
||
| 57 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||
| 58 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
| 59 | * </pre> |
||
| 60 | */ |
||
| 61 | class Article extends ActiveRecord |
||
| 62 | { |
||
| 63 | /** |
||
| 64 | * The article title. |
||
| 65 | * |
||
| 66 | * @var \Alpha\Model\Type\SmallText |
||
| 67 | * |
||
| 68 | * @since 1.0 |
||
| 69 | */ |
||
| 70 | protected $title; |
||
| 71 | |||
| 72 | /** |
||
| 73 | * The description of the article. |
||
| 74 | * |
||
| 75 | * @var \Alpha\Model\Type\SmallText |
||
| 76 | * |
||
| 77 | * @since 1.0 |
||
| 78 | */ |
||
| 79 | protected $description; |
||
| 80 | |||
| 81 | /** |
||
| 82 | * Optional custom body onload Javascript. |
||
| 83 | * |
||
| 84 | * @var \Alpha\Model\Type\SmallText |
||
| 85 | * |
||
| 86 | * @since 1.0 |
||
| 87 | */ |
||
| 88 | protected $bodyOnload; |
||
| 89 | |||
| 90 | /** |
||
| 91 | * Any custom HTML header content (e.g. Javascript) for the article. |
||
| 92 | * |
||
| 93 | * @var \Alpha\Model\Type\Text |
||
| 94 | * |
||
| 95 | * @since 1.0 |
||
| 96 | */ |
||
| 97 | protected $headerContent; |
||
| 98 | |||
| 99 | /** |
||
| 100 | * The article content. |
||
| 101 | * |
||
| 102 | * @var \Alpha\Model\Type\LargeText |
||
| 103 | * |
||
| 104 | * @since 1.0 |
||
| 105 | */ |
||
| 106 | protected $content; |
||
| 107 | |||
| 108 | /** |
||
| 109 | * The author of the article. |
||
| 110 | * |
||
| 111 | * @var \Alpha\Model\Type\SmallText |
||
| 112 | * |
||
| 113 | * @since 1.0 |
||
| 114 | */ |
||
| 115 | protected $author; |
||
| 116 | |||
| 117 | /** |
||
| 118 | * A boolean to control whether the artcile is publically accessible or not. |
||
| 119 | * |
||
| 120 | * @var \Alpha\Model\Type\Boolean |
||
| 121 | * |
||
| 122 | * @since 1.0 |
||
| 123 | */ |
||
| 124 | protected $published; |
||
| 125 | |||
| 126 | /** |
||
| 127 | * A Relation containing all of the comments on this article. |
||
| 128 | * |
||
| 129 | * @var \Alpha\Model\Type\Relation |
||
| 130 | * |
||
| 131 | * @since 1.0 |
||
| 132 | */ |
||
| 133 | protected $comments; |
||
| 134 | |||
| 135 | /** |
||
| 136 | * A Relation containing all of the votes on this article. |
||
| 137 | * |
||
| 138 | * @var \Alpha\Model\Type\Relation |
||
| 139 | * |
||
| 140 | * @since 1.0 |
||
| 141 | */ |
||
| 142 | protected $votes; |
||
| 143 | |||
| 144 | /** |
||
| 145 | * A Relation containing all of the tags on this article. |
||
| 146 | * |
||
| 147 | * @var \Alpha\Model\Type\Relation |
||
| 148 | * |
||
| 149 | * @since 1.0 |
||
| 150 | */ |
||
| 151 | protected $tags; |
||
| 152 | |||
| 153 | /** |
||
| 154 | * An array of all of the attributes on this Record which are tagged. |
||
| 155 | * |
||
| 156 | * @var array |
||
| 157 | * |
||
| 158 | * @since 1.0 |
||
| 159 | */ |
||
| 160 | protected $taggedAttributes = array('title', 'description', 'content'); |
||
| 161 | |||
| 162 | /** |
||
| 163 | * Path to a .text file where the content of this article is stored (optional). |
||
| 164 | * |
||
| 165 | * @var string |
||
| 166 | * |
||
| 167 | * @since 1.0 |
||
| 168 | */ |
||
| 169 | private $filePath; |
||
| 170 | |||
| 171 | /** |
||
| 172 | * An array of data display labels for the class properties. |
||
| 173 | * |
||
| 174 | * @var array |
||
| 175 | * |
||
| 176 | * @since 1.0 |
||
| 177 | */ |
||
| 178 | protected $dataLabels = array('ID' => 'Article ID#', 'title' => 'Title', 'description' => 'Description', 'bodyOnload' => 'Body onload Javascript', 'content' => 'Content', 'headerContent' => 'HTML Header Content', 'author' => 'Author', 'created_ts' => 'Date Added', 'updated_ts' => 'Date of last Update', 'published' => 'Published', 'URL' => 'URL', 'printURL' => 'Printer version URL', 'comments' => 'Comments', 'votes' => 'Votes', 'tags' => 'Tags'); |
||
| 179 | |||
| 180 | /** |
||
| 181 | * The name of the database table for the class. |
||
| 182 | * |
||
| 183 | * @var string |
||
| 184 | * |
||
| 185 | * @since 1.0 |
||
| 186 | */ |
||
| 187 | const TABLE_NAME = 'Article'; |
||
| 188 | |||
| 189 | /** |
||
| 190 | * The URL for this article (transient). |
||
| 191 | * |
||
| 192 | * @var string |
||
| 193 | * |
||
| 194 | * @since 1.0 |
||
| 195 | */ |
||
| 196 | protected $URL; |
||
| 197 | |||
| 198 | /** |
||
| 199 | * The print URL for this article (transient). |
||
| 200 | * |
||
| 201 | * @var string |
||
| 202 | * |
||
| 203 | * @since 1.0 |
||
| 204 | */ |
||
| 205 | protected $printURL; |
||
| 206 | |||
| 207 | /** |
||
| 208 | * Trace logger. |
||
| 209 | * |
||
| 210 | * @var \Alpha\Util\Logging\Logger |
||
| 211 | * |
||
| 212 | * @since 1.0 |
||
| 213 | */ |
||
| 214 | private static $logger = null; |
||
|
0 ignored issues
–
show
Comprehensibility
introduced
by
Loading history...
|
|||
| 215 | |||
| 216 | /** |
||
| 217 | * The constructor which sets up some housekeeping attributes. |
||
| 218 | * |
||
| 219 | * @since 1.0 |
||
| 220 | */ |
||
| 221 | public function __construct() |
||
| 222 | { |
||
| 223 | self::$logger = new Logger('Article'); |
||
| 224 | |||
| 225 | $config = ConfigProvider::getInstance(); |
||
| 226 | $separator = $config->get('cms.url.title.separator'); |
||
| 227 | |||
| 228 | // ensure to call the parent constructor |
||
| 229 | parent::__construct(); |
||
| 230 | |||
| 231 | $this->title = new SmallText(); |
||
| 232 | $this->title->setHelper('Please provide a title for the article. Note that the '.$separator.' character is not allowed!'); |
||
| 233 | $this->title->setSize(100); |
||
| 234 | $this->title->setRule('/^[^'.$separator.']*$/'); |
||
| 235 | |||
| 236 | $this->description = new SmallText(); |
||
| 237 | $this->description->setHelper('Please provide a brief description of the article.'); |
||
| 238 | $this->description->setSize(200); |
||
| 239 | $this->description->setRule("/\w+/"); |
||
| 240 | $this->bodyOnload = new SmallText(); |
||
| 241 | $this->content = new LargeText(); |
||
| 242 | $this->headerContent = new Text(); |
||
| 243 | $this->author = new SmallText(); |
||
| 244 | $this->author->setHelper('Please state the name of the author of this article'); |
||
| 245 | $this->author->setSize(70); |
||
| 246 | $this->author->setRule("/\w+/"); |
||
| 247 | $this->published = new Boolean(0); |
||
|
0 ignored issues
–
show
0 is of type integer, but the function expects a boolean.
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
Loading history...
|
|||
| 248 | |||
| 249 | $this->comments = new Relation(); |
||
| 250 | $this->markTransient('comments'); |
||
| 251 | |||
| 252 | $this->votes = new Relation(); |
||
| 253 | $this->markTransient('votes'); |
||
| 254 | |||
| 255 | $this->tags = new Relation(); |
||
| 256 | $this->markTransient('tags'); |
||
| 257 | |||
| 258 | $this->URL = ''; |
||
| 259 | $this->printURL = ''; |
||
| 260 | // mark the URL attributes as transient |
||
| 261 | $this->markTransient('URL'); |
||
| 262 | $this->markTransient('printURL'); |
||
| 263 | |||
| 264 | // mark title as unique |
||
| 265 | $this->markUnique('title'); |
||
| 266 | |||
| 267 | $this->markTransient('filePath'); |
||
| 268 | $this->markTransient('taggedAttributes'); |
||
| 269 | |||
| 270 | $this->setupRels(); |
||
| 271 | } |
||
| 272 | |||
| 273 | /** |
||
| 274 | * After creating a new Article, tokenize the description field to form a set |
||
| 275 | * of automated tags and save them. |
||
| 276 | * |
||
| 277 | * @since 1.0 |
||
| 278 | */ |
||
| 279 | protected function after_save_callback() |
||
| 280 | { |
||
| 281 | if ($this->getVersion() == 1 && $this->tags instanceof \Alpha\Model\Type\Relation) { |
||
| 282 | // update the empty tags values to reference this ID |
||
| 283 | $this->tags->setValue($this->ID); |
||
| 284 | |||
| 285 | foreach ($this->taggedAttributes as $tagged) { |
||
| 286 | $tags = Tag::tokenize($this->get($tagged), 'Alpha\Model\Article', $this->getID()); |
||
| 287 | foreach ($tags as $tag) { |
||
| 288 | try { |
||
| 289 | $tag->save(); |
||
| 290 | } catch (ValidationException $e) { |
||
|
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
|
|||
| 291 | /* |
||
| 292 | * The unique key has most-likely been violated because this Record is already tagged with this |
||
| 293 | * value, so we can ignore in this case. |
||
| 294 | */ |
||
| 295 | } |
||
| 296 | } |
||
| 297 | } |
||
| 298 | } |
||
| 299 | |||
| 300 | $this->setupRels(); |
||
| 301 | } |
||
| 302 | |||
| 303 | /** |
||
| 304 | * Set up the transient URL attributes for the artcile after it has loaded. |
||
| 305 | * |
||
| 306 | * @since 1.0 |
||
| 307 | */ |
||
| 308 | protected function after_loadByAttribute_callback() |
||
| 309 | { |
||
| 310 | $this->{'after_load_callback'}(); |
||
| 311 | } |
||
| 312 | |||
| 313 | /** |
||
| 314 | * Set up the transient URL attributes for the article after it has loaded. |
||
| 315 | * |
||
| 316 | * @since 1.0 |
||
| 317 | */ |
||
| 318 | protected function after_load_callback() |
||
| 319 | { |
||
| 320 | $config = ConfigProvider::getInstance(); |
||
| 321 | |||
| 322 | $this->URL = $config->get('app.url').'/a/'.str_replace(' ', $config->get('cms.url.title.separator'), $this->title->getValue()); |
||
| 323 | |||
| 324 | $this->printURL = $config->get('app.url').'/a/'.str_replace(' ', $config->get('cms.url.title.separator'), $this->title->getValue()).'/print'; |
||
| 325 | |||
| 326 | $this->setupRels(); |
||
| 327 | } |
||
| 328 | |||
| 329 | /** |
||
| 330 | * Gets an array of the IDs of the most recent articles added to the system (by date), from the newest |
||
| 331 | * article to the amount specified by the $limit. |
||
| 332 | * |
||
| 333 | * @param int $limit |
||
| 334 | * |
||
| 335 | * @return array |
||
| 336 | * |
||
| 337 | * @since 1.0 |
||
| 338 | * |
||
| 339 | * @throws \Alpha\Exception\AlphaException |
||
| 340 | */ |
||
| 341 | public function loadRecentWithLimit($limit) |
||
| 342 | { |
||
| 343 | $sqlQuery = 'SELECT ID FROM '.$this->getTableName()." WHERE published='1' ORDER BY created_ts DESC LIMIT 0, $limit;"; |
||
| 344 | |||
| 345 | $result = $this->query($sqlQuery); |
||
| 346 | |||
| 347 | $IDs = array(); |
||
| 348 | |||
| 349 | foreach ($result as $row) { |
||
| 350 | array_push($IDs, $row['ID']); |
||
| 351 | } |
||
| 352 | |||
| 353 | return $IDs; |
||
| 354 | } |
||
| 355 | |||
| 356 | /** |
||
| 357 | * Generates the location of the attachments folder for this article. |
||
| 358 | * |
||
| 359 | * @return string |
||
| 360 | * |
||
| 361 | * @since 1.0 |
||
| 362 | */ |
||
| 363 | public function getAttachmentsLocation() |
||
| 364 | { |
||
| 365 | $config = ConfigProvider::getInstance(); |
||
| 366 | |||
| 367 | return $config->get('app.file.store.dir').'attachments/article_'.$this->getID(); |
||
| 368 | } |
||
| 369 | |||
| 370 | /** |
||
| 371 | * Generates the URL of the attachments folder for this article. |
||
| 372 | * |
||
| 373 | * @return string |
||
| 374 | * |
||
| 375 | * @since 1.0 |
||
| 376 | */ |
||
| 377 | public function getAttachmentsURL() |
||
| 378 | { |
||
| 379 | $config = ConfigProvider::getInstance(); |
||
| 380 | |||
| 381 | return $config->get('app.url').'/attachments/article_'.$this->getID(); |
||
| 382 | } |
||
| 383 | |||
| 384 | /** |
||
| 385 | * Generates a secure URL for downloading an attachment file via the ViewAttachment controller. |
||
| 386 | * |
||
| 387 | * @param string $filename |
||
| 388 | * |
||
| 389 | * @since 1.0 |
||
| 390 | */ |
||
| 391 | public function getAttachmentSecureURL($filename) |
||
| 392 | { |
||
| 393 | return FrontController::generateSecureURL('act=Alpha\\Controller\\AttachmentController&articleID='.$this->getID().'&filename='.$filename); |
||
| 394 | } |
||
| 395 | |||
| 396 | /** |
||
| 397 | * Creates the attachment folder for the article on the server. |
||
| 398 | * |
||
| 399 | * @since 1.0 |
||
| 400 | * |
||
| 401 | * @throws \Alpha\Exception\AlphaException |
||
| 402 | */ |
||
| 403 | public function createAttachmentsFolder() |
||
| 404 | { |
||
| 405 | // create the attachment directory for the article |
||
| 406 | try { |
||
| 407 | mkdir($this->getAttachmentsLocation()); |
||
| 408 | } catch (\Exception $e) { |
||
| 409 | throw new AlphaException('Unable to create the folder ['.$this->getAttachmentsLocation().'] for the article.'); |
||
| 410 | } |
||
| 411 | |||
| 412 | // ...and set write permissions on the folder |
||
| 413 | try { |
||
| 414 | chmod($this->getAttachmentsLocation(), 0777); |
||
| 415 | } catch (\Exception $e) { |
||
| 416 | throw new AlphaException('Unable to set write permissions on the folder ['.$this->getAttachmentsLocation().'].'); |
||
| 417 | } |
||
| 418 | } |
||
| 419 | |||
| 420 | /** |
||
| 421 | * Method for returning the calculated score for this article. |
||
| 422 | * |
||
| 423 | * @return string |
||
| 424 | * |
||
| 425 | * @since 1.0 |
||
| 426 | */ |
||
| 427 | public function getArticleScore() |
||
| 428 | { |
||
| 429 | $votes = $this->getArticleVotes(); |
||
| 430 | |||
| 431 | $score = 0; |
||
| 432 | $total_score = 0; |
||
| 433 | $vote_count = count($votes); |
||
| 434 | |||
| 435 | for ($i = 0; $i < $vote_count; ++$i) { |
||
| 436 | $total_score += $votes[$i]->get('score'); |
||
| 437 | } |
||
| 438 | |||
| 439 | if ($vote_count > 0) { |
||
| 440 | $score = $total_score/$vote_count; |
||
| 441 | } |
||
| 442 | |||
| 443 | return sprintf('%01.2f', $score); |
||
| 444 | } |
||
| 445 | |||
| 446 | /** |
||
| 447 | * Method for fetching all of the votes for this article. |
||
| 448 | * |
||
| 449 | * @return array An array of ArticleVote objects |
||
| 450 | * |
||
| 451 | * @since 1.0 |
||
| 452 | */ |
||
| 453 | public function getArticleVotes() |
||
| 454 | { |
||
| 455 | $votes = $this->votes->getRelated(); |
||
| 456 | |||
| 457 | return $votes; |
||
| 458 | } |
||
| 459 | |||
| 460 | /** |
||
| 461 | * Method to determine if the logged-in user has already voted for this article. |
||
| 462 | * |
||
| 463 | * @return bool True if they have voted already, false otherwise |
||
| 464 | * |
||
| 465 | * @since 1.0 |
||
| 466 | * |
||
| 467 | * @throws \Alpha\Exception\AlphaException |
||
| 468 | */ |
||
| 469 | public function checkUserVoted() |
||
| 470 | { |
||
| 471 | $config = ConfigProvider::getInstance(); |
||
| 472 | $sessionProvider = $config->get('session.provider.name'); |
||
| 473 | $session = ServiceFactory::getInstance($sessionProvider, 'Alpha\Util\Http\Session\SessionProviderInterface'); |
||
| 474 | // just going to return true if nobody is logged in |
||
| 475 | if ($session->get('currentUser') == null) { |
||
| 476 | return true; |
||
| 477 | } |
||
| 478 | |||
| 479 | $userID = $session->get('currentUser')->getID(); |
||
| 480 | |||
| 481 | $vote = new ArticleVote(); |
||
| 482 | |||
| 483 | $sqlQuery = 'SELECT COUNT(*) AS usersVote FROM '.$vote->getTableName()." WHERE articleID='".$this->ID."' AND personID='".$userID."';"; |
||
| 484 | |||
| 485 | $result = $this->query($sqlQuery); |
||
| 486 | |||
| 487 | if (!isset($result[0])) { |
||
| 488 | throw new AlphaException('Failed to check if the current user voted for the article ['.$this->ID.'], query ['.$sqlQuery.']'); |
||
| 489 | } |
||
| 490 | |||
| 491 | $row = $result[0]; |
||
| 492 | |||
| 493 | if ($row['usersVote'] == '0') { |
||
| 494 | return false; |
||
| 495 | } else { |
||
| 496 | return true; |
||
| 497 | } |
||
| 498 | } |
||
| 499 | |||
| 500 | /** |
||
| 501 | * Method for fetching all of the comments for this article. |
||
| 502 | * |
||
| 503 | * @return array An array of ArticleComment objects |
||
| 504 | * |
||
| 505 | * @since 1.0 |
||
| 506 | */ |
||
| 507 | public function getArticleComments() |
||
| 508 | { |
||
| 509 | $comments = $this->comments->getRelated(); |
||
| 510 | |||
| 511 | return $comments; |
||
| 512 | } |
||
| 513 | |||
| 514 | /** |
||
| 515 | * Loads the content of the ArticleObject from the specified file path. |
||
| 516 | * |
||
| 517 | * @param string $filePath |
||
| 518 | * |
||
| 519 | * @since 1.0 |
||
| 520 | * |
||
| 521 | * @throws \Alpha\Exception\FileNotFoundException |
||
| 522 | */ |
||
| 523 | public function loadContentFromFile($filePath) |
||
| 524 | { |
||
| 525 | try { |
||
| 526 | $this->content->setValue(file_get_contents($filePath)); |
||
| 527 | $this->filePath = $filePath; |
||
| 528 | } catch (\Exception $e) { |
||
| 529 | throw new FileNotFoundException($e->getMessage()); |
||
| 530 | } |
||
| 531 | } |
||
| 532 | |||
| 533 | /** |
||
| 534 | * Returns true if the article content was loaded from a .text file, false otherwise. |
||
| 535 | * |
||
| 536 | * @return bool |
||
| 537 | * |
||
| 538 | * @since 1.0 |
||
| 539 | */ |
||
| 540 | public function isLoadedFromFile() |
||
| 541 | { |
||
| 542 | return $this->filePath == '' ? false : true; |
||
| 543 | } |
||
| 544 | |||
| 545 | /** |
||
| 546 | * Returns the timestamp of when the content .text file for this article was last |
||
| 547 | * modified. |
||
| 548 | * |
||
| 549 | * @return string |
||
| 550 | * |
||
| 551 | * @since 1.0 |
||
| 552 | * |
||
| 553 | * @throws \Alpha\Exception\FileNotFoundException |
||
| 554 | */ |
||
| 555 | public function getContentFileDate() |
||
| 556 | { |
||
| 557 | if ($this->filePath != '') { |
||
| 558 | try { |
||
| 559 | return date('Y-m-d H:i:s', filemtime($this->filePath)); |
||
| 560 | } catch (\Exception $e) { |
||
| 561 | throw new FileNotFoundException($e->getMessage()); |
||
| 562 | } |
||
| 563 | } else { |
||
| 564 | throw new FileNotFoundException('Error trying to access an article content file when none is set!'); |
||
| 565 | } |
||
| 566 | } |
||
| 567 | |||
| 568 | /** |
||
| 569 | * Sets up the Relation definitions on this record object. |
||
| 570 | * |
||
| 571 | * @since 2.0 |
||
| 572 | */ |
||
| 573 | protected function setupRels() |
||
| 574 | { |
||
| 575 | $this->comments->setValue($this->ID); |
||
| 576 | $this->comments->setRelatedClass('Alpha\Model\ArticleComment'); |
||
| 577 | $this->comments->setRelatedClassField('articleID'); |
||
| 578 | $this->comments->setRelatedClassDisplayField('content'); |
||
| 579 | $this->comments->setRelationType('ONE-TO-MANY'); |
||
| 580 | |||
| 581 | $this->votes->setValue($this->ID); |
||
| 582 | $this->votes->setRelatedClass('Alpha\Model\ArticleVote'); |
||
| 583 | $this->votes->setRelatedClassField('articleID'); |
||
| 584 | $this->votes->setRelatedClassDisplayField('score'); |
||
| 585 | $this->votes->setRelationType('ONE-TO-MANY'); |
||
| 586 | |||
| 587 | $this->tags->setRelatedClass('Alpha\Model\Tag'); |
||
| 588 | $this->tags->setRelatedClassField('taggedID'); |
||
| 589 | $this->tags->setRelatedClassDisplayField('content'); |
||
| 590 | $this->tags->setRelationType('ONE-TO-MANY'); |
||
| 591 | $this->tags->setTaggedClass(get_class($this)); |
||
| 592 | $this->tags->setValue($this->ID); |
||
| 593 | } |
||
| 594 | } |
||
| 595 |