Skip to content

Instantly share code, notes, and snippets.

@wiratama
Last active February 23, 2018 08:29
Show Gist options
  • Save wiratama/7b7a63e18a1687683a34f86f6711f891 to your computer and use it in GitHub Desktop.
Save wiratama/7b7a63e18a1687683a34f86f6711f891 to your computer and use it in GitHub Desktop.
<?php
namespace Movent\ContentBundle\Twig;
use Movent\ContentBundle\Permalink\PermalinkInterface;
use Movent\ContentBundle\Entity\Interfaces\ContentInterface;
use Movent\ContentBundle\Entity\Interfaces\ArticleInterface;
use Movent\ContentBundle\Entity\Interfaces\RecipeInterface;
use Movent\ContentBundle\Entity\Interfaces\ProductInterface;
use Movent\CategoryBundle\Entity\CategoryInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
use Symfony\Component\DomCrawler\Crawler;
class ContentExtension extends \Twig_Extension {
const FACEBOOK_SHARE_URL = 'https://graph.facebook.com';
const TWITTER_SHARE_URL = 'https://cdn.api.twitter.com';
protected $permalinkGenerator;
protected $generator;
protected $container;
protected $environment;
public function __construct(PermalinkInterface $permalinkGenerator, UrlGeneratorInterface $generator) {
$this->permalinkGenerator = $permalinkGenerator;
$this->generator = $generator;
}
public function initRuntime(\Twig_Environment $environment)
{
$this->environment = $environment;
}
/**
* set Service Container
*
* @param Symfony\Component\DependencyInjection\Container
*/
public function setContainer($container) {
$this->container = $container;
}
public function getFunctions() {
return array(
new \Twig_SimpleFunction('movent_content_path', array($this, 'contentPathFunction')),
new \Twig_SimpleFunction('movent_content_canonical_path', array($this, 'canonicalPathFunction')),
new \Twig_SimpleFunction('movent_content_canonical_slug_path', array($this, 'canonicalSlugPathFunction')),
new \Twig_SimpleFunction('movent_content_slug_path', array($this, 'contentPathFromSlugFunction')),
new \Twig_SimpleFunction('isArticle', array($this, 'isArticleFunction')),
new \Twig_SimpleFunction('isRecipe', array($this, 'isRecipeFunction')),
new \Twig_SimpleFunction('isProduct', array($this, 'isProductFunction')),
new \Twig_SimpleFunction('isContent', array($this, 'isContentFunction')),
new \Twig_SimpleFunction('getFBShareCount', array($this, 'getContentsFunction')),
new \Twig_SimpleFunction('getTWShareCount', array($this, 'getTWContentsFunction')),
new \Twig_SimpleFunction('bitly_short_url', array($this, 'getBitlyShortUrl')),
);
}
public function getFilters()
{
return array(
new \Twig_SimpleFilter('render_widgets', array($this, 'renderWidgets'),array('is_safe' => array('html'))),
new \Twig_SimpleFilter('shuffle', array($this, 'shuffle')),
);
}
public function getBitlyShortUrl($url)
{
if ($this->container->hasParameter('bitly_access_token')) {
$bitlyAccessToken = $this->container->getParameter('bitly_access_token');
}
if (!empty($bitlyAccessToken)) {
$client = new Client();
try {
$bitlyUrl = sprintf('https://api-ssl.bitly.com/v3/shorten?access_token=%s&longUrl=%s', $bitlyAccessToken, urlencode($url));
$response = $client->get($bitlyUrl);
if ($response->getStatusCode() == 200) {
$obj = $response->json();
return (isset($obj['data']['url']) ? $obj['data']['url'] : $url);
}
} catch (Exception $ex) {
return 0;
}
}
return $url;
}
public function contentPathFunction(ContentInterface $content, CategoryInterface $category = null, $absolute = false) {
if (!$category) {
return $this->canonicalPathFunction($content, null, $absolute);
}
return $this->generator->generate('movent_content_content_view', array('permalink' => $this->permalinkGenerator->generate($content, $category),
'_format' => 'html'), $absolute);
}
public function canonicalSlugPathFunction($slug = '', $absolute = false) {
return $this->generator->generate('movent_content_view_canonical', array('permalink' => $slug,
'_format' => 'html'), $absolute);
}
public function canonicalPathFunction(ContentInterface $content, CategoryInterface $category = null, $absolute = false) {
return $this->generator->generate('movent_content_view_canonical', array('permalink' => $this->permalinkGenerator->generate($content, $category),
'_format' => 'html'), $absolute);
}
public function contentPathFromSlugFunction($slug = '', CategoryInterface $category = null, $absolute = false) {
$routeName = 'movent_content_content_view';
if (!$category) {
$routeName = 'movent_content_view_canonical';
}
return $this->generator->generate($routeName, array('permalink' => $this->permalinkGenerator->generateFromSlug($slug, $category),
'_format' => 'html'), $absolute);
}
public function isArticleFunction(ContentInterface $content) {
return (bool) ($content instanceof ArticleInterface);
}
public function isRecipeFunction(ContentInterface $content) {
return (bool) ($content instanceof RecipeInterface);
}
public function isProductFunction(ContentInterface $content) {
return (bool) ($content instanceof ProductInterface);
}
public function isContentFunction(ContentInterface $content) {
return (bool) ($content instanceof ContentInterface);
}
public function getName() {
return 'movent_content_extension';
}
public function getContentsFunction($url) {
$client = new Client();
try {
$shareUrl = sprintf("%s/fql?q=SELECT%%20like_count,%%20total_count,%%20share_count,%%20click_count,%%20comment_count%%20FROM%%20link_stat%%20WHERE%%20url%%20=%%20%%27%s%%27", self::FACEBOOK_SHARE_URL, $url);
$response = $client->get($shareUrl);
if ($response->getStatusCode() == 200) {
$obj = $response->json();
return ((isset($obj['data']) && isset($obj['data'][0]) && isset($obj['data'][0]['share_count'])) ? $obj['data'][0]['share_count'] : null);
}
return 0;
} catch (RequestException $e) {
return 0;
}
}
public function getTWContentsFunction($url) {
$client = new Client();
try {
$shareUrl = sprintf("%s/1/urls/count.json?url=%s", self::TWITTER_SHARE_URL, $url);
$response = $client->get($shareUrl);
if ($response->getStatusCode() == 200) {
$obj = $response->json();
return (isset($obj['count']) ? $obj['count'] : 0);
}
return 0;
} catch (RequestException $e) {
return 0;
}
}
public function renderWidgets($contents,$params = [])
{
$request = $this->container->get('request');
if(!$contents){
return "";
}
$crawler = new Crawler($contents);
try {
/* div.related-content by category */
$pNode = $crawler->filter('p')->count();
$pNode = ($pNode>2) ? round($pNode/2) : $pNode;
$request = $this->container->get('request');
$parameters = explode('/', $request->getRequestURI());
$permalink = $this->permalinkGenerator->getParameters($request->getRequestURI());
$catId = $contentId = $contetnType = 0;
$relatedArticle = [];
if(count($parameters) > 4) {
$categoryData = $this->container->get('doctrine')->getRepository('MoventCategoryBundle:Category')->findOneBy(array('slug' => (string)$parameters[3]));
$catId = $categoryData->getId();
$paramSlug = explode('.',$parameters[4]);
$contentData = $this->container->get('doctrine')->getRepository('MoventContentBundle:Content')->findOneBy(array('slug' => (string)$paramSlug[0]));
$contentId = $contentData->getId();
$contentType = $contentData->getContentType();
} else {
$categoryData = $this->container->get('doctrine')->getRepository('MoventCategoryBundle:Category')->findOneBy(array('slug' => (string)$parameters[2]));
$catId = $categoryData->getId();
$paramSlug = explode('.',$parameters[3]);
$contentData = $this->container->get('doctrine')->getRepository('MoventContentBundle:Content')->findOneBy(array('slug' => (string)$paramSlug[0]));
$contentId = $contentData->getId();
$contentType = $contentData->getContentType();
}
$entityManager = $this->container->get('doctrine')->getManager();
$connection = $entityManager->getConnection();
$statement = $connection->prepare("SELECT ctr.*, c.* FROM movent__content_entity_content_category ctr JOIN movent__content_entity_content c ON ctr.content_id=c.id WHERE ctr.content_id <> :content_id AND c.content_type = :content_type AND ctr.category_id = :category_id AND c.status = :status ORDER BY RAND() LIMIT 1");
$statement->bindValue('content_id', $contentId);
$statement->bindValue('content_type', 'Article');
$statement->bindValue('category_id', $catId);
$statement->bindValue('status', 'published');
$statement->execute();
$relatedArticle = $statement->fetchAll();
$content = $this->container->get('movent_content.content.entity.manager')->findOneBy(array('id' => $relatedArticle[0]['content_id']));
/* /. div.related-content by category */
$widgetHelper = $this->container->get("movent_content.widget.helper");
//$crawler->filter("widget.inline-related-content")->each(function (Crawler $node, $i) use ($params,$widgetHelper){
$crawler->filter("p")->eq($pNode)->each(function (Crawler $node, $i) use ($params,$widgetHelper, $relatedArticle, $content){
$limit = 1;
$type = 'related-article';
$params['related_article'] = $content; //$relatedArticle;
$templateContent = $widgetHelper->setParameters($params)->setType($type)->setLimit($limit)->render();
$tmpDoc = new \DOMDocument();
$internalErrors = libxml_use_internal_errors(true);
$tmpDoc->loadHTML($templateContent?$templateContent:"<span/>", LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
libxml_use_internal_errors($internalErrors);
if($tmpDoc->documentElement) {
$node->getNode(0)->parentNode->insertBefore($node->getNode(0)->ownerDocument->importNode($tmpDoc->documentElement,true), $node->getNode(0));
}
});
}
catch(Exception $e){
// make sure to throw exception on debug mode.
if ($this->environment->isDebug()) {
throw $e;
}
}
if($crawler->count() < 1){
return;
}
$html = "";
if (!count($crawler)) {
// make sure to throw exception on debug mode.
if ($this->environment->isDebug()) {
throw new \InvalidArgumentException('The current node list is empty.');
}
}
foreach ($crawler->getNode(0)->childNodes as $child) {
$html .= $child->ownerDocument->saveHTML();
}
//Remove extra body tag
preg_match("/<body[^>]*>(.*?)<\/body>/is", $html, $matches);
return $matches[1];
}
public function shuffle($data = [])
{
shuffle($data);
return $data;
}
}
{% if data.related_article %}
<div class="related-content">
{% set url = movent_content_path(data.related_article,data.related_article.canonicalCategory, true) %}
<div class="content-item-cat{{ data.category }} mov-article_related" data-rootid="{{ data.category?data.category.id:0 }}">
<div id="{{ data.related_article.contentType }}-{{ data.related_article.id }}" class="img-holder is-loading mov-article_related__image">
<a href="{{ url }}" title="{{ data.related_article.title|raw }}">
<img alt="{{ data.related_article.imageMainLabel|raw }}" src="{{ movent_media_public_url(data.related_article.imageMain, 'image_228x151') }}" width="228" height="151" />
</a>
<div class="mov_category-icon">
{% set icon_path = movent_category_cached_config(data.category?data.category.id:0,constant('Movent\\CategoryBundle\\Services\\CategoryConfig::PROP_CAT_ICON_45x45')) %}
<img src="{{icon_path}}">
</div>
</div>
<div class="mov-article_related__content">
<h2 class="tab-header cat{{ data.category?data.category.id:0 }}">
<a href="{{ url }}" title="{{ data.related_article.title|raw }}">{{ data.related_article.title|raw }}</a>
</h2>
<p>{{ data.related_article.abstract|raw|truncate(120, true, ' [...]') }}</p>
{# <a href="{{ url }}" class="tab-link">{{"Selengkapnya"|trans}}</a> #}
</div>
</div>
</div>
{% endif %}
@wiratama
Copy link
Author

path

/src/Movent/ContentBundle/Twig/
* ContentExtension.php

/src/Movent/ContentBundle/Resources/views/Widget/
* related_article.html.twig

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment