Share.php 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. <?php
  2. /**
  3. * Manage the sharing options in FreshRSS.
  4. */
  5. class FreshRSS_Share {
  6. /**
  7. * The list of available sharing options.
  8. * @var array<string,FreshRSS_Share>
  9. */
  10. private static $list_sharing = [];
  11. /**
  12. * Register a new sharing option.
  13. * @param array{'type':string,'url':string,'transform'?:array<string>|array<string,string>,'field'?:string,'help'?:string,'form'?:'simple'|'advanced',
  14. * 'method'?:'GET'|'POST','HTMLtag'?:'button','deprecated'?:bool} $share_options is an array defining the share option.
  15. */
  16. private static function register(array $share_options): void {
  17. $type = $share_options['type'];
  18. if (isset(self::$list_sharing[$type])) {
  19. return;
  20. }
  21. self::$list_sharing[$type] = new FreshRSS_Share(
  22. $type,
  23. $share_options['url'],
  24. $share_options['transform'] ?? [],
  25. $share_options['form'] ?? 'simple',
  26. $share_options['help'] ?? '',
  27. $share_options['method'] ?? 'GET',
  28. $share_options['field'] ?? null,
  29. $share_options['HTMLtag'] ?? null,
  30. $share_options['deprecated'] ?? false
  31. );
  32. }
  33. /**
  34. * Register sharing options in a file.
  35. * @param string $filename the name of the file to load.
  36. */
  37. public static function load(string $filename): void {
  38. $shares_from_file = @include($filename);
  39. if (!is_array($shares_from_file)) {
  40. $shares_from_file = array();
  41. }
  42. foreach ($shares_from_file as $share_type => $share_options) {
  43. $share_options['type'] = $share_type;
  44. self::register($share_options);
  45. }
  46. uasort(self::$list_sharing, static function (FreshRSS_Share $a, FreshRSS_Share $b) {
  47. return strcasecmp($a->name(), $b->name());
  48. });
  49. }
  50. /**
  51. * Return the list of sharing options.
  52. * @return array<string,FreshRSS_Share>
  53. */
  54. public static function enum(): array {
  55. return self::$list_sharing;
  56. }
  57. /**
  58. * @param string $type the share type, null if $type is not registered.
  59. * @return FreshRSS_Share|null object related to the given type.
  60. */
  61. public static function get(string $type): ?FreshRSS_Share {
  62. if (!isset(self::$list_sharing[$type])) {
  63. return null;
  64. }
  65. return self::$list_sharing[$type];
  66. }
  67. /** @var string */
  68. private $type = '';
  69. /** @var string */
  70. private $name = '';
  71. /** @var string */
  72. private $url_transform = '';
  73. /** @var array<string>|array<string,array<string>> */
  74. private $transforms = [];
  75. /**
  76. * @phpstan-var 'simple'|'advanced'
  77. * @var string
  78. */
  79. private $form_type = 'simple';
  80. /** @var string */
  81. private $help_url = '';
  82. /** @var string|null */
  83. private $custom_name = null;
  84. /** @var string|null */
  85. private $base_url = null;
  86. /** @var string|null */
  87. private $id = null;
  88. /** @var string|null */
  89. private $title = null;
  90. /** @var string|null */
  91. private $link = null;
  92. /** @var bool */
  93. private $isDeprecated = false;
  94. /**
  95. * @phpstan-var 'GET'|'POST'
  96. * @var string
  97. */
  98. private $method = 'GET';
  99. /** @var string|null */
  100. private $field;
  101. /**
  102. * @phpstan-var 'button'|null
  103. * @var string
  104. */
  105. private $HTMLtag;
  106. /**
  107. * Create a FreshRSS_Share object.
  108. * @param string $type is a unique string defining the kind of share option.
  109. * @param string $url_transform defines the url format to use in order to share.
  110. * @param array<string>|array<string,array<string>> $transforms is an array of transformations to apply on link and title.
  111. * @param 'simple'|'advanced' $form_type defines which form we have to use to complete. "simple"
  112. * is typically for a centralized service while "advanced" is for
  113. * decentralized ones.
  114. * @param string $help_url is an optional url to give help on this option.
  115. * @param 'GET'|'POST' $method defines the sharing method (GET or POST)
  116. * @param 'button'|null $HTMLtag
  117. */
  118. private function __construct(string $type, string $url_transform, array $transforms, string $form_type,
  119. string $help_url, string $method, ?string $field, ?string $HTMLtag, bool $isDeprecated = false) {
  120. $this->type = $type;
  121. $this->name = _t('gen.share.' . $type);
  122. $this->url_transform = $url_transform;
  123. $this->help_url = $help_url;
  124. $this->HTMLtag = $HTMLtag;
  125. $this->isDeprecated = $isDeprecated;
  126. $this->transforms = $transforms;
  127. if (!in_array($form_type, array('simple', 'advanced'))) {
  128. $form_type = 'simple';
  129. }
  130. $this->form_type = $form_type;
  131. if (!in_array($method, array('GET', 'POST'))) {
  132. $method = 'GET';
  133. }
  134. $this->method = $method;
  135. $this->field = $field;
  136. }
  137. /**
  138. * Update a FreshRSS_Share object with information from an array.
  139. * @param array<string,string> $options is a list of information to update where keys should be
  140. * in this list: name, url, id, title, link.
  141. */
  142. public function update(array $options): void {
  143. $available_options = array(
  144. 'name' => 'custom_name',
  145. 'url' => 'base_url',
  146. 'id' => 'id',
  147. 'title' => 'title',
  148. 'link' => 'link',
  149. 'method' => 'method',
  150. 'field' => 'field',
  151. );
  152. foreach ($options as $key => $value) {
  153. if (isset($available_options[$key])) {
  154. $this->{$available_options[$key]} = $value;
  155. }
  156. }
  157. }
  158. /**
  159. * Return the current type of the share option.
  160. */
  161. public function type(): string {
  162. return $this->type;
  163. }
  164. /**
  165. * Return the current method of the share option.
  166. * @return 'GET'|'POST'
  167. */
  168. public function method(): string {
  169. return $this->method;
  170. }
  171. /**
  172. * Return the current field of the share option. It’s null for shares
  173. * using the GET method.
  174. */
  175. public function field(): ?string {
  176. return $this->field;
  177. }
  178. /**
  179. * Return the current form type of the share option.
  180. * @return 'simple'|'advanced'
  181. */
  182. public function formType(): string {
  183. return $this->form_type;
  184. }
  185. /**
  186. * Return the current help url of the share option.
  187. */
  188. public function help(): string {
  189. return $this->help_url;
  190. }
  191. /**
  192. * Return the custom type of HTML tag of the share option, null for default.
  193. * @return 'button'|null
  194. */
  195. public function HTMLtag(): ?string {
  196. return $this->HTMLtag;
  197. }
  198. /**
  199. * Return the current name of the share option.
  200. */
  201. public function name(bool $real = false): ?string {
  202. if ($real || is_null($this->custom_name) || empty($this->custom_name)) {
  203. return $this->name;
  204. } else {
  205. return $this->custom_name;
  206. }
  207. }
  208. /**
  209. * Return the current base url of the share option.
  210. */
  211. public function baseUrl(): string {
  212. return $this->base_url;
  213. }
  214. /**
  215. * Return the deprecated status of the share option.
  216. */
  217. public function isDeprecated(): bool {
  218. return $this->isDeprecated;
  219. }
  220. /**
  221. * Return the current url by merging url_transform and base_url.
  222. */
  223. public function url(): string {
  224. $matches = array(
  225. '~ID~',
  226. '~URL~',
  227. '~TITLE~',
  228. '~LINK~',
  229. );
  230. $replaces = array(
  231. $this->id(),
  232. $this->base_url,
  233. $this->title(),
  234. $this->link(),
  235. );
  236. return str_replace($matches, $replaces, $this->url_transform);
  237. }
  238. /**
  239. * Return the id.
  240. * @param bool $raw true if we should get the id without transformations.
  241. */
  242. public function id(bool $raw = false): ?string {
  243. if ($raw) {
  244. return $this->id;
  245. }
  246. return self::transform($this->id, $this->getTransform('id'));
  247. }
  248. /**
  249. * Return the title.
  250. * @param bool $raw true if we should get the title without transformations.
  251. */
  252. public function title(bool $raw = false): string {
  253. if ($raw) {
  254. return $this->title;
  255. }
  256. return self::transform($this->title, $this->getTransform('title'));
  257. }
  258. /**
  259. * Return the link.
  260. * @param bool $raw true if we should get the link without transformations.
  261. */
  262. public function link(bool $raw = false): string {
  263. if ($raw) {
  264. return $this->link;
  265. }
  266. return self::transform($this->link, $this->getTransform('link'));
  267. }
  268. /**
  269. * Transform a data with the given functions.
  270. * @param string $data the data to transform.
  271. * @param array<string> $transform an array containing a list of functions to apply.
  272. * @return string the transformed data.
  273. */
  274. private static function transform(string $data, array $transform): string {
  275. if (!is_array($transform) || empty($transform)) {
  276. return $data;
  277. }
  278. foreach ($transform as $action) {
  279. if (is_string($action) && $action != '') {
  280. $data = call_user_func($action, $data);
  281. }
  282. }
  283. return $data;
  284. }
  285. /**
  286. * Get the list of transformations for the given attribute.
  287. * @param string $attr the attribute of which we want the transformations.
  288. * @return array<string> containing a list of transformations to apply.
  289. */
  290. private function getTransform(string $attr): array {
  291. if (array_key_exists($attr, $this->transforms)) {
  292. return $this->transforms[$attr];
  293. }
  294. return $this->transforms;
  295. }
  296. }