2

My client is looking to integrate news content coming from an external API into their Joomla website. The API is in the JSON format and includes multiple fields like title, summary, date, and full text content.

I am looking for a way to get the data from the API and map it to the appropriate fields in com_content. The generated articles would be assigned to one single category.

I have reviewed this post and the Joomla 3 API http client class, but I am not sure how to get started. I have familiarity with Joomla PHP programming, but not with consuming external data through APIs.

The website is running Joomla 3.10.3.

Any suggestions are greatly appreciated.

2 Answers 2

2
+25

Do you want to do a fetch only from the news website (GET requests only) or do you need to push back information from your Joomla! 3 website eg (POST request) ?

Joomla 3 HTTP Client is the same than the 1.x branch on Packagist HTTP Client 1.x

If what you want is GET only you might want to consider using com_newsfeeds and incoming rss feed.

You could use something like com_api for Joomla! 3 to do this.

One side note about security: Joomla 3.10.4 is already out you should consider backup your site and update to this version.

EDIT:

I coded a plugin to get you up and running as an example to fetch articles from a news api like newsapi.org

here is the revelant code of the plugin


<?php
declare(strict_types=1);
/**
 * System - Examplenews
 *
 * @package    Examplenews
 *
 * @author     Alexandre ELISÉ <[email protected]>
 * @copyright  Copyright(c) 2009 - 2021 Alexandre ELISÉ. All rights reserved
 * @license    GNU General Public License version 2 or later; see LICENSE.txt
 * @link       https://alexapi.cloud
 */

defined('_JEXEC') or die;

use Joomla\CMS\Application\CMSApplication;
use Joomla\CMS\Http\Response;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\Input\Input;
use Joomla\Registry\Registry;

/**
 * Examplenews plugin.
 *
 * @package   Examplenews
 * @since     0.1.0
 */
class PlgSystemExamplenews extends CMSPlugin
{
    /**
     * Application object
     *
     * @var    CMSApplication
     * @since  0.1.0
     */
    protected ?CMSApplication $app = null;

    /**
     * Database object
     *
     * @var    JDatabaseDriver
     * @since  0.1.0
     */
    protected ?JDatabaseDriver $db = null;

    /**
     * @param $subject
     * @param $config
     */
    public function __construct(&$subject, $config = [])
    {
        $this->autoloadLanguage = true;
        parent::__construct($subject, $config);
    }

    /**
     * Fetch top-headlines articles from newsapi.org API using the Joomla! 3.10
     * Http Client and the StreamTransport
     * This is meant to be sample code as an example to guide you along the way to
     * achieve your goal
     * @return mixed
     */
    public function onAjaxExamplenews()
    {
        if ($this->app->isClient('administrator'))
        {
            return;
        }

        $this->handleRequest($this->app->input);
    }

    public function onAfterInitialise()
    {

        if ($this->app->isClient('administrator'))
        {
            return;
        }

        $this->handleRequest($this->app->input);
    }


    /**
     * Provide a way to test this method independently
     *
     * @param   \Joomla\Input\Input|null  $givenInput
     *
     * @return mixed
     */
    private function handleRequest(?Input $givenInput = null)
    {
        $input = $givenInput ?? $this->app->input;

        //to be safe we should add a csrf-token verification
        // but since
        // a GET request is idempotent (does change with same input multiple times) we should be fine
        // If you feel it's insecuren, uncomment the next line
        // Session::checkToken('GET') || die(Text::_('JINVALID_TOKEN'));

        $verb = strtoupper($input->getMethod());

        try
        {
            switch ($verb)
            {
                case 'GET':

                    $uri = new Joomla\CMS\Uri\Uri('https://newsapi.org/v2/top-headlines');

                    $uri->setQuery(
                        [
                            'country'  => 'ca',
                            'category' => 'business', 'apiKey' =>
                                $this->params->get('apiKey', ''),
                        ]
                    );

                    $response          = new Response;
                    $response->headers = [
                        'Content-Type' => 'application/json',
                    ];
                    $response->code    = 200;
                    $response->body    = file_get_contents((string) $uri);

                    // Render the response
                    $this->render($response);
                default:
                    throw new BadMethodCallException('HTTP Verb Unknown', 405);
            }
        }
        catch (Throwable $throwable)
        {
            header('Content-Type: application/json');
            echo (new Registry($throwable))->toString();
            die;
        }
    }

    /**
     * @param   \Joomla\CMS\Http\Response  $response
     *
     * @return void
     */
    private function render(Response $response)
    {
        // Clear headers first to prevent unexpected errors
        // then redefined custom ones in the render method
        $this->app->clearHeaders();

        foreach ($response->headers as $key => $value)
        {
            header(sprintf('%s: %s', $key, $value));
        }

        http_response_code($response->code);
        echo $response->body;
        die;
    }
}


When using the default Http Client I found a weird behaviour not allowing me to successfully do get requests that's why I directly used file_get_contents and Joomla! Uri class to do the same thing more efficiently simpler and optimized for GET requests.

You can use the fetched data in an ajax use case too on your joomla website after installing the sample plugin I provided.

https://example.org/index.php?option=com_ajax&plugin=examplenews&group=system&format=raw&tmpl=component 

the plugin is on my GitHub for ease of use for you and other SO users. Direct download link Source code of the plugin on GitHub

10
  • I only need to perform GET requests from the news API. There is no RSS feed for this content as it requires a commercial API key for access. I have reviewed com_api. Would writing a plugin allow me to fetch the news articles and write the data to com_content? Dec 20, 2021 at 19:50
  • Hi @MikeHermary I have written a sample plugin for you to put you on the right track will upload it here and on github as an example to base your work on Dec 20, 2021 at 20:39
  • Awesome! I really appreciate the assistance. Dec 20, 2021 at 22:41
  • No problem. I like sharing what I have learned along the way constantly learning new things every day. Happy to share with the Super Joomlers Community. Dec 20, 2021 at 23:29
  • 1
    My apologies. I am away on holidays have not had a chance to test your code. I will do that early next week. Dec 31, 2021 at 18:13
0

The above answer is probably better but thought I'd share our approach.

Our client uses an external site (not Joomla!) to process charity donations. So - we need to pull the total donated amount from this external site to put on their Joomla! site.

External Site: External Site

The external site doesn't have an API to pull from - so we fetch the external webpage via cURL and can load it via either module or our Joomla! Template.

Our Template

As the external page is huge - we are creating a .txt file with the relevant total saved, and refreshing if it's older than 6 hours.

We use FLEXIcontent CCK to simplify our Joomla admin for the client - with a sponsorship URL field that triggers the code:

Admin

So on each of our sponsor pages, the client enters the URL, and that fetches the results.

Code: https://gist.github.com/iamrobert/0a19a6f43db017cff368ea244922052d

Joomla! has custom fields - so there isn't really anything unique to our code that couldn't be done via Joomla! Plus when I first started I just inserted it into our template index.php to understand the code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.