Skip to content

Instantly share code, notes, and snippets.

@terwey
Last active February 1, 2017 22:31
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save terwey/5699090 to your computer and use it in GitHub Desktop.
Newscoop 4.2 - A Simple Plugin

Newscoop 4.2 - a Simple Plugin

Just like you I am extremely excited about the release of [Newscoop 4.2] and the new [Symfony Bundles] plugin system. In the following few steps I will demonstrate to you how to get started creating a super simple Plugin for [Newscoop 4.2].

Prerequisites

  • Motivation (we won't get anywhere if you don't have this!)
  • Your favourite code editor
  • Git client
  • (S)FTP Client for connecting to your server
  • Some knowledge of how to use the Terminal
    • If you're on Windows we'll be connecting via PuTTY to your Newscoop install
  • Github account (we'll be needing one)

Introduction

Because the new Plugin system is based on Symfony Bundles we are now able to use Packagist to maintain and update our Plugins. This allows for more flexibility and better community integration in Newscoop. Here's a quick sum-up of the advantages and disadvantages:

Advantages

  • Symfony Bundle
    • This means the Plugins can be extremely powerful!
  • Plugin is registered on Packagist and can be installed and updated directly from the command line (web integration is coming!)

Disadvantage

  • Packagist is required at the moment

Plugin development introduction

Now before any Development can start we have to figure out what we want our Package to do. In this case we are going to build a simple Plugin that generates some <meta /> tags for a Newscoop article that can be interpreted by Facebook. These are also known as OG Meta or OpenGraph Meta tags.

What does that mean? These tags usually look something like this:

<meta property="og:title" content="European Council candidates set to be named" />
<meta property="og:type" content="article" />
<meta property="og:url" content="http:/www.yoursite.com/en/jan2011/politics/64/European-Council-candidates-set-to-be-named.htm" />
<meta property="og:site_name" content="The New Custodian" />
<meta property="og:description" content="BRUSSELS - Italian and Greek candidates nominated for President of the European Council in secret ballot." />
<meta property="og:image" content="http://www.yoursite.com/images/cms-image-000000092.jpg" />

These special tags are used by Facebook which uses them to display information about shared pages. Facebook however won't display everything you're now looking at, only these parts:

Title: 			European Council candidates set to be named
Type:			Article
URL:			http:/www.yoursite.com/en/jan2011/politics/64/European-Council-candidates-set-to-be-named.htm
Site Name:		The New Custodian
Description:	BRUSSELS - Italian and Greek candidates nominated for President of the European Council in secret ballot.
Image:			http://www.yoursite.com/images/cms-image-000000092.jpg

The information that we're passing to Facebook is so that it knows what the page the user actually shared is about.

Now we have the introduction for what we want to build out of the way, it's time for some code!

Getting started

I am assuming that we're developing on either a Mac or a Linux machine. If you're on Windows, bear with me, we'll get to you soon enough. Start your Terminal (on Mac this can be found under Applications/Utilities/Terminal.app) In Terminal let's create a Working Directory.

user@somepc:~$ mkdir newscoop-plugin-facebook
user@somepc:~$ cd newscoop-plugin-facebook/
user@somepc:~/newscoop-plugin-facebook$ git init .

After the last command you will recieve a response similar to the one below:

Initialized empty Git repository in /Users/user/newscoop-plugin-facebook/.git/

From here on I will denote the Terminal commands with just $ only type the command AFTER the dollar-sign.

Awesome! We have just made a working directory and initialised a Git repository within it. We have to do this because Packagist requires a linked Git repository.

Now we have the basic environment we need let's make some files we will need. And because we're all lazy and a bit nerdy we'll use a cool command to quickly create a few skeleton files.

$ touch composer.json NewscoopFacebookMetaBundle.php README.md

These files don't do anything yet but they provide a blank slate to begin with.

Let's edit them.

Composer.json

The Composer.json is a very important file, it describes what the Plugin does and who wrote it among other things. You should find the file in ~/newscoop-plugin-facebook. If you are on a Mac we can use a small trick, type open . in your Terminal and a Finder window will open at the correct directory. Open your favourite Code Editor and open this file in it!

The following code has to be placed in it, we'll go bit by bit over it to make it more clear.

Package name

The "name" is not known yet because you haven't signed up at Packagist yet (if you have already you know what to do here) so you don't have the information yet. For now leave it as it is shown here.

{
"name": "GITHUB_USERNAME/GITHUB_REPO_NAME",
Description and keywords

This sets a description and keywords for Packagist

"description": "My awesome Newscoop Plugin for Facebook integration",
"keywords": ["newscoop", "facebook"],
Version and licensing

The License can be any License you want, but we like the GPL so we're going to use that.

"version": "0.1",
"type": "newscoop-plugin",
"license": "GPL-3.0",
Author name and email address

Your name and email address, for copyright purposes!

"authors": [
	{
	"name": "YOUR NAME",
	"email": "YOUR@EMAIL.ADDRESS"

More information about the different kinds of copyright can be found at the Creative Commons website.

Finishing up

The last bit, just copy it into the file.

    }
],
"require": {
    "php": ">=5.3.3",
    "newscoop/plugins-installer": "*"
},
"autoload": {
    "psr-0": { "Newscoop\\FacebookMetaBundle\\NewscoopFacebookMetaBundle": "" }
},
"target-dir": "Newscoop/FacebookMetaBundle",
"minimum-stability": "dev"
}

Now your composer.json should be complete. Save it and close it for now.

NewscoopFacebookMetaBundle.php

This file we won't really use but we need it so that Newscoop understands what it has to do with the Plugin. Just copy it as shown here.

<?php

namespace Newscoop\FacebookMetaBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;

class NewscoopFacebookMetaBundle extends Bundle
{
}

README.md

This file can contain anything you want, usually a description of the software it accompanies, but for now you can just leave it empty.

Creating the resources

Now let's jump back into the Terminal and create the rest of the structure we need.

$ mkdir -p Resources/smartyPlugins/

This little cool command here made 2 directories in one go. This is because of the -p flag we gave to mkdir.

$ touch Resources/smartyPlugins/block.facebook_meta_block.php

Now the last file of the Plugin has been created, it's time for the actual Plugin we're creating!

Smarty Block Function

Newscoop currently extensively uses Smarty Block Functions which is a really easy way to add extra logic to your already awesome Newscoop Template. In the Plugin we will now create a new Smarty Block Function which we will later call from our Newscoop Template.

Edit your new file block.facebook_meta_block.php, inside the directory Resources/smartyPlugins/ and add the following blocks.

Basic Plugin setup
function smarty_block_facebook_meta_block($params, $content, &$smarty, &$repeat) {

This is the actual function that 'runs' the current the new Plugin.

The arguments we pass to the function are coming from Smarty. Here is a brief explanation:

  • $params are the parameters Smarty passes to it internally
  • $content this variable holds the content inside the Smarty Function Block inside the Template
  • &$smarty is the actual $smarty object we normally have inside a Smarty Template, this is there known as $this
  • &$repeat this var lets us know if the Smarty Function Block is inside a loop and if present the iteration it's at

Continuing with the rest of the code:

	if (!isset($content)) {
		return '';
	}

If there is $content set inside the Template in our Smarty Function Block we return nothing extra and assume the Templater wants to override our function in the Template.

	$smarty->smarty->loadPlugin('smarty_shared_escape_special_chars');
	$context = $smarty->getTemplateVars('gimme');

Load the $context. In the Template this is normally known as $gimme. Anything that $gimme can give us we can now directly access in our Plugin! How cool is that?

    $html = '';

Initialise and set an empty value to $html.

Is it an article?
	if ($context->article->defined) {

Test to see if the current page we're going to be displayed on is actually an article. Equivalent to $gimme->article->defined

Now the fun part! The actual code we want to load extra in our HTML so that Facebook knows what what!

og:title Article Name

We set the og:title meta property and are telling the content to be $context->article->name (again the same as: $gimme->article->name)

		$html .= '<meta property="og:title" content="'.$context->article->name.'" />'."\n";

We are using the shorthand for concatenating the strings in PHP .=. We could have also written it as: $html = $html . 'new string';, but that's very messy and error prone.

Because we have to add in extra variables in that variable string we concatenate these by using again the . operator in PHP. Example: $html .= 'Foo Bar'.$var; means literally: "Add the text 'Foo Bar' to the variable $html and join it together with $var".

If you find this scary, do not wit, it's not required to finish this tutorial! It's just explaining a bit of the PHP parts we're using.

og:type Type

Set the og:type meta property and are telling the content to be article. We do this hard-coded because we know it's always an Article (remember the Test to see if it's an article or not?)

		$html .= '<meta property="og:type" content="article" />'."\n";
og:URL Article URL

Facebook also really wants to know what the URL is that you want your visitors to use to link back to your article. Here we call to an internal Newscoop Smarty Function to generate the correct URL for the Article. If you however have special visitor tracking and whatnot you could of course place that all in here too!.

To recap: set the og:url's content to: 'http:/'.$context->publication->site. smarty_function_uri($params, $smarty).

		$html .= '<meta property="og:url" content="http:/'.$context->publication->site. smarty_function_uri($params, $smarty) .'" />'."\n";
og:site_name Newscoop Site Name

Of course we should not forget to set the Site Name! Set og:site_name to context->publication->name

		$html .= '<meta property="og:site_name" content="'. $context->publication->name .'" />'."\n";
og:description Article Description

And because we can we show the Article Deck in the Facebook share too! Important It might be that your Newscoop install doesn't have the Deck type inside an Article. Check this first!

Set the og:description to strip_tags($context->article->deck). We place the $context->article->deck inside the PHP function strip_tags first to prevent that we might have a <b> or similar in that block of text.

		$html .= '<meta property="og:description" content="'.strip_tags($context->article->deck).'" />'."\n";
og:image Article Image

Not every Newscoop Article has an Image. We certainly try (at least I hope you do!) but to prevent that it will show a 404 not found error or something similar when someone Shares your awesome Newscoop Article we do a small Test to see if the article actually has an image. We do this with $context->article->image->imageurl. This variable contains an URL. PHP is really smart so if it's empty it will automatically return false and it won't go inside the Test block.

		if ($context->article->image->imageurl) {

Awesome! Turns out you do have an image! We set the og:image's content to: $context->article->image->imageurl which will generate the correct URL for the Image of your Newscoop Article.

			$html .= '<meta property="og:image" content="'. $context->article->image->imageurl .'" />'."\n";

And of course, we have to close the current Test!

		}	
What if it's not an article?

Remember testing before if it's an article? Here we define what it should do in case it's not.

	} else {
og:site_name Newscoop Site Name

We tell it to simply show the Newscoop Site Name

		$html .= '<meta property="og:site_name" content="'. $context->publication->name .'" />'."\n";
Finishing touches

Close the Test to see if it's an article.

    }

Return the $html variable we have now filled with awesome Facebook compatible OpenGraph Meta Tags.

    return $html;

And last but not least, close the Smarty Function Block

}

