| | |
| | | <?php |
| | | namespace JVBase\managers\SEO\render; |
| | | |
| | | use JVBase\base\SchemaHelper; |
| | | use JVBase\inc\managers\SEO\render\Thing\Intangible\ItemList\OfferCatalog; |
| | | use JVBase\Instance; |
| | | use JVBase\managers\Cache; |
| | | use JVBase\managers\SEO\BreadcrumbManager; |
| | | use JVBase\managers\SEO\render\Thing\CreativeWork\Menu; |
| | | use JVBase\managers\SEO\render\Thing\CreativeWork\MenuSection; |
| | | use JVBase\managers\SEO\render\Thing\Intangible\MenuItem; |
| | | use JVBase\managers\SEO\render\Thing\Intangible\Offer; |
| | | use JVBase\managers\SEO\render\Thing\Intangible\Service; |
| | | use JVBase\managers\SEO\render\Thing\Organization\LocalBusiness\LocalBusiness; |
| | | use JVBase\managers\SEO\render\Thing\Thing; |
| | | use JVBase\meta\Meta; |
| | | use JVBase\registrar\config\seo\Resolver; |
| | | use JVBase\registrar\Registrar; |
| | | use WP_Query; |
| | | |
| | | if (!defined('ABSPATH')) { |
| | | exit; |
| | | } |
| | | class SchemaOutput { |
| | | use Instance; |
| | | protected array $types; |
| | | public function __construct() { |
| | | protected function __construct() { |
| | | add_action('wp_head', [$this, 'outputSchema'], 0); |
| | | $this->init(); |
| | | } |
| | |
| | | |
| | | $registrar = false; |
| | | if (is_front_page()) { |
| | | $schema[] = $this->buildWebsiteSchema(true); |
| | | $schema[] = $this->buildWebsiteSchema(); |
| | | $test = $this->buildOrganizationSchema(); |
| | | if (!empty($test)) { |
| | | $schema[] = $test; |
| | | } |
| | | } |
| | | |
| | | if (is_singular($this->types)) { |
| | | $type = get_post_type(); |
| | | $registrar = Registrar::getInstance($type); |
| | | if ($registrar) { |
| | | |
| | | $function = BASE.'build_singular_'.jvbNoBase($type).'_schema'; |
| | | if (function_exists($function)) { |
| | | $schema = $function(get_the_ID()); |
| | | } else if ($registrar) { |
| | | $seo = $registrar->getSEO(); |
| | | $schema[] = $seo->schema()->outputSingularSchema(); |
| | | } |
| | |
| | | $registrar = Registrar::getInstance($type); |
| | | if ($registrar ) { |
| | | $seo = $registrar->getSEO(); |
| | | error_log('SEO: '.print_r($seo->schema(), true)); |
| | | // error_log('SEO: '.print_r($seo->schema(), true)); |
| | | $schema[] = $seo->schema()->outputArchiveSchema(); |
| | | } |
| | | } elseif (is_post_type_archive('product')) { |
| | | $schema[] = $this->buildProductSchema(); |
| | | } |
| | | $isContent = array_values(array_filter(array_map(function($item) { |
| | | return intval(get_option(BASE.$item.'_archive', false)); |
| | | },Registrar::getFeatured('is_content', 'term')))); |
| | | },Registrar::withFeature('is_content', 'term')))); |
| | | |
| | | if (!empty($isContent) && is_page($isContent)){ |
| | | $type = get_post_meta(get_the_id(), BASE.'for_type', true); |
| | |
| | | |
| | | if (!empty($schema)) { |
| | | if (!is_front_page()) { |
| | | $website = JVB()->schemaHelper()::schema('website'); |
| | | $website = SchemaHelper::getInstance()::schema('website'); |
| | | if (!empty($website)) { |
| | | if (JVB_TESTING) { |
| | | Cache::for('websiteSchema')->flush(); |
| | | } |
| | | |
| | | $website = Cache::for('websiteSchema')->remember( |
| | | 'schema', |
| | | function () { |
| | |
| | | |
| | | protected function websiteSchema():array |
| | | { |
| | | $stored = JVB()->schemaHelper()::schema('website'); |
| | | $website = JVB()->schemaHelper()::classFromConfig($stored); |
| | | $stored = SchemaHelper::getInstance()::schema('website'); |
| | | $website = SchemaHelper::getInstance()::classFromConfig($stored); |
| | | |
| | | if (!$website->getUrl() || empty($website->getUrl())){ |
| | | $website->setUrl(get_home_url()); |
| | |
| | | } |
| | | // $encoded = wp_json_encode($schema, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT); |
| | | // $encoded = wp_json_encode($schema, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT, 1024); |
| | | $encoded = wp_json_encode($schema, JSON_UNESCAPED_SLASHES, 512); |
| | | $encoded = wp_json_encode($schema, JSON_UNESCAPED_SLASHES, 2048); |
| | | if ($encoded === false) { |
| | | error_log('wp_json_encode failed: ' . json_last_error_msg()); |
| | | return; |
| | |
| | | if (JVB_TESTING){ |
| | | Cache::for('websiteSchema')->flush(); |
| | | } |
| | | $storedWebsite = JVB()->schemaHelper()::schema('website'); |
| | | $storedWebsite = SchemaHelper::getInstance()::schema('website'); |
| | | |
| | | if (!$full) { |
| | | return Cache::for('websiteSchema')->remember( |
| | |
| | | return in_array($key, $allowed); |
| | | }, ARRAY_FILTER_USE_KEY); |
| | | |
| | | $website = JVB()->schemaHelper()::classFromConfig($storedWebsite); |
| | | $website = SchemaHelper::getInstance()::classFromConfig($storedWebsite); |
| | | if (!$website->getName() || empty($website->getName())) { |
| | | $website->setName(get_bloginfo('name')); |
| | | } |
| | |
| | | return Cache::for('websiteSchema')->remember( |
| | | 'full', |
| | | function () use ($storedWebsite) { |
| | | $website = JVB()->schemaHelper()::classFromConfig($storedWebsite); |
| | | $website = SchemaHelper::getInstance()::classFromConfig($storedWebsite); |
| | | if (!$website->getName() || empty($website->getName())) { |
| | | $website->setName(get_bloginfo('name')); |
| | | } |
| | |
| | | if ($reference) { |
| | | return $this->getOptionSchemaReference('organization'); |
| | | } |
| | | $config = JVB()->schemaHelper()::schema('organization'); |
| | | $config = SchemaHelper::getInstance()::schema('organization'); |
| | | |
| | | return JVB()->schemaHelper()::classFromConfig($config); |
| | | return SchemaHelper::getInstance()::classFromConfig($config); |
| | | } |
| | | |
| | | public function getOptionSchemaReference(string $option):mixed |
| | |
| | | return null; |
| | | } |
| | | |
| | | $stored = JVB()->schemaHelper()::reference($option); |
| | | $stored = SchemaHelper::getInstance()::reference($option); |
| | | |
| | | if (empty($stored)){ |
| | | error_log('Attempted to get schema reference for: '.$option.', but defaults not set.'); |
| | |
| | | |
| | | public function buildOrganizationSchema():array |
| | | { |
| | | $config = JVB()->schemaHelper()::schema('organization'); |
| | | $config = SchemaHelper::getInstance()::schema('organization'); |
| | | |
| | | $class = JVB()->schemaHelper()::classFromConfig($config); |
| | | $class = SchemaHelper::getInstance()::classFromConfig($config); |
| | | return ($class)? $class->outputSchema() : []; |
| | | } |
| | | |
| | | public function buildProductSchema():array |
| | | { |
| | | $sections = jvb_menu_sections(); |
| | | if (empty($sections)) { |
| | | $sections = []; |
| | | } |
| | | |
| | | $menuSections = []; |
| | | |
| | | foreach ($sections as $s) { |
| | | if (empty($s['id'])) { |
| | | continue; |
| | | } |
| | | $items = new WP_Query([ |
| | | 'post_type' => 'product', |
| | | 'order' => 'ASC', |
| | | 'posts_per_page' => -1, |
| | | 'post_status' => 'publish', |
| | | 'tax_query' => [ |
| | | [ |
| | | 'taxonomy' => 'product_cat', |
| | | 'terms' => (int)$s['id'] |
| | | ] |
| | | ], |
| | | 'fields' => 'ids', |
| | | ]); |
| | | if (!$items->have_posts()) { |
| | | continue; |
| | | } |
| | | |
| | | $section = new MenuSection(); |
| | | |
| | | $section->setName($s['name']); |
| | | $section->setId(get_post_type_archive_link('product').'#'.sanitize_title($s['name'])); |
| | | if (!empty($s['description'])) { |
| | | $section->setDescription($s['description']); |
| | | } |
| | | |
| | | $menuItems = []; |
| | | foreach ($items->posts as $ID) { |
| | | $meta = Meta::forPost($ID); |
| | | $fields = $meta->getAll(); |
| | | if (empty($fields['variations'])) { |
| | | $item = $this->buildMenuItem($ID, $fields); |
| | | if ($item) { |
| | | $menuItems[] = $item; |
| | | } |
| | | } else { |
| | | foreach ($fields['variations'] as $variation) { |
| | | $item = $this->buildMenuItem($ID, $variation); |
| | | if ($item) { |
| | | $menuItems[] = $item; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (!empty($menuItems)) { |
| | | $section->setHasMenuItem($menuItems); |
| | | $menuSections[] = $section; |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | | if (!empty($menuSections)) { |
| | | $schema = new Menu(); |
| | | $schema->setName(get_bloginfo('name') . ' | Alberta\'s Best Food Truck Menu'); |
| | | $schema->setId(get_post_type_archive_link('product').'#menu'); |
| | | $schema->setDescription('Southern style barbeque with Northern flair from Meeting Creek, Alberta'); |
| | | $schema->setUrl(get_post_type_archive_link('product')); |
| | | |
| | | $schema->setHasMenuSection($menuSections); |
| | | |
| | | return $schema->outputSchema(); |
| | | } |
| | | |
| | | return []; |
| | | } |
| | | |
| | | protected function buildMenuItem(int $ID, array $fields):MenuItem|false |
| | | { |
| | | $item = new MenuItem(); |
| | | $item->setUrl(get_the_permalink($ID)); |
| | | $base = get_post_type_archive_link('product').'#'.$ID.'-'.sanitize_title($fields['post_title']); |
| | | $item->setId($base); |
| | | $doit = false; |
| | | if (!empty($fields['post_thumbnail']??'')) { |
| | | $doit = true; |
| | | $item->setImage(Thing::createImageFromID($fields['post_thumbnail'])); |
| | | } |
| | | |
| | | if (!empty($fields['post_excerpt']??'')) { |
| | | $doit = true; |
| | | $item->setDescription(wp_strip_all_tags($fields['post_excerpt'])); |
| | | } |
| | | |
| | | if (!empty($fields['price']??'')) { |
| | | $doit = true; |
| | | $offer = new Offer(); |
| | | $offer->setId($base.'-price'); |
| | | $offer->setPrice($fields['price']); |
| | | $offer->setPriceCurrency('CAD'); |
| | | $item->setOffers($offer); |
| | | } |
| | | return $doit ? $item : false; |
| | | } |
| | | } |
| | | |