| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335 |
- <?php
- declare(strict_types=1);
- /**
- * Manage the sharing options in FreshRSS.
- */
- class FreshRSS_Share {
- /**
- * The list of available sharing options.
- * @var array<string,FreshRSS_Share>
- */
- private static array $list_sharing = [];
- /**
- * Register a new sharing option.
- * @param array{type:string,url:string,transform?:array<callable>|array<string,array<callable>>,field?:string,help?:string,form?:'simple'|'advanced',
- * method?:'GET'|'POST',HTMLtag?:'button',deprecated?:bool} $share_options is an array defining the share option.
- */
- public static function register(array $share_options): void {
- $type = $share_options['type'];
- if (isset(self::$list_sharing[$type])) {
- return;
- }
- self::$list_sharing[$type] = new FreshRSS_Share(
- $type,
- $share_options['url'],
- $share_options['transform'] ?? [],
- $share_options['form'] ?? 'simple',
- $share_options['help'] ?? '',
- $share_options['method'] ?? 'GET',
- $share_options['field'] ?? null,
- $share_options['HTMLtag'] ?? null,
- $share_options['deprecated'] ?? false
- );
- }
- /**
- * Register sharing options in a file.
- * @param string $filename the name of the file to load.
- */
- public static function load(string $filename): void {
- $shares_from_file = @include($filename);
- if (!is_array($shares_from_file)) {
- $shares_from_file = [];
- }
- foreach ($shares_from_file as $share_type => $share_options) {
- if (!is_array($share_options)) {
- continue;
- }
- $share_options['type'] = $share_type;
- /** @var array{type:string,url:string,transform?:array<callable>|array<string,array<callable>>,field?:string,help?:string,form?:'simple'|'advanced',
- * method?:'GET'|'POST',HTMLtag?:'button',deprecated?:bool} $share_options */
- self::register($share_options);
- }
- uasort(self::$list_sharing, static fn(FreshRSS_Share $a, FreshRSS_Share $b) => strcasecmp($a->name() ?? '', $b->name() ?? ''));
- }
- /**
- * Return the list of sharing options.
- * @return array<string,FreshRSS_Share>
- */
- public static function enum(): array {
- return self::$list_sharing;
- }
- /**
- * @param string $type the share type, null if $type is not registered.
- * @return FreshRSS_Share|null object related to the given type.
- */
- public static function get(string $type): ?FreshRSS_Share {
- return self::$list_sharing[$type] ?? null;
- }
- private readonly string $name;
- /**
- * @phpstan-var 'simple'|'advanced'
- */
- private readonly string $form_type;
- private ?string $custom_name = null;
- private ?string $base_url = null;
- private ?string $id = null;
- private ?string $title = null;
- private ?string $link = null;
- /**
- * @phpstan-var 'GET'|'POST'
- */
- private string $method;
- /**
- * Create a FreshRSS_Share object.
- * @param string $type is a unique string defining the kind of share option.
- * @param string $url_transform defines the url format to use in order to share.
- * @param array<callable>|array<string,array<callable>> $transforms is an array of transformations to apply on link and title.
- * @param 'simple'|'advanced' $form_type defines which form we have to use to complete. "simple"
- * is typically for a centralized service while "advanced" is for
- * decentralized ones.
- * @param string $help_url is an optional url to give help on this option.
- * @param 'GET'|'POST' $method defines the sharing method (GET or POST)
- * @param 'button'|null $HTMLtag
- */
- private function __construct(
- private readonly string $type,
- private readonly string $url_transform,
- private array $transforms,
- string $form_type,
- private readonly string $help_url,
- string $method,
- private ?string $field,
- private readonly ?string $HTMLtag,
- private readonly bool $isDeprecated = false
- ) {
- $this->name = _t('gen.share.' . $this->type);
- if (!in_array($form_type, ['simple', 'advanced'], true)) {
- $form_type = 'simple';
- }
- $this->form_type = $form_type;
- if (!in_array($method, ['GET', 'POST'], true)) {
- $method = 'GET';
- }
- $this->method = $method;
- }
- /**
- * Update a FreshRSS_Share object with information from an array.
- * @param array<string,string> $options is a list of information to update where keys should be
- * in this list: name, url, id, title, link.
- */
- public function update(array $options): void {
- foreach ($options as $key => $value) {
- switch ($key) {
- case 'name':
- $this->custom_name = $value;
- break;
- case 'url':
- $this->base_url = $value;
- break;
- case 'id':
- $this->id = $value;
- break;
- case 'title':
- $this->title = $value;
- break;
- case 'link':
- $this->link = $value;
- break;
- case 'method':
- $this->method = strcasecmp($value, 'POST') === 0 ? 'POST' : 'GET';
- break;
- case 'field':
- $this->field = $value;
- break;
- }
- }
- }
- /**
- * Return the current type of the share option.
- */
- public function type(): string {
- return $this->type;
- }
- /**
- * Return the current method of the share option.
- * @return 'GET'|'POST'
- */
- public function method(): string {
- return $this->method;
- }
- /**
- * Return the current field of the share option. It’s null for shares
- * using the GET method.
- */
- public function field(): ?string {
- return $this->field;
- }
- /**
- * Return the current form type of the share option.
- * @return 'simple'|'advanced'
- */
- public function formType(): string {
- return $this->form_type;
- }
- /**
- * Return the current help url of the share option.
- */
- public function help(): string {
- return $this->help_url;
- }
- /**
- * Return the custom type of HTML tag of the share option, null for default.
- * @return 'button'|null
- */
- public function HTMLtag(): ?string {
- return $this->HTMLtag;
- }
- /**
- * Return the current name of the share option.
- */
- public function name(bool $real = false): ?string {
- if ($real || empty($this->custom_name)) {
- return $this->name;
- } else {
- return $this->custom_name;
- }
- }
- /**
- * Return the current base url of the share option.
- */
- public function baseUrl(): string {
- return $this->base_url ?? '';
- }
- /**
- * Return the deprecated status of the share option.
- */
- public function isDeprecated(): bool {
- return $this->isDeprecated;
- }
- /**
- * Return the current url by merging url_transform and base_url.
- */
- public function url(): string {
- $matches = [
- '~ID~',
- '~URL~',
- '~TITLE~',
- '~LINK~',
- ];
- $replaces = [
- $this->id() ?? '',
- $this->base_url ?? '',
- $this->title(),
- $this->link(),
- ];
- return str_replace($matches, $replaces, $this->url_transform);
- }
- /**
- * Return the id.
- * @param bool $raw true if we should get the id without transformations.
- */
- public function id(bool $raw = false): ?string {
- if ($raw) {
- return $this->id;
- }
- if ($this->id === null) {
- return null;
- }
- return self::transform($this->id, $this->getTransform('id'));
- }
- /**
- * Return the title.
- * @param bool $raw true if we should get the title without transformations.
- */
- public function title(bool $raw = false): string {
- if ($raw) {
- return $this->title ?? '';
- }
- if ($this->title === null) {
- return '';
- }
- return self::transform($this->title, $this->getTransform('title'));
- }
- /**
- * Return the link.
- * @param bool $raw true if we should get the link without transformations.
- */
- public function link(bool $raw = false): string {
- if ($raw) {
- return $this->link ?? '';
- }
- if ($this->link === null) {
- return '';
- }
- return self::transform($this->link, $this->getTransform('link'));
- }
- /**
- * Transform a data with the given functions.
- * @param string $data the data to transform.
- * @param array<callable> $transform an array containing a list of functions to apply.
- * @return string the transformed data.
- */
- private static function transform(string $data, array $transform): string {
- if (empty($transform)) {
- return $data;
- }
- foreach ($transform as $action) {
- $return = call_user_func($action, $data);
- if (is_string($return)) {
- $data = $return;
- }
- }
- return $data;
- }
- /**
- * Get the list of transformations for the given attribute.
- * @param string $attr the attribute of which we want the transformations.
- * @return list<callable> containing a list of transformations to apply.
- */
- private function getTransform(string $attr): array {
- if (array_key_exists($attr, $this->transforms)) {
- $candidates = is_array($this->transforms[$attr]) ? $this->transforms[$attr] : [];
- } else {
- $candidates = $this->transforms;
- }
- $transforms = [];
- foreach ($candidates as $transform) {
- if (is_callable($transform)) {
- $transforms[] = $transform;
- }
- }
- return $transforms;
- }
- }
|