/** * Get the form for article creation and updating. * * @param BlogArticleModel $article * * @return Form */ public static function GetArticleForm(BlogArticleModel $article) { $page = $article->getLink('Page'); $blog = $article->getLink('Blog'); $page->set('parenturl', $blog->get('baseurl')); $form = new Form(); $form->set('callsmethod', 'BlogHelper::BlogArticleFormHandler'); $form->addModel($page, 'page'); $form->addModel($article, 'model'); if (Core::IsComponentAvailable('facebook') && Core::IsLibraryAvailable('jquery')) { // Is this article already posted? if ($article->get('fb_post_id')) { $form->addElement('select', ['disabled' => true, 'title' => 'Post to Facebook', 'options' => ['' => 'Posted!'], 'group' => 'Publish Settings']); } else { $form->addElement('select', ['class' => 'facebook-post-to-select', 'title' => 'Post to Facebook', 'name' => 'facebook_post', 'options' => ['' => '-- Please enable javascript --'], 'group' => 'Publish Settings']); } } // Lock in some elements for this blog article page. $form->getElement('page[parenturl]')->setFromArray(array('value' => $blog->get('baseurl'), 'readonly' => 'readonly')); // And remove a few other elements. $form->removeElement('model[title]'); return $form; }
<?php /** * Created by JetBrains PhpStorm. * User: powellc * Date: 1/17/13 * Time: 10:20 PM * This is the upgrade file from 1.3.0 to 1.4.0 * * Blogs now have a published date. By default, all published articles should have that timestamp set to the last modified date. */ // Since this runs prior to the blog system being enabled, I need to manually include the model files. require_once ROOT_PDIR . 'components/blog/models/BlogArticleModel.php'; require_once ROOT_PDIR . 'components/blog/models/BlogModel.php'; $schema = BlogArticleModel::GetSchema(); if (isset($schema['published'])) { $articles = BlogArticleModel::Find(array('status' => 'published', 'published' => '')); foreach ($articles as $article) { /** @var $article BlogArticleModel */ $article->set('published', $article->get('updated')); $article->save(); } } // return
<?php /** * Created by JetBrains PhpStorm. * User: powellc * Date: 1/17/13 * Time: 10:20 PM * This is the upgrade file from 1.5.0 to 1.5.1 * * Required because with the file input change in 2.6.0 returning core resolved paths, * the data in the database will contain that path now. */ $articles = BlogArticleModel::Find(['image != ']); foreach ($articles as $a) { /** @var $a BlogArticleModel */ $a->set('image', 'public/blog/' . $a->get('image')); $a->save(); } // return
/** * Created by JetBrains PhpStorm. * User: powellc * Date: 1/17/13 * Time: 10:20 PM * This is the upgrade file from 1.2.1 to 1.3.0. * * The blog system in 1.3.0 and later utilizes a dedicated Page entry for each blog entry. This helps to have more * fine grain control over each entry's settings and data, as well as making use of the insertable system. */ // Create a page for each BlogArticle! // Since this runs prior to the blog system being enabled, I need to manually include the model files. require_once ROOT_PDIR . 'components/blog/models/BlogArticleModel.php'; require_once ROOT_PDIR . 'components/blog/models/BlogModel.php'; $articles = BlogArticleModel::Find(); foreach ($articles as $article) { /** @var $article BlogArticleModel */ /** @var $blog BlogModel */ $blog = $article->getLink('Blog'); /** @var $page PageModel */ $page = $article->getLink('Page'); $page->setFromArray(array('title' => $article->get('title'), 'rewriteurl' => $blog->get('rewriteurl') . '/' . $article->get('id') . '-' . \Core\str_to_url($article->get('title')), 'parenturl' => $blog->get('baseurl'), 'fuzzy' => 0, 'admin' => 0)); if ($article->get('authorid')) { $user = UserModel::Construct($article->get('authorid')); $page->setMeta('author', $user->getDisplayName()); $page->setMeta('authorid', $user->get('id')); } $page->setMeta('description', $article->get('description')); $page->setMeta('keywords', $article->get('keywords')); $page->save();
protected function tearDown() { $this->blog->delete(); $this->article->delete(); }
private function _viewBlogArticle(BlogModel $blog, BlogArticleModel $article) { $view = $this->getView(); /** @var $page PageModel */ $page = $article->getLink('Page'); //$articles = $blog->getLink('BlogArticle'); $manager = \Core\user()->checkAccess('p:/blog/manage_all'); $editor = \Core\user()->checkAccess($blog->get('manage_articles_permission ')) || $manager; $author = UserModel::Construct($article->get('authorid')); //$authorid = $author->get('id'); //var_dump($page->getMeta('keywords')); die(); if (!$article->isPublished()) { // Is it actually not published, or just marked for a future publish date? if ($article->get('status') == 'published') { $publishdate = new CoreDateTime($article->get('published')); Core::SetMessage('Article is set to be published on ' . $publishdate->getFormatted('F jS, Y \\a\\t h:ia'), 'info'); } else { Core::SetMessage('Article not published yet!', 'info'); } } //$view->templatename = $page->get('page_template') ? $page->get('page_template') : 'pages/blog/article_view.tpl'; $view->templatename = 'pages/blog/article_view.tpl'; //$view->addBreadcrumb($blog->get('title'), $blog->get('rewriteurl')); $view->title = $article->get('title'); $view->meta['title'] = $article->get('title'); $view->updated = $article->get('updated'); $view->canonicalurl = \Core\resolve_link($article->get('rewriteurl')); $view->meta['og:type'] = 'article'; if ($article->get('image')) { $image = \Core\Filestore\Factory::File($article->get('image')); $view->meta['og:image'] = $image->getPreviewURL('200x200'); } //if($author){ // /** @var $author User */ // //$view->meta['author'] = $author->getDisplayName(); // $view->meta['author'] = $author; //} $view->meta['description'] = $article->getTeaser(); $view->assign('author', $author->exists() ? $author : null); $view->assign('article', $article); $view->assign('body', \Core\parse_html($article->get('body'))); if ($editor) { $view->addControl('Edit Article', '/blog/article/update/' . $article->get('id'), 'edit'); if ($article->get('status') == 'draft') { $view->addControl(['title' => 'Publish Article', 'link' => '/blog/article/publish/' . $blog->get('id') . '/' . $article->get('id'), 'icon' => 'arrow-up', 'confirm' => 'Publish article?']); } $view->addControl(array('title' => 'Delete Article', 'link' => '/blog/article/delete/' . $article->get('id'), 'icon' => 'remove', 'confirm' => 'Remove blog article?')); } // Add the extra view types for this page $view->addHead('<link rel="alternate" type="application/atom+xml" title="' . $page->get('title') . ' Atom Feed" href="' . \Core\resolve_link($blog->get('baseurl')) . '.atom"/>'); $view->addHead('<link rel="alternate" type="application/rss+xml" title="' . $page->get('title') . ' RSS Feed" href="' . \Core\resolve_link($blog->get('baseurl')) . '.rss"/>'); $view->addControl('RSS Feed', \Core\resolve_link($blog->get('baseurl')) . '.rss', 'rss'); }
/** * Helper utility to import a given remote blog. * * @param bool $verbose Set to true to enable real-time verbose output of the operation. * @return array * * @throws Exception */ public function importFeed($verbose = false) { $blogid = $this->get('id'); if (!$this->exists()) { throw new Exception('Unable to import a blog that does not exist!'); } // Make sure this is a remote blog. if ($this->get('type') != 'remote') { throw new Exception('Cannot import a blog that is not remote!'); } $file = \Core\Filestore\Factory::File($this->get('remote_url')); if (!$file->exists()) { throw new Exception($this->get('remote_url') . ' does not appear to exist'); } $defaults = ['parenturl' => $this->get('baseurl'), 'site' => $this->get('site'), 'component' => 'blog']; $changes = ['added' => 0, 'updated' => 0, 'skipped' => 0, 'deleted' => 0]; $changelog = ''; // I need a list of current articles in this feed. This is because remote deletions won't be coming in on the feed. $map = array(); $articles = BlogArticleModel::FindRaw(['blogid = ' . $blogid]); foreach ($articles as $a) { $map[$a['guid']] = $a['id']; } // I can't trust that remote files list what they actually are because many frameworks, // (WP in specific), do not correctly use content-types :/ $contents = $file->getContents(); // Which feed type is this? $header = substr($contents, 0, 400); // All the standardized records $records = array(); if (strpos($header, '<rss ') !== false) { if ($verbose) { echo 'Found an RSS feed with the URL of ' . $file->getURL() . '!<br/>' . "\n"; ob_flush(); flush(); } $xml = new XMLLoader(); $xml->setRootName('rss'); $xml->loadFromString($contents); foreach ($xml->getElements('channel/item') as $item) { $dat = ['guid' => '', 'link' => '', 'thumbnail' => '', 'published' => '', 'updated' => '', 'description' => '']; foreach ($item->childNodes as $child) { if ($child->nodeName == '#text') { continue; } switch ($child->nodeName) { case 'media:thumbnail': $dat['thumbnail'] = $child->getAttribute('url'); break; case 'pubDate': $dat['published'] = $child->nodeValue; break; default: $dat[$child->nodeName] = $child->nodeValue; } } $records[] = $dat; } } elseif (strpos($header, 'http://www.w3.org/2005/Atom') !== false) { if ($verbose) { echo 'Found an ATOM feed with the URL of ' . $file->getURL() . '!<br/>' . "\n"; ob_flush(); flush(); } $xml = new XMLLoader(); $xml->setRootName('feed'); $xml->loadFromString($contents); foreach ($xml->getRootDOM()->childNodes as $item) { if ($item->nodeName != 'entry') { continue; } $dat = ['guid' => '', 'link' => '', 'thumbnail' => '', 'published' => '', 'updated' => '', 'description' => '']; $imgheight = 0; foreach ($item->childNodes as $child) { if ($child->nodeName == '#text') { continue; } switch ($child->nodeName) { case 'id': $dat['guid'] = $child->nodeValue; break; case 'link': if ($child->getAttribute('rel') == 'alternate' && $child->getAttribute('type') == 'text/html') { if ($child->nodeValue) { $dat['link'] = $child->nodeValue; } else { $dat['link'] = $child->getAttribute('href'); } } break; case 'im:image': if ($child->getAttribute('height') > $imgheight) { $dat['thumbnail'] = $child->nodeValue; $imgheight = $child->getAttribute('height'); } break; case 'updated': $dat['updated'] = strtotime($child->nodeValue); break; case 'summary': if ($dat['description'] != '') { $dat['description'] = $child->nodeValue; } break; case 'content': $dat['description'] = $child->nodeValue; break; default: $dat[$child->nodeName] = $child->nodeValue; } } if (!$dat['published'] && $dat['updated']) { // make sure that there's a published date. $dat['published'] = $dat['updated']; } $records[] = $dat; } } else { throw new Exception('Invalid remote file found, please ensure it is either an RSS or Atom feed!'); } // Now that they're standardized... foreach ($records as $dat) { /** @var PageModel $page */ $page = PageModel::Construct($dat['link']); $published = $dat['published'] == '' || is_numeric($dat['published']) ? $dat['published'] : strtotime($dat['published']); $updated = $dat['updated'] != '' ? is_numeric($dat['updated']) ? $dat['updated'] : strtotime($dat['updated']) : $published; $pagedat = ['published' => $published, 'title' => $dat['title'], 'body' => $dat['description'], 'updated' => $updated]; $newpagedat = array_merge($defaults, ['selectable' => '0']); $page->setFromArray($pagedat); if (!$page->exists()) { // Add the "new" dat only if the page doesn't exist before. $page->setFromArray($newpagedat); } if ($dat['thumbnail']) { $remote = \Core\Filestore\Factory::File($dat['thumbnail']); $new = $remote->copyTo('public/blog/'); $page->setMeta('image', $new->getFilename(false)); } $page->setMeta('guid', $dat['guid']); $thischange = $page->exists() ? 'updated' : 'added'; if ($page->changed()) { $page->save(); $changes[$thischange]++; $changelog .= $thischange . ' ' . $dat['title'] . "<br/>\n"; if ($verbose) { echo $thischange . ' ' . $dat['title'] . "<br/>\n"; ob_flush(); flush(); } } else { $changes['skipped']++; if ($verbose) { echo 'No changes to ' . $dat['title'] . "<br/>\n"; ob_flush(); flush(); } } } return ['status' => 1, 'message' => 'Import feed successfully!', 'added' => $changes['added'], 'updated' => $changes['updated'], 'deleted' => $changes['deleted'], 'skipped' => $changes['skipped'], 'changelog' => $changelog]; }