text('og_title', _t('@seo', 'Title')); $form->textarea('og_description', _t('@seo', 'Description')); //$form->text('og_video_url', _t('@seo', 'Video URL')); if (! $static) { $form->select('og_image', _t('@seo', 'Images'), false, $this->imageOptions()); foreach ( [ 'og_image_uploaded' => ['title' => _t('@seo', 'Uploaded Images'), 'visible-if' => 'uploaded'], 'og_image_default' => ['title' => _t('@seo', 'Default Images'), 'hidden-if' => 'uploaded'], ] as $fieldName => $fieldSettings ) { $form->images($fieldName, $fieldSettings['title'], 5, 10 /* 10Mb */, [], [ 'folderByID' => $opts['images_folderbyid'] ?? false, ]) ->tip(_t('@seo', 'Minimum size: 200px x 200px, ideal ratio 1.91:1, 8MB max. (eg. 1640px x 856px or 3280px x 1712px for retina screens)')) ->setFolder(rtrim($opts['images_dir'] ?? bff::publicPath('files/images/settings'), '\/') . DS); if (isset($fieldSettings['visible-if'])) { $form->visibleIf('og_image', $fieldSettings['visible-if']); } if (isset($fieldSettings['hidden-if'])) { $form->hiddenIf('og_image', $fieldSettings['hidden-if']); } } } $form->select('og_type', _t('@seo', 'Type'), false, $this->typeOptions()); } /** * General settings form * @param Form $form */ public function settings($form) { $form->staticText('', $this->providerTitle()); $form->text('og_sitename', _t('@seo', 'Site Name'), [], false); $form->text('fb_app_id', _t('@seo', 'Facebook App ID'), [], false); } /** * Get social page meta * @param Template $template seo template * @param array $page page data * @param string $lang language * @param bool|array $landing active landing page or false * @param array $opts [social_images_key, general_social_template_key] * @return array */ public function getMeta(Template $template, array $page, string $lang, $landing, array $opts = []): array { if ($this->meta) { return $this->meta; } $seo = SEO::i(); $general = !empty($page[$opts['general_social_template_key'] ?? 'msocialtemplate']); $data = $template->data[self::SOCIAL_KEY]; $datatext = $template->data[self::SOCIALTEXT_KEY]; # og:locale $locale = Lang::getLanguageSettings($lang, 'locale'); if (! empty($locale)) { $this->setMeta('og:locale', $locale); } # url if ($template->canonical) { $canonicalUrl = $template->canonical->getMeta($lang, $landing)['link-canonical']['href'] ?? ''; if (! empty($canonicalUrl)) { $this->setMeta('og:url', $canonicalUrl); } } # type $type = $page[self::SOCIAL_KEY]['og_type'] ?? $data['og_type'] ?? ''; if (array_key_exists($type, $this->typeOptions())) { $this->setMeta('og:type', strval($type)); } # title, description, video $placeholders = $template->params; foreach ( [ 'og_title' => 'og:title', 'og_description' => 'og:description', 'og_video_url' => 'og:video', ] as $key => $property ) { $content = $page[self::SOCIALTEXT_KEY][$key] ?? ''; if ($general) { $content = str_replace( ($content !== '' ? ['{meta-base}', ' {meta-base}'] : [' {meta-base}', '{meta-base} ', '{meta-base}']), $content, $datatext[$key][$lang] ?? '' ); } if (! empty($content)) { $content = $seo->metaTextPrepare($content, $placeholders); if (! empty($content)) { $this->setMeta($property, $content); } } } # image $images = []; $imagesSource = $page[self::SOCIAL_KEY]['og_image'] ?? $data['og_image'] ?? 'content'; if ($imagesSource === 'uploaded') { $uploadedImages = $page[self::SOCIAL_KEY]['og_image_uploaded'] ?? $data['og_image_uploaded'] ?? []; if (! empty($uploadedImages) && is_array($uploadedImages)) { foreach ($uploadedImages as $image) { $images[] = [ 'width' => $image['width'] ?? 0, 'height' => $image['height'] ?? 0, 'url' => Url::dynamic($image['url']['o'], [], ['lang' => Lang::getDefaultLanguage()]), ]; } } } else { # 'content' or empty $contentImages = $page[$opts['social_images_key'] ?? 'images'] ?? []; if (empty($contentImages)) { # no content images => use default images $defaultImages = $data['og_image_default'] ?? []; if (! empty($defaultImages) && is_array($defaultImages)) { $contentImages = []; foreach ($defaultImages as $image) { $contentImages[] = [ 'width' => $image['width'] ?? 0, 'height' => $image['height'] ?? 0, 'url' => Url::dynamic($image['url']['o'], [], ['lang' => Lang::getDefaultLanguage()]), ]; } } } if (! empty($contentImages)) { if (is_string($contentImages)) { $contentImages = [['social_url' => $contentImages]]; } if (is_array($contentImages)) { foreach ($contentImages as $image) { if (isset($image['social_url']) || isset($image['url'])) { $images[] = [ 'width' => $image['width'] ?? 0, 'height' => $image['height'] ?? 0, 'url' => Url::dynamic($image['social_url'] ?? $image['url']), ]; } } } } } $i = 0; foreach ($images as $image) { if (! empty($image['url'])) { $this->setMeta('og:image', $image['url'], 'og:image:' . $i); if (! empty($image['width'])) { $this->setMeta('og:image:width', $image['width'], 'og:image:width:' . $i); } if (! empty($image['height'])) { $this->setMeta('og:image:height', $image['height'], 'og:image:height:' . $i); } if (! $i) { $this->setMeta('twitter:image', $image['url'], 'twitter:image:' . $i, 'name'); } $i++; } } # general: # og:site_name: $settings = config::get('seo.social', [], TYPE_ARRAY); if (! empty($settings['og_sitename'])) { $content = $seo->metaTextPrepare($settings['og_sitename'], $placeholders); if (! empty($content)) { $this->setMeta('og:site_name', $content); } } # fb:app_id if (! empty($settings['fb_app_id'])) { $this->setMeta('fb:app_id', $settings['fb_app_id']); } return $this->meta; } /** * Set open graph meta data * @param string $property * @param string|array $content * @param string|null $key * @param string $propertyKey */ protected function setMeta(string $property, $content, $key = null, $propertyKey = 'property') { $tag = [ $propertyKey => $property, 'content' => $content, ]; $this->meta[$key ?? $property] = array_merge($tag, [ 'tag' => 'meta', 'html' => '', ]); } /** * Image options * @return array */ public function imageOptions(): array { return [ [ 'id' => 'content', 'title' => _t('@seo', 'Content Images'), ], [ 'id' => 'uploaded', 'title' => _t('@seo', 'Uploaded Images'), ], ]; } /** * Type options * @see https://ogp.me/#no_vertical * @return array */ public function typeOptions() { $list = [ 'article' => [ 'title' => _t('@seo', 'Article'), ], 'book' => [ 'title' => _t('@seo', 'Book'), ], 'profile' => [ 'title' => _t('@seo', 'Profile'), ], 'website' => [ 'title' => _t('@seo', 'Website'), ], 'music.song' => [ 'title' => _t('@seo', 'Music: Song'), ], 'music.album' => [ 'title' => _t('@seo', 'Music: Album'), ], 'music.playlist' => [ 'title' => _t('@seo', 'Music: Playlist'), ], 'music.radio_station' => [ 'title' => _t('@seo', 'Music: Radio Station'), ], 'video.movie' => [ 'title' => _t('@seo', 'Video: Movie'), ], 'video.episode' => [ 'title' => _t('@seo', 'Video: Episode'), ], 'video.tv_show' => [ 'title' => _t('@seo', 'Video: TV Show'), ], 'video.other' => [ 'title' => _t('@seo', 'Video: Other'), ], ]; foreach ($list as $key => &$value) { $value['id'] = $key; } return $list; } }