Now save the file block.facebook_meta_block.php, take a short break or let's continue! Cause we're almost done!

Wrapping things up

Commit to Git

Because we're using Git we should of course not forget to commit our changes! Also we need to do this because eventually we're going to Push our changes to Github.

$ git add .
$ git commit -m "Initial commit of my awesome Newscoop Plugin"

Now go and Register with Github and come back here once your done

Github Repository

Ah good, your back! Ok Github has some awesome docs to get you started etc and you should have already read through them (right?).

Now, in Github you should create a Repository. Also great guides on Github for those! Look them through!

Add the Remote Github Repo to our local Git repo

Now we have to add the Remote Github Repo to our local Repo. We do this with the following command:

This adds the new Remote Repo

$ git remote add origin YOUR_GITHUB_REPO_URL

And with this command we can check if it was successful

$ git remote -v

If you want more info you can check with the Github Help themselves

Changing our composer.json

Before we didn't set the correct package name in our composer.json which we know now!

Open up your composer.json and change the following to reflect your Github Username and Github Repository Name

"name": "GITHUB_USERNAME/GITHUB_REPO_NAME",

We have to one more time commit to reflect these changes:

$ git add composer.json
$ git commit -m "Update to the composer.json"

Push our local Repo to Github

Now to actually Push our changes

