All about the development of Exponential (CMS) by Graham Brookins, 7x (formerly Brookins Consulting) and our think tank kracker.org.

eZ Publish / Exponential Extensions From GitHub Repositories Mirrored and Forked Have Been Imported into Exponential Projects.

We have over 3652 project extensions now available on the Exponential Projects website portal / source code forge.

Join the site today by registering. Then create your first extension project! Then have your team join existing extension projects to collaborate and work together on useful tools and products.

I bring news of a new solution 7x is working on for developers with an interest to syndicate information without an rss / atom / xml / etc feed available.

Today if you want to include your companies YouTube Playlist videos (say commercials or educational materials) you can embed this content manually within the administrator content editing features available by default.

What if you want to sync content from YouTube like your companies playlist video content (the meta data not the actual videos, playback is through YouTube's embed video URL APIs) into the eZ Content Tree Automatically?

Currently this is possible today without a feed via old fashioned web page scraping of specific account playlists video title and video URL URI v element data (video's id) using RSS-Bridge.

Normally RSS-Bridge (doc) is a standalone application well written in OOP PHP. Because documentation on using the library standalone is limited we created a solution to bootup the software layers and call the provided YouTube Playlist Data Collection APIs from RSS-Bridge within an eZ Publish Request Scope within a eZ Publish Cronjob Part Script.

Filename: extension/sevenx_rss_bridge/cronjobs/7xRssBridgeYoutubeFeedImport.php

<?php

if ( !$isQuiet )
{
$cli->output( "Creating youtube video object(s) ..." );
}

$count = SevenxRssBridgeFeedImport::importFeedContentObjects();

if ( !$isQuiet )
{
$cli->output( "Number of objects created: $count" );
$cli->output( "Done." );
}

?>

Got your attention now with a stub for calling the features we need within eZ (Remember to enable via cronjob settings and clear all caches).

Filename: extension/sevenx_rss_bridge/settings/cronjobs.ini.append.php

<?php /* #?ini charset="utf8"?

[CronjobSettings]
ExtensionDirectories[]=sevenx_rss_bridge

[CronjobPart-youtube-feed-import]
Scripts[]=7xRssBridgeYoutubeFeedImport.php

*/ ?>

Next we have the worker class that does the work to fetch the YouTube information, create the YouTube videos (Meta Data Based Embeds in a Playlist) underneath Youtube Playlist Nodes Containing the Playlist Meta Data.

With this we first create the playlist nodes (locations) with the required playlist YouTube embed URL + Parameters (like list which helps provide long form content within a playlist). With the following code in place (remember to regenerate eZ's Autoloads) we can call the cronjob and sync / import the data from YouTube into eZ Publish Content Tree.

Filename: extension/sevenx_rss_bridge/classes/SevenxRssBridgeFeedImport.php

<?php

class SevenxRssBridgeFeedImport
{
public static function importFeedContentObjects()
{
// Settings
$storageNodeID = eZINI::instance('sevenx_videos.ini')->variable('PlaylistSettings','PlaylistNodeID');

// Fetch Playlists Objects to store the videos underneath.
$playlists = self::fetchNodeContent($storageNodeID );

// Initialize the count of imported items
$importedCount = 0;

// Include RSS-Bridge autoloader
require_once('vendor/rss-bridge/rss-bridge/lib/bootstrap.php');

foreach ( $playlists as $playlist )
{
if ( $playlist->attribute('children_count') <= 0 )
{
$playlistsNodeID = $playlist->attribute('node_id');

$dm = $playlist->dataMap();
$playlistID = $dm[ 'youtube_url' ]->content();
if ( !str_contains($playlistID, 'videoseries' ) )
continue;

$playlistID = explode( 'list=', $playlistID )[1];
$bridgeParams = [
'p' => $playlistID
];

try {
$main = new RssBridge();

$bridgeFactory = new BridgeFactory();
// Directly instantiate the YouTubeBridge class
$bridge = $bridgeFactory->create( YoutubeBridge::class );

// Set parameters
$bridge->setInput( $bridgeParams );

// Fetch data
$data = $bridge->collectData();
$items = $bridge->getItems();
//var_dump( $items );

// Process each video entry
foreach ($items as $item) {
$importedCount += self::importYouTubeVideo($item, $playlistsNodeID, $playlistID);
}

} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
return 0; // Return 0 in case of error
}
}
}

echo "Successfully imported YouTube videos.\n";
return $importedCount; // Return the count of imported items
}

private static function importYouTubeVideo($item, $storageNodeID, $playlistID)
{
$adminUser = 'admin'; // no password used so safe and available by default. change if needed.
$classID = 48; // Note: Please change to your video class.
// Extract video data
$title = $item['title'];
$description = $item['content'];
$url = $item['uri'];
$video = explode( '?v=', $url )[1];
$url = "https://www.youtube.com/embed/$video?si=" . $video . '&list=' . $playlistID;

// var_dump($item['title']);
// var_dump($url);
// die('fin');
// return 1;

// Fetch admin user
$user = eZUser::fetchByName( $adminUser );
$userCreatorID = $user->attribute( 'contentobject_id' );

// Create object
$defaultSectionID = 1;
$class = eZContentClass::fetch( $classID );
$contentObject = $class->instantiate( $userCreatorID, $defaultSectionID );

// Set remote_id content
//$remoteID = "contentserver:incomingnode";
//$contentObject->setAttribute( 'remote_id', $remoteID );
$contentObject->store();

// Fetch related IDs
$contentObjectID = $contentObject->attribute( 'id' );
//$userID = $contentObjectID;

// Create node assignment
$nodeAssignment = eZNodeAssignment::create( array( 'contentobject_id' => $contentObjectID,
'contentobject_version' => 1,
'parent_node' => $storageNodeID,
'is_main' => 1 ) );
$nodeAssignment->store();

// Set version modified and status content
$version = $contentObject->version( 1 );
$version->setAttribute( 'modified', time() );
$version->setAttribute( 'status', eZContentObject::STATUS_DRAFT );
$version->store();

// Fetch contentObject IDs
$contentObjectID = $contentObject->attribute( 'id' );
$contentObjectAttributes = $version->contentObjectAttributes();

// Set Name
$contentObjectAttributes[0]->setAttribute( 'data_text', $title );
$contentObjectAttributes[0]->store();

// Set Name
$contentObjectAttributes[2]->fromString( "$url|$title" );
$contentObjectAttributes[2]->store();

// Publish content object to top level root node
$operationResult = eZOperationHandler::execute( 'content', 'publish', array( 'object_id' => $contentObjectID,'version' => 1 ) );

echo "Imported video: $title\n $url\n";
return 1; // Return 1 to indicate successful import
}

public static function fetchNodeContent( $nodeID = 2, $limit = false, $classIdentifierArray = array( 'playlist' ) )
{
$node = eZContentObjectTreeNode::fetch($nodeID);

if (!$node) {
echo "Node with ID $nodeID not found.\n";
return [];
}

// Fetch only objects of 'playlist' class
$params = [
'ClassFilterType' => array( 'include' ),
'ClassFilterArray' => $classIdentifierArray, // Replace 'playlist' with your desired class identifier
'Limit' => $limit // Adjust the limit as needed
];

$result = eZContentObjectTreeNode::subTreeByNodeID($params, $nodeID);

return $result;
}
}

?>

Here is an example of calling the cronjob script. We do this after the above is properly installed and configured.

cd /path/to/ezpublish/; clear; date;./runcronjobs.php youtube-feed-import; date

This solution works well by simulation of the RSS-Bridge Application which effortlessly (once you learn how to call it correctly) fetches Youtube / Instagram / Telegram / Other content for you to store and use within your own website powered by eZ Publish.

We are working to release a package of this software ready to install and customize to meet your own needs. Until then use this blog post as a project origin story / working example of a solution for content stored in web applications which do not provide feeds.

Tag Cloud

#working-late-nights 100% Working Example 100% Working Installation 2.4.0.0 2.4.0.1 2.4.0.1 PHP 8.3 Support 2.5.0.x 2024 2024/Q3 6.0.4 6.0.6 6.0.7 6.0.8 6.0.9 7x 7x Blog 7x Digg 7x Symbolic Link Distribution of eZ Publish 6 7x Valkey 8.3 Addons Alpha Audio Automation BC Blog Book Bottom of the Pages CMS CSS Call Me Campaign Changes Community Composer Composer eZ Publish extension Contact Content Syncronization Contribute Copy Subtree Count Cronjob Databases Default Installation Demo DBs Design Designs Development Digg Project DiggClone Direction Documentation Download Download Statistics DragonflyDB Dual Kernel Educational Emails Embeded Image Class Engine Enterprise Grade Example Exp Expansive Features Now Available! Exponentail Platform Legacy Exponential Exponential 6 Exponential Basic Exponential CMS Exponential Platform Exponential Platform Legacy Exponential Projects Exponential.earth Extension Extensions Features First Seps Framework Free Free Documentation License Free Software From GitHub Fun Funding GFDL GNU GPL GPLv2 (or later) GitHub Google Graham Brookins Guide Headless CMS History Hit me up Home Page Hosting Howto Import Importing content Improvements Installation Configuration Introducing Introduction Kernel Key / Value Stores Learning PHP Learning eZ Publish Learning eZ Publish 3 Legacy Maintenance Messaging Mirror Multi Domain Installations Name Change Netgen Networking New Content New Developments New Features New Report View New Stack New Year New development News Now available! Now online Open Source Open Source Project PHP PHP 5.x PHP 7.x PHP 8 PHP 8.2 PHP 8.3 PHP 8.3 Support PHP 8.4 Support PHP 8.x PHP CMS For Beginers PHP Websites Package Packages Page View Patreon Performance Podcast Private Messager Project Questions RSS Feed RSS-Bridge Library ReST APIs Rebrand Rebranding Recent Improvements Record Redesign Redis Release Releases Remarks Report Responsive Restored SOAP SQLIte SQLite. eZ Publish. New feature Screen Recording Script Scripting Search Second Look Setup Wizard Source Code Sponsor Sponsorship Stable Status updates Styles Support Symfony Sync Syndicate System of Systems Testers Welcome Testing Thousands of Exponential Extensions Tip Try Today Two way Updates Upgrade Valkey Value Added Features Vendors Version Version Control Version Numbers Websites Statistics Wordpress admin design admin3 clone.digg.one cms design developer developer initiative digg.one do not wait for the release to try drag and drop installation eZ eZ PM eZ Package Development eZ Publish eZ Publish 6 eZ Publish 6.0 CMS eZ Publish Basic eZ Publish Database Configuration Builder eZ Publish Symbolic Link Distribution eZ Region eZ Update eZpedia expand the future of eZ Publish exponential ez ezcommunity ezpublish flexible fund me git github hcaptcha php php8 projects rebranding recaptcha responsive share simple support update functionality v1.1.0 valkey

Mon Tue Wed Thu Fri Sat Sun
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        

Tags

Powered by eZ Publish™ CMS Open Source Web Content Management. Copyright © 1999-2014 eZ Systems AS (except where otherwise noted). All rights reserved.