summaryrefslogtreecommitdiffstatshomepage
path: root/core/modules/media/src/OEmbed/Endpoint.php
blob: d70ae2c30f6fb1aff6d5cd7102eb2f1b53dfe1cc (plain) (blame)
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
<?php

namespace Drupal\media\OEmbed;

use Drupal\Component\Utility\UrlHelper;

/**
 * Value object for oEmbed provider endpoints.
 *
 * @internal
 *   This class is an internal part of the oEmbed system and should only be
 *   instantiated by instances of Drupal\media\OEmbed\Provider.
 */
class Endpoint {

  /**
   * The endpoint's URL.
   *
   * @var string
   */
  protected $url;

  /**
   * The provider this endpoint belongs to.
   *
   * @var \Drupal\media\OEmbed\Provider
   */
  protected $provider;

  /**
   * List of URL schemes supported by the provider.
   *
   * @var string[]
   */
  protected $schemes;

  /**
   * List of supported formats. Only 'json' and 'xml' are allowed.
   *
   * @var string[]
   *
   * @see https://oembed.com/#section2
   */
  protected $formats;

  /**
   * Whether the provider supports oEmbed discovery.
   *
   * @var bool
   */
  protected $supportsDiscovery;

  /**
   * Endpoint constructor.
   *
   * @param string $url
   *   The endpoint URL. May contain a "{format}" placeholder.
   * @param \Drupal\media\OEmbed\Provider $provider
   *   The provider this endpoint belongs to.
   * @param string[] $schemes
   *   List of URL schemes supported by the provider.
   * @param string[] $formats
   *   List of supported formats. Can be "json", "xml" or both.
   * @param bool $supports_discovery
   *   Whether the provider supports oEmbed discovery.
   *
   * @throws \InvalidArgumentException
   *   If the endpoint URL is empty.
   */
  public function __construct($url, Provider $provider, array $schemes = [], array $formats = [], $supports_discovery = FALSE) {
    $this->provider = $provider;
    $this->schemes = $schemes;

    $this->formats = $formats = array_map('mb_strtolower', $formats);
    // Assert that only the supported formats are present.
    assert(array_diff($formats, ['json', 'xml']) == []);

    // Use the first provided format to build the endpoint URL. If no formats
    // are provided, default to JSON.
    $this->url = str_replace('{format}', reset($this->formats) ?: 'json', $url);

    if (!UrlHelper::isValid($this->url, TRUE) || !UrlHelper::isExternal($this->url)) {
      throw new \InvalidArgumentException('oEmbed endpoint must have a valid external URL');
    }

    $this->supportsDiscovery = (bool) $supports_discovery;
  }

  /**
   * Returns the endpoint URL.
   *
   * The URL will be built with the first available format. If the endpoint
   * does not provide any formats, JSON will be used.
   *
   * @return string
   *   The endpoint URL.
   */
  public function getUrl() {
    return $this->url;
  }

  /**
   * Returns the provider this endpoint belongs to.
   *
   * @return \Drupal\media\OEmbed\Provider
   *   The provider object.
   */
  public function getProvider() {
    return $this->provider;
  }

  /**
   * Returns list of URL schemes supported by the provider.
   *
   * @return string[]
   *   List of schemes.
   */
  public function getSchemes() {
    return $this->schemes;
  }

  /**
   * Returns list of supported formats.
   *
   * @return string[]
   *   List of formats.
   */
  public function getFormats() {
    return $this->formats;
  }

  /**
   * Returns whether the provider supports oEmbed discovery.
   *
   * @return bool
   *   Returns TRUE if the provides discovery, otherwise FALSE.
   */
  public function supportsDiscovery() {
    return $this->supportsDiscovery;
  }

  /**
   * Tries to match a URL against the endpoint schemes.
   *
   * @param string $url
   *   Media item URL.
   *
   * @return bool
   *   TRUE if the URL matches against the endpoint schemes, otherwise FALSE.
   */
  public function matchUrl($url) {
    foreach ($this->getSchemes() as $scheme) {
      // Convert scheme into a valid regular expression.
      $regexp = str_replace(['.', '*', '?'], ['\.', '.*', '\?'], $scheme);
      if (preg_match("|^$regexp$|", $url)) {
        return TRUE;
      }
    }
    return FALSE;
  }

  /**
   * Builds and returns the endpoint URL.
   *
   * In most situations this function should not be used. Your are probably
   * looking for \Drupal\media\OEmbed\UrlResolver::getResourceUrl(), because it
   * is alterable and also cached.
   *
   * @param string $url
   *   The canonical media URL.
   *
   * @return string
   *   URL of the oEmbed endpoint.
   *
   * @see \Drupal\media\OEmbed\UrlResolver::getResourceUrl()
   */
  public function buildResourceUrl($url) {
    $query = ['url' => $url];
    return $this->getUrl() . '?' . UrlHelper::buildQuery($query);
  }

}