$ git push origin

Now take a look at your Github Repository page, refresh it and you'll see the new files we just created. Almost there!

Packagist

Now we got to setup Packagist. Luckily we just registered already with Github and Packagist allows us to Login with the Github account information.

Go the the Packagist Login page and click on Login with Github.

After login we can Submit a Package, which asks for your Github Repository URL. Paste in the same URL we used before in the section Add the Remote Github Repo to our local Git repo

If everything went alright, you should now have your Plugin registered with Packagist!

Installing the Plugin

Now for the real deal! On the server where you run Newscoop 4.2 we have to do a few things to install the Plugin. Connect to it via SSH and we're off!

The following commands are assuming we're on the server that has Newscoop 4.2 installed!

First we change directories to where the Newscoop install is, this is usually /var/www/newscoop/ but can vary depending on your setup.

$ cd /var/www/newscoop/

Now we are going to install the Plugin! Go to Packagist and there you can find the full name of your Packagist package. This should usually be the same as the Github repo but we can better check!

Replace that in the following command and execute it.

$ php application/console plugins:install "PACKAGIST_USER/PACKAGIST_PACKAGE_NAME" --env=prod

To explain what it does:

  • php tells the Command Line PHP application to execute the following statements.
  • application/console tells PHP to run it in our application enviroment from the console.
  • plugins: tells the application enviroment we're focusing on the plugins
  • install of course installs! This can also be update (or remove but why would you want that?)
  • --env=prod is required that it installs it in the Production enviroment where your Site will be running in.

