]> git.mxchange.org Git - friendica.git/blobdiff - src/Module/Api/ApiResponse.php
Merge pull request #11141 from urbalazs/language-names
[friendica.git] / src / Module / Api / ApiResponse.php
index 2ce9137337f13b7f581df2768db169d6525f989e..0eb2f644b9fc57b5a893dad58c94914890dd524a 100644 (file)
@@ -1,35 +1,59 @@
 <?php
+/**
+ * @copyright Copyright (C) 2010-2022, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
 
 namespace Friendica\Module\Api;
 
 use Friendica\App\Arguments;
+use Friendica\App\BaseURL;
 use Friendica\Core\L10n;
-use Friendica\Core\Logger;
-use Friendica\Core\System;
-use Friendica\DI;
-use Friendica\Object\Api\Mastodon\Error;
+use Friendica\Module\Response;
 use Friendica\Util\Arrays;
-use Friendica\Util\HTTPInputData;
+use Friendica\Util\DateTimeFormat;
 use Friendica\Util\XML;
+use Psr\Log\LoggerInterface;
+use Friendica\Factory\Api\Twitter\User as TwitterUser;
 
 /**
- * This class is used to format and return API responses
+ * This class is used to format and create API responses
  */
-class ApiResponse
+class ApiResponse extends Response
 {
        /** @var L10n */
        protected $l10n;
        /** @var Arguments */
        protected $args;
+       /** @var LoggerInterface */
+       protected $logger;
+       /** @var BaseURL */
+       protected $baseUrl;
+       /** @var TwitterUser */
+       protected $twitterUser;
 
-       /**
-        * @param L10n      $l10n
-        * @param Arguments $args
-        */
-       public function __construct(L10n $l10n, Arguments $args)
+       public function __construct(L10n $l10n, Arguments $args, LoggerInterface $logger, BaseURL $baseUrl, TwitterUser $twitterUser)
        {
-               $this->l10n = $l10n;
-               $this->args = $args;
+               $this->l10n        = $l10n;
+               $this->args        = $args;
+               $this->logger      = $logger;
+               $this->baseUrl     = $baseUrl;
+               $this->twitterUser = $twitterUser;
        }
 
        /**
@@ -78,29 +102,57 @@ class ApiResponse
                return XML::fromArray($data3, $xml, false, $namespaces);
        }
 
+       /**
+        * Set values for RSS template
+        *
+        * @param array $arr Array to be passed to template
+        * @param int   $cid Contact ID of template
+        * @return array
+        */
+       private function addRSSValues(array $arr, int $cid)
+       {
+               if (empty($cid)) {
+                       return $arr;
+               }
+
+               $user_info = $this->twitterUser->createFromContactId($cid)->toArray();
+
+               $arr['$user'] = $user_info;
+               $arr['$rss'] = [
+                       'alternate'    => $user_info['url'],
+                       'self'         => $this->baseUrl . '/' . $this->args->getQueryString(),
+                       'base'         => $this->baseUrl,
+                       'updated'      => DateTimeFormat::utcNow(DateTimeFormat::API),
+                       'atom_updated' => DateTimeFormat::utcNow(DateTimeFormat::ATOM),
+                       'language'     => $user_info['lang'],
+                       'logo'         => $this->baseUrl . '/images/friendica-32.png',
+               ];
+
+               return $arr;
+       }
+
        /**
         * Formats the data according to the data type
         *
         * @param string $root_element Name of the root element
         * @param string $type         Return type (atom, rss, xml, json)
         * @param array  $data         JSON style array
+        * @param int    $cid          ID of the contact for RSS
         *
         * @return array|string (string|array) XML data or JSON data
         */
-       public function formatData(string $root_element, string $type, array $data)
+       public function formatData(string $root_element, string $type, array $data, int $cid = 0)
        {
                switch ($type) {
-                       case 'atom':
                        case 'rss':
+                               $data = $this->addRSSValues($data, $cid);
+                       case 'atom':
                        case 'xml':
-                               $ret = $this->createXML($data, $root_element);
-                               break;
+                               return $this->createXML($data, $root_element);
                        case 'json':
                        default:
-                               $ret = $data;
-                               break;
+                               return $data;
                }
-               return $ret;
        }
 
        /**
@@ -135,17 +187,17 @@ class ApiResponse
         *
         * @return void
         */
-       public static function error(int $code, string $description, string $message, string $format = null)
+       public function error(int $code, string $description, string $message, string $format = null)
        {
                $error = [
                        'error'   => $message ?: $description,
                        'code'    => $code . ' ' . $description,
-                       'request' => DI::args()->getQueryString()
+                       'request' => $this->args->getQueryString()
                ];
 
-               header(($_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.1') . ' ' . $code . ' ' . $description);
+               $this->setHeader(($_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.1') . ' ' . $code . ' ' . $description);
 
-               self::exit('status', ['status' => $error], $format);
+               $this->exit('status', ['status' => $error], $format);
        }
 
        /**
@@ -157,18 +209,18 @@ class ApiResponse
         *
         * @return void
         */
-       public static function exit(string $root_element, array $data, string $format = null)
+       public function exit(string $root_element, array $data, string $format = null, int $cid = 0)
        {
                $format = $format ?? 'json';
 
-               $return = DI::apiResponse()->formatData($root_element, $format, $data);
+               $return = $this->formatData($root_element, $format, $data, $cid);
 
                switch ($format) {
                        case 'xml':
-                               header('Content-Type: text/xml');
+                               $this->setType(static::TYPE_XML);
                                break;
                        case 'json':
-                               header('Content-Type: application/json');
+                               $this->setType(static::TYPE_JSON);
                                if (!empty($return)) {
                                        $json = json_encode(end($return));
                                        if (!empty($_GET['callback'])) {
@@ -178,40 +230,48 @@ class ApiResponse
                                }
                                break;
                        case 'rss':
-                               header('Content-Type: application/rss+xml');
-                               $return = '<?xml version="1.0" encoding="UTF-8"?>' . "\n" . $return;
+                               $this->setType(static::TYPE_RSS);
                                break;
                        case 'atom':
-                               header('Content-Type: application/atom+xml');
-                               $return = '<?xml version="1.0" encoding="UTF-8"?>' . "\n" . $return;
+                               $this->setType(static::TYPE_ATOM);
                                break;
                }
 
-               echo $return;
-               exit;
+               $this->addContent($return);
+       }
+
+       /**
+        * Wrapper around exit() for JSON only responses
+        *
+        * @param array $data
+        */
+       public function exitWithJson(array $data)
+       {
+               $this->exit('content', ['content' => $data], static::TYPE_JSON);
        }
 
        /**
         * Quit execution with the message that the endpoint isn't implemented
         *
         * @param string $method
+        * @param array  $request (optional) The request content of the current call for later analysis
         *
         * @return void
         * @throws \Exception
         */
-       public static function unsupported(string $method = 'all')
+       public function unsupported(string $method = 'all', array $request = [])
        {
-               $path = DI::args()->getQueryString();
-               Logger::info('Unimplemented API call',
+               $path = $this->args->getQueryString();
+               $this->logger->info('Unimplemented API call',
                        [
                                'method'  => $method,
                                'path'    => $path,
                                'agent'   => $_SERVER['HTTP_USER_AGENT'] ?? '',
-                               'request' => HTTPInputData::process()
+                               'request' => $request,
                        ]);
-               $error             = DI::l10n()->t('API endpoint %s %s is not implemented', strtoupper($method), $path);
-               $error_description = DI::l10n()->t('The API endpoint is currently not implemented but might be in the future.');
-               $errorobj          = new Error($error, $error_description);
-               System::jsonError(501, $errorobj->toArray());
+               $error             = $this->l10n->t('API endpoint %s %s is not implemented', strtoupper($method), $path);
+               $error_description = $this->l10n->t('The API endpoint is currently not implemented but might be in the future.');
+
+               $this->exit('error', ['error' => ['error' => $error, 'error_description' => $error_description]]);
        }
 }