5 * Font Squirrel API module file.
8 use Drupal\Core\Entity\EntityInterface;
9 use Drupal\fontyourface\Entity\Font;
12 * Implements hook_fontyourface_api().
14 function fontsquirrel_api_fontyourface_api() {
17 'name' => 'Font Squirrel',
22 * Implements hook_entity_presave().
24 function fontsquirrel_api_entity_presave(EntityInterface $entity) {
25 if ($entity instanceof Font) {
26 if ($entity->pid->value == 'fontsquirrel_api' && $entity->isEnabled()) {
27 $metadata = $entity->getMetadata();
28 $directory_location = _fontsquirrel_api_get_font_directory_location($entity);
29 file_prepare_directory($directory_location, FILE_CREATE_DIRECTORY);
30 $zip_location = file_build_uri('fontyourface/fontsquirrel/' . $metadata['path'] . '-fontfacekit.zip');
31 // Throw an exception; make it hard if this fails.
32 $uri = 'http://www.fontsquirrel.com/fontfacekit/' . $metadata['path'];
33 $response = \Drupal::httpClient()->get($uri, ['headers' => ['Accept' => 'text/plain']]);
34 if (!file_exists(drupal_realpath($zip_location))) {
35 file_unmanaged_save_data($response->getBody(), $zip_location);
38 $font_pathinfo = pathinfo($metadata['font_filename']);
39 if ($zip = zip_open(drupal_realpath($zip_location))) {
40 while ($entry = zip_read($zip)) {
41 $entry_name = zip_entry_name($entry);
42 $path_info = pathinfo($entry_name);
43 if (strpos($path_info['filename'], $font_pathinfo['filename'] . '-webfont') !== FALSE &&
44 in_array($path_info['extension'], ['eot', 'ttf', 'woff', 'svg'])) {
45 $files[$path_info['extension']] = $path_info['filename'] . '.' . $path_info['extension'];
46 $data = zip_entry_read($entry, zip_entry_filesize($entry));
47 file_unmanaged_save_data($data, $directory_location . '/' . $path_info['filename'] . '.' . $path_info['extension'], FILE_EXISTS_REPLACE);
49 zip_entry_close($entry);
54 $css_file = _fontsquirrel_api_generate_fontfamily_css_stylesheet($entity->css_family->value, $files);
55 file_unmanaged_save_data($css_file, $directory_location . '/fontyourface-stylesheet.css', FILE_EXISTS_REPLACE);
62 * Implements hook_page_attachments().
64 function fontsquirrel_api_page_attachments(&$page) {
65 $enabled_fonts = &drupal_static('fontyourface_fonts', []);
66 foreach ($enabled_fonts as $font) {
67 if ($font->pid->value == 'fontsquirrel_api' && $font->isEnabled()) {
68 $directory_location = _fontsquirrel_api_get_font_directory_location($font);
69 $page['#attached']['html_head'][] = [
71 '#type' => 'html_tag',
74 'rel' => 'stylesheet',
75 'href' => file_create_url($directory_location . '/fontyourface-stylesheet.css'),
78 ], 'fontsquirrel-api-' . $font->id(),
85 * Prepares variables for Font templates.
87 * Default template: font.html.twig.
89 * @param array $variables
90 * An associative array containing:
91 * - elements: An associative array containing the user information and any
92 * - attributes: HTML attributes for the containing element.
94 function fontsquirrel_api_preprocess_font(array &$variables) {
95 $font = $variables['elements']['#font'];
96 $metadata = $font->getMetadata();
97 if ($font->pid->value == 'fontsquirrel_api' && $font->isDisabled()) {
98 $variables['font_preview']['#markup'] = '<img style=\'max-width:100%;\' src="' . $metadata['preview_image'] . '" />';
103 * Prepares variables for full font template preview.
105 * Default template: font--full.html.twig.
107 * @param array $variables
108 * An associative array containing:
109 * - elements: An associative array containing the user information and any
110 * - attributes: HTML attributes for the containing element.
112 function fontsquirrel_api_preprocess_font__full(array &$variables) {
113 fontsquirrel_api_preprocess_font($variables);
117 * Prepares variables for font teaser preview.
119 * Default template: font--teaser.html.twig.
121 * @param array $variables
122 * An associative array containing:
123 * - elements: An associative array containing the user information and any
124 * - attributes: HTML attributes for the containing element.
126 function fontsquirrel_api_preprocess_font__teaser(array &$variables) {
127 $font = $variables['elements']['#font'];
128 $metadata = $font->getMetadata();
129 if ($font->pid->value == 'fontsquirrel_api' && $font->isDisabled()) {
130 $variables['font_preview']['#markup'] = '<img width="160px" src="https://www.fontsquirrel.com/widgets/test_drive/' . $metadata['checksum'] . '?s=144&t=AaGg" />';
135 * Implements hook_fontyourface_import().
137 function fontsquirrel_api_fontyourface_import($font_context = []) {
138 // Individual font could take a lot of time.
139 @set_time_limit(3600);
140 $context = $font_context;
142 if (empty($context['sandbox'])) {
143 $context['sandbox']['fonts'] = _fontsquirrel_api_get_fonts_from_api();
144 $context['sandbox']['progress'] = 0;
145 $context['sandbox']['max'] = count($context['sandbox']['fonts']);
148 $font_import = array_pop($context['sandbox']['fonts']);
149 if (!empty($font_import)) {
151 'id' => $font_import->id,
152 'path' => $font_import->family_urlname,
153 'font_filename' => $font_import->font_filename,
155 $font = new stdClass();
156 $font->name = $font_import->family_name;
157 $font->url = 'https://www.fontsquirrel.com/fonts/' . $font_import->family_urlname;
158 $font->provider = 'fontsquirrel_api';
159 $font->css_family = $font_import->family_urlname . 'regular';
160 // Font Squirrel fonts have no concept of normal/bold/light/italics fonts.
161 $font->css_weight = 400;
162 $font->css_style = 'normal';
163 $font->foundry = $font_import->foundry_name;
164 $font->foundry_url = 'https://www.fontsquirrel.com/foundry/' . $font_import->foundry_urlname;
165 $font->license = 'See Font Squirrel license page';
166 $font->license_url = $font->url . '#eula';
167 $font->classification = [
168 str_replace(' ', '-', strtolower($font_import->classification)),
173 $font->metadata = $metadata;
174 $variants = fontsquirrel_api_get_font_family_info($font_import);
175 foreach ($variants as $variant) {
176 $variant_metadata = $metadata;
177 $variant_metadata['font_filename'] = $variant->filename;
178 $variant_metadata['checksum'] = $variant->checksum;
179 $variant_metadata['preview_image'] = str_replace('\\', '', $variant->sample_image);
180 $variant_font = clone $font;
181 $variant_font->name = $variant->family_name . ' ' . $variant->style_name;
182 $variant_font->url = $font->url . '#' . $variant->fontface_name;
183 $variant_font->css_family = $variant->fontface_name;
184 $variant_font->metadata = $variant_metadata;
185 fontyourface_save_font($variant_font);
187 $context['message'] = "Imported {$context['sandbox']['progress']} (plus variants) of {$context['sandbox']['max']}";
188 $context['sandbox']['progress'] = $context['sandbox']['max'] - count($context['sandbox']['fonts']);
189 $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
192 drupal_set_message(t('Imported @count Font Squirrel fonts (and variants).', ['@count' => $context['sandbox']['max']]));
198 * Retrieves fonts from api and parses them for consumption.
201 * List of fonts ready for ingesting as FontInterface objects.
203 function _fontsquirrel_api_get_fonts_from_api() {
205 $uri = 'https://www.fontsquirrel.com/api/fontlist/all';
206 $response = \Drupal::httpClient()->get($uri, ['headers' => ['Accept' => 'text/plain']]);
207 $data = json_decode($response->getBody());
209 catch (RequestException $e) {
210 drupal_set_message(t('There was an error downloading font list from Font Squirrel.'), 'error');
211 fontyourface_log('Invalid drupal_http_request response: @response', ['@response' => $e->getMessage()]);
218 * Get font family information from Font Squirrel.
220 * @param object $font_import
221 * Initial font package data from Font Squirrel.
224 * Font family information from Font Squirrel.
226 function fontsquirrel_api_get_font_family_info($font_import) {
228 $uri = 'http://www.fontsquirrel.com/api/familyinfo/' . $font_import->family_urlname;
229 $response = \Drupal::httpClient()->get($uri, ['headers' => ['Accept' => 'text/plain']]);
230 $data = json_decode($response->getBody());
232 catch (RequestException $e) {
233 drupal_set_message(t('There was an error downloading font list from Font Squirrel.'), 'error');
234 fontyourface_log('Invalid drupal_http_request response: @response', ['@response' => $e->getMessage()]);
241 * Returns directory location of font package from Font Squirrel.
243 * @param Drupal\fontyourface\Entity\Font $font
244 * Font entity with downloaded package.
247 * File stream location to font package.
249 function _fontsquirrel_api_get_font_directory_location(Font $font) {
250 return file_build_uri('fontyourface/fontsquirrel/' . _fontsquirrel_api_get_sanitized_css_family($font->css_family->value) . '-fontfacekit');
254 * Returns sanitized css family text.
256 * @param string $css_family
257 * Unsanitized version of css family string.
260 * Sanitized css family string.
262 function _fontsquirrel_api_get_sanitized_css_family($css_family) {
263 return preg_replace("/[^A-Za-z0-9\-]/", '', $css_family);
267 * Generates CSS to load font.
269 * @param string $css_family
270 * Font entity with downloaded package.
271 * @param array $files
272 * Font files keyed by file type.
275 * CSS Definition for @font-face.
277 function _fontsquirrel_api_generate_fontfamily_css_stylesheet($css_family, array $files) {
278 $data = "@font-face {\n";
279 $data .= "font-family: '{$css_family}';\n";
283 $data .= "src: url('{$files['eot']}');\n";
284 $lines[] = "url('{$files['eot']}?#iefix') format('embedded-opentype')";
287 $lines[] = "url('{$files['ttf']}') format('truetype')";
289 if ($files['woff']) {
290 $lines[] = "url('{$files['woff']}') format('woff')";
293 $lines[] = "url('{$files['svg']}#{$css_family}') format('svg')";
296 $data .= 'src: ' . implode(', ', $lines) . ";\n";
297 $data .= "font-weight: normal;\n";
298 $data .= "font-style: normal;\n";
299 return $data . "}\n";