/** * Renderer for the Metabox. */ public static function render_meta_box() { $ajax_nonce = wp_create_nonce("instant-articles-force-submit"); $post_id = intval($_POST['post_ID']); $post = get_post($post_id); $adapter = new Instant_Articles_Post($post); $article = $adapter->to_instant_article(); $canonical_url = $adapter->get_canonical_url(); $submission_status = null; $published = 'publish' === $post->post_status; $dev_mode = false; $force_submit = get_post_meta($post_id, Instant_Articles_Publisher::FORCE_SUBMIT_KEY, true); $should_submit_post = apply_filters('instant_articles_should_submit_post', true, $adapter); Instant_Articles_Wizard::menu_items(); $settings_page_href = Instant_Articles_Wizard::get_url(); $publishing_settings = Instant_Articles_Option_Publishing::get_option_decoded(); $publish_with_warnings = $publishing_settings['publish_with_warnings']; if ($published) { try { $fb_app_settings = Instant_Articles_Option_FB_App::get_option_decoded(); $fb_page_settings = Instant_Articles_Option_FB_Page::get_option_decoded(); $publishing_settings = Instant_Articles_Option_Publishing::get_option_decoded(); $dev_mode = isset($publishing_settings['dev_mode']) ? $publishing_settings['dev_mode'] ? true : false : false; if (isset($fb_app_settings['app_id']) && isset($fb_app_settings['app_secret']) && isset($fb_page_settings['page_access_token']) && isset($fb_page_settings['page_id'])) { // Instantiate a new Client to get the status of this article. $client = Client::create($fb_app_settings['app_id'], $fb_app_settings['app_secret'], $fb_page_settings['page_access_token'], $fb_page_settings['page_id'], $dev_mode); $submission_status_id = get_post_meta($post_id, Instant_Articles_Publisher::SUBMISSION_ID_KEY, true); if (!empty($submission_status_id)) { $submission_status = $client->getSubmissionStatus($submission_status_id); } else { // Grab the latest status of this article and display. $article_id = $client->getArticleIDFromCanonicalURL($canonical_url); $submission_status = $client->getLastSubmissionStatus($article_id); } } } catch (FacebookResponseException $e) { $submission_status = null; } } include dirname(__FILE__) . '/meta-box-template.php'; die; }
/** * Automatically add meta tag for Instant Articles URL claiming * when page is set. * * @since 0.4 */ function inject_url_claiming_meta_tag() { $publishing_settings = Instant_Articles_Option_Publishing::get_option_decoded(); $fb_page_settings = Instant_Articles_Option_FB_Page::get_option_decoded(); if (isset($fb_page_settings['page_id'])) { ?> <meta property="fb:pages" content="<?php echo esc_attr($fb_page_settings['page_id']); ?> " /> <?php } }
/** * Render post * * @since 0.1 * @return InstantArticle */ public function to_instant_article() { /** * Fires before the instant article is rendered. * * @since 0.1 * @param Instant_Article_Post $instant_article_post The instant article post. */ do_action('instant_articles_before_transform_post', $this); // Get time zone configured in WordPress. Default to UTC if no time zone configured. $date_time_zone = get_option('timezone_string') ? new DateTimeZone(get_option('timezone_string')) : new DateTimeZone('UTC'); // Initialize transformer $file_path = plugin_dir_path(__FILE__) . 'rules-configuration.json'; $configuration = file_get_contents($file_path); $transformer = new Transformer(); $this->transformer = $transformer; $transformer->loadRules($configuration); $transformer = apply_filters('instant_articles_transformer_rules_loaded', $transformer); $settings_publishing = Instant_Articles_Option_Publishing::get_option_decoded(); if (isset($settings_publishing['custom_rules_enabled']) && !empty($settings_publishing['custom_rules_enabled']) && isset($settings_publishing['custom_rules']) && !empty($settings_publishing['custom_rules'])) { $transformer->loadRules($settings_publishing['custom_rules']); } $transformer = apply_filters('instant_articles_transformer_custom_rules_loaded', $transformer); $blog_charset = get_option('blog_charset'); $header = Header::create()->withPublishTime(Time::create(Time::PUBLISHED)->withDatetime(new DateTime($this->_post->post_date, $date_time_zone)))->withModifyTime(Time::create(Time::MODIFIED)->withDatetime(new DateTime($this->_post->post_modified, $date_time_zone))); $title = $this->get_the_title(); if ($title) { $document = new DOMDocument(); libxml_use_internal_errors(true); $document->loadHTML('<?xml encoding="' . $blog_charset . '" ?><h1>' . $title . '</h1>'); libxml_use_internal_errors(false); $transformer->transform($header, $document); } if ($this->has_subtitle()) { $header->withSubTitle($this->get_the_subtitle()); } $authors = $this->get_the_authors(); foreach ($authors as $author) { $author_obj = Author::create(); if ($author->display_name) { $author_obj->withName($author->display_name); } if ($author->bio) { $author_obj->withDescription($author->bio); } if ($author->user_url) { $author_obj->withURL($author->user_url); } $header->addAuthor($author_obj); } $kicker = $this->get_the_kicker(); if ($kicker) { $header->withKicker($kicker); } $cover = $this->get_cover_media(); if ($cover->getUrl()) { $header->withCover($cover); } $this->instant_article = InstantArticle::create()->withCanonicalUrl($this->get_canonical_url())->withHeader($header)->addMetaProperty('op:generator:application', 'facebook-instant-articles-wp')->addMetaProperty('op:generator:application:version', IA_PLUGIN_VERSION); $settings_style = Instant_Articles_Option_Styles::get_option_decoded(); if (isset($settings_style['article_style']) && !empty($settings_style['article_style'])) { $this->instant_article->withStyle($settings_style['article_style']); } else { $this->instant_article->withStyle('default'); } $libxml_previous_state = libxml_use_internal_errors(true); $document = new DOMDocument('1.0', get_option('blog_charset')); $content = $this->get_the_content(); // DOMDocument isn’t handling encodings too well, so let’s help it a little. if (function_exists('mb_convert_encoding')) { $content = mb_convert_encoding($content, 'HTML-ENTITIES', get_option('blog_charset')); } else { $content = htmlspecialchars_decode(utf8_decode(htmlentities($content, ENT_COMPAT, 'utf-8', false))); } $result = $document->loadHTML('<!doctype html><html><body>' . $content . '</body></html>'); // We need to make sure that scripts use absolute URLs and not relative URLs. $scripts = $document->getElementsByTagName('script'); if (!empty($scripts)) { foreach ($scripts as $script) { $src = $script->getAttribute('src'); $explode_src = parse_url($src); if (is_array($explode_src) && empty($explode_src['scheme']) && !empty($explode_src['host']) && !empty($explode_src['path'])) { $src = 'https://' . $explode_src['host'] . $explode_src['path']; } $script->setAttribute('src', $src); } } libxml_clear_errors(); libxml_use_internal_errors($libxml_previous_state); $document = apply_filters('instant_articles_parsed_document', $document); if ($result) { $transformer->transform($this->instant_article, $document); } $this->add_ads_from_settings(); $this->add_analytics_from_settings(); $this->instant_article = apply_filters('instant_articles_transformed_element', $this->instant_article); /** * Fires after the instant article is rendered. * * @since 0.1 * @param Instant_Article_Post $instant_article_post The instant article post. */ do_action('instant_articles_after_transform_post', $this); return $this->instant_article; }
/** * Submits article to Instant Articles. * * @param string $post_id The identifier of post. * @param Post $post The WP Post. */ public static function submit_article($post_id, $post) { // Don't process if this is just a revision or an autosave. if (wp_is_post_revision($post) || wp_is_post_autosave($post)) { return; } // Don't process if this post is not published if ('publish' !== $post->post_status) { return; } // Only process posts $post_types = apply_filters('instant_articles_post_types', array('post')); if (!in_array($post->post_type, $post_types)) { return; } // Transform the post to an Instant Article. $adapter = new Instant_Articles_Post($post); $article = $adapter->to_instant_article(); // Skip empty articles or articles missing title. // This is important because the save_post action is also triggered by bulk updates, but in this case // WordPress does not load the content field from DB for performance reasons. In this case, articles // will be empty here, despite of them actually having content. if (count($article->getChildren()) === 0 || !$article->getHeader() || !$article->getHeader()->getTitle()) { return; } // Instantiate an API client. try { $fb_app_settings = Instant_Articles_Option_FB_App::get_option_decoded(); $fb_page_settings = Instant_Articles_Option_FB_Page::get_option_decoded(); $publishing_settings = Instant_Articles_Option_Publishing::get_option_decoded(); $dev_mode = isset($publishing_settings['dev_mode']) ? $publishing_settings['dev_mode'] ? true : false : false; if (isset($fb_app_settings['app_id']) && isset($fb_app_settings['app_secret']) && isset($fb_page_settings['page_access_token']) && isset($fb_page_settings['page_id'])) { $client = Client::create($fb_app_settings['app_id'], $fb_app_settings['app_secret'], $fb_page_settings['page_access_token'], $fb_page_settings['page_id'], $dev_mode); // Don't publish posts with password protection if (post_password_required($post)) { // Unpublishes if already published and from now on it started to have password protection $client->removeArticle($article->getCanonicalURL()); delete_post_meta($post_id, self::SUBMISSION_ID_KEY); return; } // Don't process if contains warnings and blocker flag for transformation warnings is turned on. if (count($adapter->transformer->getWarnings()) > 0 && isset($publishing_settings['block_publish_with_warnings']) && $publishing_settings['block_publish_with_warnings']) { // Unpublishes if already published $client->removeArticle($article->getCanonicalURL()); delete_post_meta($post_id, self::SUBMISSION_ID_KEY); return; } if ($dev_mode) { $published = false; } else { // Any publish status other than 'publish' means draft for the Instant Article. $published = true; } try { // Import the article. $submission_id = $client->importArticle($article, $published); update_post_meta($post_id, self::SUBMISSION_ID_KEY, $submission_id); } catch (Exception $e) { // Try without taking live for pages not yet reviewed. $submission_id = $client->importArticle($article, false); update_post_meta($post_id, self::SUBMISSION_ID_KEY, $submission_id); } } } catch (Exception $e) { Logger::getLogger('instantarticles-wp-plugin')->error('Unable to submit article.', $e->getTraceAsString()); } }
/** * Render post * * @since 0.1 * @return InstantArticle */ public function to_instant_article() { /** * Fires before the instant article is rendered. * * @since 0.1 * @param Instant_Article_Post $instant_article_post The instant article post. */ do_action('instant_articles_before_transform_post', $this); // Get time zone configured in WordPress. Default to UTC if no time zone configured. $date_time_zone = get_option('timezone_string') ? new DateTimeZone(get_option('timezone_string')) : new DateTimeZone('UTC'); // Initialize transformer $file_path = plugin_dir_path(__FILE__) . 'rules-configuration.json'; $configuration = file_get_contents($file_path); $transformer = new Transformer(); $this->transformer = $transformer; $transformer->loadRules($configuration); $transformer = apply_filters('instant_articles_transformer_rules_loaded', $transformer); $settings_publishing = Instant_Articles_Option_Publishing::get_option_decoded(); if (isset($settings_publishing['custom_rules_enabled']) && !empty($settings_publishing['custom_rules_enabled']) && isset($settings_publishing['custom_rules']) && !empty($settings_publishing['custom_rules'])) { $transformer->loadRules($settings_publishing['custom_rules']); } $transformer = apply_filters('instant_articles_transformer_custom_rules_loaded', $transformer); $blog_charset = get_option('blog_charset'); $header = Header::create()->withPublishTime(Time::create(Time::PUBLISHED)->withDatetime(new DateTime($this->_post->post_date, $date_time_zone)))->withModifyTime(Time::create(Time::MODIFIED)->withDatetime(new DateTime($this->_post->post_modified, $date_time_zone))); $title = $this->get_the_title(); if ($title) { $document = new DOMDocument(); libxml_use_internal_errors(true); $document->loadHTML('<?xml encoding="' . $blog_charset . '" ?><h1>' . $title . '</h1>'); libxml_use_internal_errors(false); $transformer->transform($header, $document); } if ($this->has_subtitle()) { $header->withSubTitle($this->get_the_subtitle()); } $authors = $this->get_the_authors(); foreach ($authors as $author) { $author_obj = Author::create(); if ($author->display_name) { $author_obj->withName($author->display_name); } if ($author->bio) { $author_obj->withDescription($author->bio); } if ($author->user_url) { $author_obj->withURL($author->user_url); } $header->addAuthor($author_obj); } $kicker = $this->get_the_kicker(); if ($kicker) { $header->withKicker($kicker); } $cover = $this->get_cover_media(); if ($cover->getUrl()) { $header->withCover($cover); } $this->instant_article = InstantArticle::create()->withCanonicalUrl($this->get_canonical_url())->withHeader($header)->addMetaProperty('op:generator:application', 'facebook-instant-articles-wp')->addMetaProperty('op:generator:application:version', IA_PLUGIN_VERSION); $settings_style = Instant_Articles_Option_Styles::get_option_decoded(); if (isset($settings_style['article_style']) && !empty($settings_style['article_style'])) { $this->instant_article->withStyle($settings_style['article_style']); } else { $this->instant_article->withStyle('default'); } $transformer->transformString($this->instant_article, $this->get_the_content(), get_option('blog_charset')); $this->add_ads_from_settings(); $this->add_analytics_from_settings(); $this->instant_article = apply_filters('instant_articles_transformed_element', $this->instant_article); /** * Fires after the instant article is rendered. * * @since 0.1 * @param Instant_Article_Post $instant_article_post The instant article post. */ do_action('instant_articles_after_transform_post', $this); return $this->instant_article; }