If everything went alright your Plugin is now Installed! But, one more important bit we should NOT forget!

Finishing up

Modifying your existing Template

We have to modify your existing Template to include the new Plugin, if we don't it'll never show anything and all this precious work was for nothing!

This varies from theme to theme but I'll show you where to do this using the Sample Site Rockstar.

The file we need to edit is located then here YOURNEWSCOOPDIR/themes/publication_2/theme_1/_tpl/_html-head.tpl

Find a bit where you want to add it to in the <head> and place the following code:

{{ facebook_meta_block }}{{ /facebook_meta_block }}

If your current Template already has Open Graph Meta tags, remove them else we'll have them double.

Remove the Newscoop cache

Clear out the Newscoop cache.

Trying it out

Load your Newscoop site with an article open. Now take a look in the Source Code and look in the <head> part of the page. You should now see something like:

<meta property="og:title" content="European Council candidates set to be named" />
<meta property="og:type" content="article" />
<meta property="og:url" content="http:/www.yoursite.com/en/jan2011/politics/64/European-Council-candidates-set-to-be-named.htm" />
<meta property="og:site_name" content="The New Custodian" />
<meta property="og:description" content="BRUSSELS - Italian and Greek candidates nominated for President of the European Council in secret ballot." />
<meta property="og:image" content="http://www.yoursite.com/images/cms-image-000000092.jpg" />

If this is the case, high-five yourself cause your done! You just made your own Plugin! This was a very simple Plugin and in another post I will show you how to create a more complex Plugin which will respond to Newscoop Events.

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