Find the Exponential Software extensions you want
| UNIX name | Owner | Status |
|---|---|---|
| FacebookPostImporterBundle | 7x | stable |
| Version | Compatible with |
|---|---|
| N/A | N/A |
This is an eZ Publish Symfony bundle to make it easy to import posts from a Facebook page. You simply have to describe how to map the Facebook posts to the eZ content class.
Add this repo to your composer.json file configuration:
{
"require": {
"contextualcode/facebook-post-importer-bundle": "dev-master"
},
"repositories": [
{
"type": "vcs",
"url": "[email protected]:contextualcode/FacebookPostImporterBundle.git"
}
]
}
and run composer update contextualcode/facebook-post-importer-bundle.
Enable the bundle in app/AppKernel.php (ezpublish/EzPublishKernel.php) by adding this line in the registerBundles method:
public function registerBundles()
{
$bundles = array(
...
new ContextualCode\FacebookPostImporterBundle\ContextualCodeFacebookPostImporterBundle()
);
You'll have to have these before using the bundle.
And set these as parameters in a yml file like:
cc_facebook_post_importer:
access_token: ...
app_id: ...
app_secret: ...
page_id: ...
facebook_version: ...
The facebook_version is optional. You can see the current version here here, which is "v2.12" as of January 30th, 2018.
These are are optional in the yml config, so you are able to set them dynamically:
// make a new service instance
$fbImporter = new FacebookPostImporterService();
// or, from inside a Controller or ContainerAwareCommand, use the existing one
// $fbImporter = $this->getContainer()->get( "contextualcode.facebookpostimporter.importer" );
$fbImporter->setFBParam("app_id", $appID);
$fbImporter->setFBParam("facebook_version", $facebookVersion);
...
But they must all be set before running the actual import.
You can set the language to import to by calling setLanguage:
$fbImporter->setLanguage('eng-GB');
The default is 'eng-US'.
The main part of using the FacebookPostImporter service is the function setCallableForEdge. This is the how the attribute mapping from a FB post to an eZ class is done.
The two parameters to setCallableForEdge are 1) a PHP callable (callback) that will do the mapping from Facebook data to eZ attributes, and 2) an optional parameter that chooses which data from Facebook to give to the first parameter.
More specifically, the second parameter (which is optional) to setCallableForEdge is the FB post edge name. It determines what data from the post is sent in the first parameter. If "none" (or left out), the first parameter will be the post itself (/post). Otherwise, you can specify any of the /post edges (https://developers.facebook.com/docs/graph-api/reference/v2.11/post#edges). For example, you can pass "/attachments" (or "attachments") as this parameter, and then the first parameter will be the data from /{$POST_ID}/attachments, so you could access any image attachment URLs (see example below in Usage).
The parameters that will be passed to the callable (callback) function you provide as the first parameter to setCallableForEdge are 1) data from the Facebook post and 2) a reference to an eZ\Publish\API\Repository\Values\Content\ContentCreateStruct. The callable should set the ContentCreateStruct fields as necessary, presumably using the Facebook data.
Important: Every one of your callables should return true if the eZ object should be published. If one callable returns false, the object won't be published. You can use this to control whether or not the importer publishes an object for posts that meet certain criteria (has image, long enough message, before or after a certain date, etc.).
After setting up the service and setting all of the callables, you can run import() to do the actual import. Import takes three optional parameters:
1) since, which should be a Unix timestamp. It will get added as a query param to all of the FB API calls, to limit the posts grabbed to only posts 'since' a certain datetime.
2) until, which should be a Unix timestamp that behaves just like since, but 'until' a certain datetime.
3) verbose, which should be a boolean that controls whether or not to output progress messages when importing.
Assuming you have an eZ class with identifier fb_post with attributes fb_post_id (text line), name (text line), and message (text block), the basic flow of using the FacebookPostImporter service will look like:
use ContextualCode\FacebookPostImporterBundle\Services\FacebookPostImporterService;
// make a new service instance
$fbImporter = new FacebookPostImporterService();
// or, from inside a Controller or ContainerAwareCommand, use the existing one
// $fbImporter = $this->getContainer()->get('contextualcode.facebookpostimporter.importer');
// set our container node ID
$fbImporter->setContainerNodeID(123);
// set our eZ class identifier
$fbImporter->setImportClass('fb_post');
// set the field to check before double-importing any post
$fbImporter->setPostIDAttribute('fb_post_id');
// set the mappings
// this will be run for each post's data
$fbImporter->setCallableForEdge('fbImporterPostEdgeMapper');
// run the import
$fbImporter->import();
// if you wanted to only grab the posts since yesterday
// $yesterdayTimestamp = time() - (24 * 60 * 60);
// $fbImporter->import($yesterdayTimestamp);
// this function will receive FB post data
// and a eZ\Publish\API\Repository\Values\Content\ContentCreateStruct by reference
function fbImporterPostEdgeMapper($data, &$contentCreateStruct)
{
// set the necessary fields with the FB data
// (you'll want to do more error checking than this)
$contentCreateStruct->setField('name', substr($data['message'], 0, 20));
$contentCreateStruct->setField('fb_post_id', $data['id']);
$contentCreateStruct->setField('message', $data['message']);
// give the green light to eventually publish this object
return true;
}
Note that we called $fbImporter->setPostIDAttribute('fb_post_id'); and stored the FB post id into the eZ object's fb_post_id field. These two things means that the next time we run this import, we won't import posts from Facebook that have an ID that is already in any eZ fb_post object (in our container node)'s fb_post_id attribute. So this import will be safe to run on a cronojob to import only the new posts. You should also take advantage of the since parameter when calling import().
What if you wanted to upload an image attachment from the Facebook post into an ezbinaryfile attribute called image, for example? That data is not available in the default /post edge. It's in the /{$POST_ID}/attachments edge. So, call setCallableForEdge like this (before you run import()):
$fbImporter->setCallableForEdge('fbImporterAttachmentsEdgeMapper', '/attachments');
function fbImporterAttachmentEdgeMapper($data, &$contentCreateStruct)
{
if (count($data) == 0) {
return true;
}
if (!isset($data[0]['media']['image']['src'])) {
return true;
}
$imgSrc = $data[0]['media']['image']['src'];
// download the image to disk however you want
// $filePath = downloadImage($imgSrc);
$contentCreateStruct->setField('image', $filePath);
return true;
}
There's a full example of downloading an image in /examples/ImportFBPostsCommand.php.
Note that you can set as many setCallableForEdges as there are post edges, but only the last one set for each edge will run.
There's an example Symfony command located at /examples/ImportFBPostsCommand.php. This shows how to use a Symfony command (that can be run as a cronjob) to import all Facebook posts as an eZ class named fb_post, in a certain container node.
http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License v2