Security update for Core, with self-updated composer
[yaffs-website] / web / modules / contrib / fontyourface / modules / google_fonts_api / google_fonts_api.module
1 <?php
2
3 /**
4  * @file
5  * Google Fonts module file.
6  */
7
8 /**
9  * Implements hook_fontyourface_api().
10  */
11 function google_fonts_api_fontyourface_api() {
12   return [
13     'version' => '3',
14     'name' => 'Google Fonts',
15   ];
16 }
17
18 /**
19  * Implements hook_page_attachments().
20  */
21 function google_fonts_api_page_attachments(&$page) {
22   $enabled_fonts = &drupal_static('fontyourface_fonts', []);
23   $fonts = [];
24   foreach ($enabled_fonts as $font) {
25     if ($font->pid->value == 'google_fonts_api') {
26       $fonts[] = $font;
27     }
28   }
29   $url = google_fonts_api_generate_font_family_css($fonts);
30   if (!empty($url)) {
31     $page['#attached']['html_head'][] = [
32       [
33         '#type' => 'html_tag',
34         '#tag' => 'link',
35         '#attributes' => [
36           'rel' => 'stylesheet',
37           'href' => $url,
38           'media' => 'all',
39         ],
40       ], 'fontyourface-google-fonts-api',
41     ];
42   }
43 }
44
45 /**
46  * Generates font family css for multiple fonts.
47  *
48  * @param array $fonts
49  *   Array of FontInterface objects.
50  *
51  * @return string
52  *   URL to load fonts on page.
53  */
54 function google_fonts_api_generate_font_family_css(array $fonts) {
55   $url = '';
56   $paths = [];
57   foreach ($fonts as $font) {
58     if ($font->pid->value == 'google_fonts_api') {
59       $metadata = $font->getMetadata();
60       $path_parts = explode(':', $metadata['path']);
61
62       $all_subsets[$metadata['subset']] = $metadata['subset'];
63
64       if (!isset($paths[$path_parts[0]])) {
65         $paths[$path_parts[0]] = [];
66       }
67
68       if (count($path_parts) > 1) {
69         $paths[$path_parts[0]][$path_parts[1]] = $path_parts[1];
70       }
71       else {
72         $paths[$path_parts[0]]['regular'] = 'regular';
73       }
74     }
75   }
76
77   if (count($paths) > 0) {
78
79     $families = [];
80
81     foreach ($paths as $family => $variants) {
82       $families[$family] = urlencode($family) . ':' . implode(',', $variants);
83     }
84
85     $base = 'http://fonts.googleapis.com/css?family=';
86
87     if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
88       $base = 'https://fonts.googleapis.com/css?family=';
89     }
90
91     $url = $base . implode('|', $families) . '&subset=' . implode(',', $all_subsets);
92
93   }
94   return $url;
95 }
96
97 /**
98  * Implements hook_fontyourface_import().
99  */
100 function google_fonts_api_fontyourface_import($font_context = []) {
101   $context = $font_context;
102   if (empty($context['sandbox'])) {
103     $context['sandbox']['fonts'] = _google_fonts_api_get_fonts_from_api();
104     $context['sandbox']['progress'] = 0;
105     $context['sandbox']['max'] = count($context['sandbox']['fonts']);
106   }
107   $font = array_pop($context['sandbox']['fonts']);
108   if (!empty($font)) {
109     if (!isset($font->tags)) {
110       $font->tags = [];
111     }
112     fontyourface_save_font($font);
113     $context['message'] = "Imported {$context['sandbox']['progress']} of {$context['sandbox']['max']}";
114     $context['sandbox']['progress'] = $context['sandbox']['max'] - count($context['sandbox']['fonts']);
115     $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
116   }
117   else {
118     drupal_set_message(t('Imported @count fonts from Google Fonts', ['@count' => $context['sandbox']['progress']]));
119   }
120   return $context;
121 }
122
123 /**
124  * Retrieves fonts from api and parses them for consumption.
125  *
126  * @return array
127  *   List of fonts ready for ingesting as FontInterface objects.
128  */
129 function _google_fonts_api_get_fonts_from_api() {
130   // Return the JSON object with all available fonts
131   // For now, it uses the API key of BarisW (co-maintainer of this module)
132   // This key is limited to 10.000 requests per day, which should be
133   // sufficient as it is only used when selecting fonts in the admin interface.
134   // After that, the fonts are stored in Drupal.
135   try {
136     $uri = 'https://www.googleapis.com/webfonts/v1/webfonts?key=AIzaSyBgeqKlFdYj3Y7VwmrEXnXzpnx5TfKXG4o';
137     $response = \Drupal::httpClient()->get($uri, ['headers' => ['Accept' => 'text/plain'], 'verify' => FALSE]);
138     $data = (string) $response->getBody();
139   }
140   catch (RequestException $e) {
141     drupal_set_message(t('The list of Google Fonts could not be fetched. Verify that your server can connect the Google Servers (https://www.googleapis.com). Error: %error', ['%error' => $response->error]), 'error');
142     return FALSE;
143   }
144
145   $json_results = json_decode($data);
146
147   return _google_fonts_api_convert_api_results($json_results->items);
148 }
149
150 /**
151  * Converts the Google Fonts API JSON results to a generic Fonts object array.
152  *
153  * @param array $json_font_list
154  *   Array of Google Font objects.
155  *
156  * @return array
157  *   Array of objects compatible with Fontyourface interface.
158  */
159 function _google_fonts_api_convert_api_results(array $json_font_list) {
160   $fonts = [];
161   foreach ($json_font_list as $json_font) {
162     foreach ($json_font->variants as $json_font_variant) {
163       foreach ($json_font->subsets as $json_font_subset) {
164
165         $font_id = $json_font->family . ' ' . $json_font_variant . ' (' . $json_font_subset . ')';
166
167         switch ($json_font_variant) {
168           case 'regular':
169             $css_style = 'normal';
170             $css_weight = 'normal';
171             break;
172
173           case 'italic':
174             $css_style = 'italic';
175             $css_weight = 'normal';
176             break;
177
178           case 'bold':
179             $css_style = 'normal';
180             $css_weight = 'bold';
181             break;
182
183           case 'bolditalic':
184             $css_style = 'italic';
185             $css_weight = 'bold';
186             break;
187
188           default:
189             // For all other cases (eg 400 or 400italic).
190             if (is_numeric($json_font_variant)) {
191               // Variant is a number, like 400.
192               $css_style = 'normal';
193               $css_weight = $json_font_variant;
194             }
195             elseif (is_numeric(substr($json_font_variant, 0, 3))) {
196               // Variant is a combined string of number and string, like 400italic.
197               // The numeric part is always three characters long, so we can split it easily.
198               $css_style = substr($json_font_variant, 3);
199               $css_weight = substr($json_font_variant, 0, 3);
200             }
201         }
202
203         $fonts[$font_id] = new stdClass();
204         $fonts[$font_id]->name = $font_id;
205         $fonts[$font_id]->url = 'http://www.google.com/webfonts/family?family=' . $json_font->family . '&subset=' . $json_font_subset . '#' . $json_font_variant;
206         $fonts[$font_id]->provider = 'google_fonts_api';
207         $fonts[$font_id]->css_family = $json_font->family;
208         $fonts[$font_id]->css_style = $css_style;
209         $fonts[$font_id]->css_weight = $css_weight;
210         $fonts[$font_id]->designer = '';
211         $fonts[$font_id]->designer_url = '';
212         $fonts[$font_id]->foundry = '';
213         $fonts[$font_id]->foundry_url = '';
214         $fonts[$font_id]->license = '';
215         $fonts[$font_id]->license_url = '';
216         $fonts[$font_id]->classification = [
217           $json_font->category,
218         ];
219         $fonts[$font_id]->language = [
220           $json_font_subset,
221         ];
222         $fonts[$font_id]->metadata = [
223           'path' => $json_font->family . ':' . $json_font_variant,
224           'subset' => $json_font_subset,
225         ];
226       }
227     }
228   }
229
230   return $fonts;
231 }