Instant Articles for WP - Version 3.0

Version Description

  • Fix versioning - use WP style
  • Ignore hyperlinks with a #
  • Allow filtering of post types used in the feed
  • Use v2.6 of the Facebook API
  • Coding standards & whitespace fixes
  • Load Facebook SDK over HTTPS
  • Avoid crawling of 404s
  • Replace social embeds with interactives
  • Use submission ID to check status in the admin
  • Fix over-zealous escaping

props markbarnes, paulschreiber, diegoquinteiro, gemedet

Download this release

Release Info

Developer philipjohn
Plugin Icon 128x128 Instant Articles for WP
Version 3.0
Comparing to
See all releases

Code changes from version 2.11 to 3.0

Files changed (95) hide show
  1. class-instant-articles-post.php +59 -31
  2. class-instant-articles-publisher.php +16 -3
  3. compat/class-instant-articles-google-analytics-for-wordpress.php +1 -1
  4. compat/class-instant-articles-jetpack.php +4 -5
  5. facebook-instant-articles.php +17 -11
  6. meta-box/class-instant-articles-meta-box.php +28 -20
  7. meta-box/meta-box-template.php +5 -5
  8. readme.txt +17 -2
  9. rules-configuration.json +45 -12
  10. settings/class-instant-articles-option-ads.php +6 -10
  11. settings/class-instant-articles-option-analytics.php +1 -0
  12. settings/class-instant-articles-option-publishing.php +3 -3
  13. settings/class-instant-articles-option.php +11 -11
  14. settings/class-instant-articles-settings-fb-page.php +5 -5
  15. settings/class-instant-articles-settings-wizard.php +1 -1
  16. settings/template-settings-advanced.php +1 -1
  17. settings/template-settings-info.php +7 -7
  18. settings/template-settings-wizard.php +13 -13
  19. shortcodes.php +0 -254
  20. vendor/autoload.php +1 -1
  21. vendor/composer/autoload_files.php +10 -0
  22. vendor/composer/autoload_real.php +39 -14
  23. vendor/composer/autoload_static.php +131 -0
  24. vendor/composer/installed.json +23 -21
  25. vendor/facebook/facebook-instant-articles-sdk-php/CONTRIBUTING.md +1 -1
  26. vendor/facebook/facebook-instant-articles-sdk-php/README.md +13 -1
  27. vendor/facebook/facebook-instant-articles-sdk-php/composer.lock +52 -49
  28. vendor/facebook/facebook-instant-articles-sdk-php/docs/QuickStart.md +3 -685
  29. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Client/Client.php +77 -11
  30. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Ad.php +1 -31
  31. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Analytics.php +1 -31
  32. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Caption.php +42 -3
  33. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Cite.php +34 -0
  34. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Element.php +33 -14
  35. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/ElementWithHTML.php +65 -0
  36. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Header.php +48 -4
  37. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/InstantArticle.php +3 -2
  38. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/InstantArticleInterface.php +14 -0
  39. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Interactive.php +41 -37
  40. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/ListElement.php +3 -2
  41. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/SocialEmbed.php +4 -241
  42. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Sponsor.php +96 -0
  43. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Parser/Parser.php +43 -0
  44. vendor/facebook/facebook-instant-articles-sdk-php/{tests/Facebook/InstantArticles/Transformer/instant-article-example-rules.json → src/Facebook/InstantArticles/Parser/instant-articles-rules.json} +16 -15
  45. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/ConfigurationSelectorRule.php +6 -3
  46. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/ImageInsideParagraphRule.php +98 -0
  47. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/InteractiveRule.php +9 -2
  48. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/SocialEmbedRule.php +13 -0
  49. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/SponsorRule.php +52 -0
  50. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Transformer.php +15 -7
  51. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Warnings/DeprecatedRuleWarning.php +73 -0
  52. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Warnings/NoRootInstantArticleFoundWarning.php +70 -0
  53. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Warnings/ValidatorWarning.php +2 -2
  54. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Warnings/validator_warning_messages.ini +1 -1
  55. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Validators/InstantArticleValidator.php +2 -1
  56. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Client/ClientTest.php +348 -14
  57. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/AdTest.php +4 -6
  58. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/AnalyticsTest.php +4 -10
  59. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/CaptionTest.php +19 -2
  60. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/CiteTest.php +19 -2
  61. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/HeaderTest.php +93 -6
  62. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/InstantArticleTest.php +10 -8
  63. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/InteractiveTest.php +39 -9
  64. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/SocialEmbedTest.php +7 -10
  65. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/SponsorTest.php +40 -0
  66. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/Validators/InstantArticleValidatorTest.php +1 -1
  67. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Parser/ParserTest.php +63 -0
  68. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Parser/instant-article-example.html +199 -0
  69. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/CMS/WPTransformerTest.php +2 -1
  70. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/CMS/wp-ia.xml +18 -0
  71. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/CMS/wp-rules.json +13 -78
  72. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/CMS/wp.html +8 -0
  73. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/Example/SimpleTransformerTest.php +1 -1
  74. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/Example/{simple-ia.xml → simple-ia.html} +5 -0
  75. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/Example/simple-rules.json +10 -0
  76. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/Example/simple.html +4 -0
  77. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/TransformerTest.php +26 -3
  78. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/instant-article-example.html +11 -6
  79. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/wp-rules.json +270 -0
  80. vendor/facebook/php-sdk-v4/composer.json +3 -3
  81. vendor/facebook/php-sdk-v4/src/Facebook/Facebook.php +2 -2
  82. vendor/facebook/php-sdk-v4/src/Facebook/FacebookApp.php +10 -1
  83. vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/Birthday.php +85 -0
  84. vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphNode.php +14 -2
  85. vendor/facebook/php-sdk-v4/src/Facebook/Helpers/FacebookRedirectLoginHelper.php +8 -16
  86. vendor/facebook/php-sdk-v4/src/Facebook/HttpClients/FacebookCurlHttpClient.php +3 -50
  87. vendor/facebook/php-sdk-v4/src/Facebook/PseudoRandomString/PseudoRandomStringGeneratorTrait.php +1 -4
  88. vendor/facebook/php-sdk-v4/src/Facebook/SignedRequest.php +2 -8
  89. vendor/facebook/php-sdk-v4/src/Facebook/polyfills.php +49 -0
  90. vendor/symfony/css-selector/CssSelector.php +2 -2
  91. vendor/symfony/css-selector/CssSelectorConverter.php +3 -3
  92. vendor/symfony/css-selector/Parser/Parser.php +8 -8
  93. vendor/symfony/css-selector/Parser/TokenStream.php +6 -6
  94. vendor/symfony/css-selector/XPath/Translator.php +2 -2
  95. wpcom-helper.php +0 -43
class-instant-articles-post.php CHANGED
@@ -296,7 +296,7 @@ class Instant_Articles_Post {
296
 
297
  // If we’re not it the loop or otherwise properly setup.
298
  $reset_postdata = false;
299
- if ( $this->_post->ID !== $post->ID ) {
300
  $post = get_post( $this->_post->ID );
301
  setup_postdata( $post );
302
  $reset_postdata = true;
@@ -322,6 +322,12 @@ class Instant_Articles_Post {
322
  // Some people choose to disable wpautop. Due to the Instant Articles spec, we really want it in!
323
  $content = wpautop( $content );
324
 
 
 
 
 
 
 
325
  /**
326
  * Filter the post content for Instant Articles.
327
  *
@@ -578,6 +584,31 @@ class Instant_Articles_Post {
578
  // Get time zone configured in WordPress. Default to UTC if no time zone configured.
579
  $date_time_zone = get_option( 'timezone_string' ) ? new DateTimeZone( get_option( 'timezone_string' ) ) : new DateTimeZone( 'UTC' );
580
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
581
  $header =
582
  Header::create()
583
  ->withPublishTime(
@@ -585,8 +616,14 @@ class Instant_Articles_Post {
585
  )
586
  ->withModifyTime(
587
  Time::create( Time::MODIFIED )->withDatetime( new DateTime( $this->_post->post_modified, $date_time_zone ) )
588
- )
589
- ->withTitle( $this->get_the_title() );
 
 
 
 
 
 
590
 
591
  $authors = $this->get_the_authors();
592
  foreach ( $authors as $author ) {
@@ -610,9 +647,9 @@ class Instant_Articles_Post {
610
  if ( $cover['src'] ) {
611
  $image = Image::create()->withURL( $cover['src'] );
612
  if ( isset( $cover['caption'] ) && strlen( $cover['caption'] ) > 0 ) {
613
- $image->withCaption(
614
- Caption::create()->withTitle( $cover['caption'] )
615
- );
616
  }
617
 
618
  $header->withCover( $image );
@@ -625,35 +662,12 @@ class Instant_Articles_Post {
625
  ->addMetaProperty( 'op:generator:application:version', IA_PLUGIN_VERSION );
626
 
627
  $settings_style = Instant_Articles_Option_Styles::get_option_decoded();
628
- if ( isset( $settings_style['article_style'] ) && ! empty ( $settings_style['article_style'] ) ) {
629
  $this->instant_article->withStyle( $settings_style['article_style'] );
630
- }
631
- else {
632
  $this->instant_article->withStyle( 'default' );
633
  }
634
 
635
- $file_path = plugin_dir_path( __FILE__ ) . 'rules-configuration.json';
636
- $configuration = file_get_contents( $file_path );
637
-
638
- $transformer = new Transformer();
639
- $this->transformer = $transformer;
640
- $transformer->loadRules( $configuration );
641
-
642
- $transformer = apply_filters( 'instant_articles_transformer_rules_loaded', $transformer );
643
-
644
- $settings_publishing = Instant_Articles_Option_Publishing::get_option_decoded();
645
-
646
- if (
647
- isset ( $settings_publishing['custom_rules_enabled'] ) &&
648
- ! empty( $settings_publishing['custom_rules_enabled'] ) &&
649
- isset ( $settings_publishing['custom_rules'] ) &&
650
- ! empty( $settings_publishing['custom_rules'] )
651
- ) {
652
- $transformer->loadRules( $settings_publishing['custom_rules'] );
653
- }
654
-
655
- $transformer = apply_filters( 'instant_articles_transformer_custom_rules_loaded', $transformer );
656
-
657
  $libxml_previous_state = libxml_use_internal_errors( true );
658
  $document = new DOMDocument( '1.0', get_option( 'blog_charset' ) );
659
  $content = $this->get_the_content();
@@ -666,6 +680,20 @@ class Instant_Articles_Post {
666
  }
667
 
668
  $result = $document->loadHTML( '<!doctype html><html><body>' . $content . '</body></html>' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
669
  libxml_clear_errors();
670
  libxml_use_internal_errors( $libxml_previous_state );
671
 
296
 
297
  // If we’re not it the loop or otherwise properly setup.
298
  $reset_postdata = false;
299
+ if ( empty( $post ) || $this->_post->ID !== $post->ID ) {
300
  $post = get_post( $this->_post->ID );
301
  setup_postdata( $post );
302
  $reset_postdata = true;
322
  // Some people choose to disable wpautop. Due to the Instant Articles spec, we really want it in!
323
  $content = wpautop( $content );
324
 
325
+ // Remove hyperlinks beginning with a # as they cause errors on Facebook (from http://wordpress.stackexchange.com/a/227332/19528)
326
+ preg_match_all( '!<a[^>]*? href=[\'"]#[^<]+</a>!i', $content, $matches );
327
+ foreach ( $matches[0] as $link ) {
328
+ $content = str_replace( $link, strip_tags($link), $content );
329
+ }
330
+
331
  /**
332
  * Filter the post content for Instant Articles.
333
  *
584
  // Get time zone configured in WordPress. Default to UTC if no time zone configured.
585
  $date_time_zone = get_option( 'timezone_string' ) ? new DateTimeZone( get_option( 'timezone_string' ) ) : new DateTimeZone( 'UTC' );
586
 
587
+ // Initialize transformer
588
+ $file_path = plugin_dir_path( __FILE__ ) . 'rules-configuration.json';
589
+ $configuration = file_get_contents( $file_path );
590
+
591
+ $transformer = new Transformer();
592
+ $this->transformer = $transformer;
593
+ $transformer->loadRules( $configuration );
594
+
595
+ $transformer = apply_filters( 'instant_articles_transformer_rules_loaded', $transformer );
596
+
597
+ $settings_publishing = Instant_Articles_Option_Publishing::get_option_decoded();
598
+
599
+ if (
600
+ isset( $settings_publishing['custom_rules_enabled'] ) &&
601
+ ! empty( $settings_publishing['custom_rules_enabled'] ) &&
602
+ isset( $settings_publishing['custom_rules'] ) &&
603
+ ! empty( $settings_publishing['custom_rules'] )
604
+ ) {
605
+ $transformer->loadRules( $settings_publishing['custom_rules'] );
606
+ }
607
+
608
+ $transformer = apply_filters( 'instant_articles_transformer_custom_rules_loaded', $transformer );
609
+
610
+ $blog_charset = get_option( 'blog_charset' );
611
+
612
  $header =
613
  Header::create()
614
  ->withPublishTime(
616
  )
617
  ->withModifyTime(
618
  Time::create( Time::MODIFIED )->withDatetime( new DateTime( $this->_post->post_modified, $date_time_zone ) )
619
+ );
620
+
621
+ $title = $this->get_the_title();
622
+ if ( $title ) {
623
+ $document = new DOMDocument();
624
+ $document->loadHTML( '<?xml encoding="' . $blog_charset . '" ?><h1>' . $title . '</h1>' );
625
+ $transformer->transform( $header, $document );
626
+ }
627
 
628
  $authors = $this->get_the_authors();
629
  foreach ( $authors as $author ) {
647
  if ( $cover['src'] ) {
648
  $image = Image::create()->withURL( $cover['src'] );
649
  if ( isset( $cover['caption'] ) && strlen( $cover['caption'] ) > 0 ) {
650
+ $document = new DOMDocument();
651
+ $document->loadHTML( '<?xml encoding="' . $blog_charset . '" ?><h1>' . $cover['caption'] . '</h1>' );
652
+ $image->withCaption( $transformer->transform( Caption::create(), $document ) );
653
  }
654
 
655
  $header->withCover( $image );
662
  ->addMetaProperty( 'op:generator:application:version', IA_PLUGIN_VERSION );
663
 
664
  $settings_style = Instant_Articles_Option_Styles::get_option_decoded();
665
+ if ( isset( $settings_style['article_style'] ) && ! empty( $settings_style['article_style'] ) ) {
666
  $this->instant_article->withStyle( $settings_style['article_style'] );
667
+ } else {
 
668
  $this->instant_article->withStyle( 'default' );
669
  }
670
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
671
  $libxml_previous_state = libxml_use_internal_errors( true );
672
  $document = new DOMDocument( '1.0', get_option( 'blog_charset' ) );
673
  $content = $this->get_the_content();
680
  }
681
 
682
  $result = $document->loadHTML( '<!doctype html><html><body>' . $content . '</body></html>' );
683
+
684
+ // We need to make sure that scripts use absolute URLs and not relative URLs.
685
+ $scripts = $document->getElementsByTagName('script');
686
+ if ( ! empty( $scripts ) ) {
687
+ foreach ( $scripts as $script ){
688
+ $src = $script->getAttribute( 'src' );
689
+ $explode_src = parse_url( $src );
690
+ if ( is_array( $explode_src ) && empty( $explode_src['scheme'] ) ) {
691
+ $src = 'https://' . $explode_src['host'] . $explode_src['path'];
692
+ }
693
+ $script->setAttribute( 'src' , $src );
694
+ }
695
+ }
696
+
697
  libxml_clear_errors();
698
  libxml_use_internal_errors( $libxml_previous_state );
699
 
class-instant-articles-publisher.php CHANGED
@@ -17,6 +17,11 @@ use Facebook\Facebook;
17
  */
18
  class Instant_Articles_Publisher {
19
 
 
 
 
 
 
20
  /**
21
  * Inits publisher.
22
  */
@@ -42,6 +47,12 @@ class Instant_Articles_Publisher {
42
  return;
43
  }
44
 
 
 
 
 
 
 
45
  // Transform the post to an Instant Article.
46
  $adapter = new Instant_Articles_Post( $post );
47
 
@@ -51,7 +62,7 @@ class Instant_Articles_Publisher {
51
  // This is important because the save_post action is also triggered by bulk updates, but in this case
52
  // WordPress does not load the content field from DB for performance reasons. In this case, articles
53
  // will be empty here, despite of them actually having content.
54
- if ( count($article->getChildren()) === 0 || ! $article->getHeader() || ! $article->getHeader()->getTitle() ) {
55
  return;
56
  }
57
 
@@ -87,10 +98,12 @@ class Instant_Articles_Publisher {
87
 
88
  try {
89
  // Import the article.
90
- $client->importArticle( $article, $take_live );
 
91
  } catch ( Exception $e ) {
92
  // Try without taking live for pages not yet reviewed.
93
- $client->importArticle( $article, false );
 
94
  }
95
  }
96
  } catch ( Exception $e ) {
17
  */
18
  class Instant_Articles_Publisher {
19
 
20
+ /**
21
+ * Key to store the submission status ID on meta data
22
+ */
23
+ const SUBMISSION_ID_KEY = 'instant_articles_submission_id';
24
+
25
  /**
26
  * Inits publisher.
27
  */
47
  return;
48
  }
49
 
50
+ // Only process posts
51
+ $post_types = apply_filters( 'instant_articles_post_types', array( 'post' ) );
52
+ if ( ! in_array( $post->post_type, $post_types ) ) {
53
+ return;
54
+ }
55
+
56
  // Transform the post to an Instant Article.
57
  $adapter = new Instant_Articles_Post( $post );
58
 
62
  // This is important because the save_post action is also triggered by bulk updates, but in this case
63
  // WordPress does not load the content field from DB for performance reasons. In this case, articles
64
  // will be empty here, despite of them actually having content.
65
+ if ( count( $article->getChildren() ) === 0 || ! $article->getHeader() || ! $article->getHeader()->getTitle() ) {
66
  return;
67
  }
68
 
98
 
99
  try {
100
  // Import the article.
101
+ $submission_id = $client->importArticle( $article, $take_live );
102
+ update_post_meta( $post_id, self::SUBMISSION_ID_KEY, $submission_id );
103
  } catch ( Exception $e ) {
104
  // Try without taking live for pages not yet reviewed.
105
+ $submission_id = $client->importArticle( $article, false );
106
+ update_post_meta( $post_id, self::SUBMISSION_ID_KEY, $submission_id );
107
  }
108
  }
109
  } catch ( Exception $e ) {
compat/class-instant-articles-google-analytics-for-wordpress.php CHANGED
@@ -51,7 +51,7 @@ class Instant_Articles_Google_Analytics_For_WordPress {
51
 
52
  $options = Yoast_GA_Options::instance()->options;
53
 
54
- if ( isset( $options['enable_universal'] ) && 1 == $options['enable_universal'] ) {
55
  $tracker = new Yoast_GA_Universal;
56
  } else {
57
  $tracker = new Yoast_GA_JS;
51
 
52
  $options = Yoast_GA_Options::instance()->options;
53
 
54
+ if ( isset( $options['enable_universal'] ) && 1 === intval( $options['enable_universal'] ) ) {
55
  $tracker = new Yoast_GA_Universal;
56
  } else {
57
  $tracker = new Yoast_GA_JS;
compat/class-instant-articles-jetpack.php CHANGED
@@ -39,7 +39,7 @@ class Instant_Articles_Jetpack {
39
  private function _fix_facebook_embed() {
40
 
41
  // All of these are registered in jetpack/modules/shortcodes/facebook.php
42
-
43
  if ( defined( 'JETPACK_FACEBOOK_EMBED_REGEX' ) ) {
44
  wp_embed_unregister_handler( 'facebook' );
45
  wp_embed_register_handler( 'facebook', JETPACK_FACEBOOK_EMBED_REGEX, array( __CLASS__, 'facebook_embed_handler' ) );
@@ -71,14 +71,13 @@ class Instant_Articles_Jetpack {
71
  $locale = get_locale();
72
 
73
  // Source: https://www.facebook.com/translations/FacebookLocales.xml
74
- $fbLocales = array( 'af_ZA', 'ak_GH', 'am_ET', 'ar_AR', 'as_IN', 'ay_BO', 'az_AZ', 'be_BY', 'bg_BG', 'bn_IN', 'br_FR', 'bs_BA', 'ca_ES', 'cb_IQ', 'ck_US', 'co_FR', 'cs_CZ', 'cx_PH', 'cy_GB', 'da_DK', 'de_DE', 'el_GR', 'en_GB', 'en_IN', 'en_PI', 'en_UD', 'en_US', 'eo_EO', 'es_CL', 'es_CO', 'es_ES', 'es_LA', 'es_MX', 'es_VE', 'et_EE', 'eu_ES', 'fa_IR', 'fb_LT', 'ff_NG', 'fi_FI', 'fo_FO', 'fr_CA', 'fr_FR', 'fy_NL', 'ga_IE', 'gl_ES', 'gn_PY', 'gu_IN', 'gx_GR', 'ha_NG', 'he_IL', 'hi_IN', 'hr_HR', 'ht_HT', 'hu_HU', 'hy_AM', 'id_ID', 'ig_NG', 'is_IS', 'it_IT', 'ja_JP', 'ja_KS', 'jv_ID', 'ka_GE', 'kk_KZ', 'km_KH', 'kn_IN', 'ko_KR', 'ku_TR', 'ky_KG', 'la_VA', 'lg_UG', 'li_NL', 'ln_CD', 'lo_LA', 'lt_LT', 'lv_LV', 'mg_MG', 'mi_NZ', 'mk_MK', 'ml_IN', 'mn_MN', 'mr_IN', 'ms_MY', 'mt_MT', 'my_MM', 'nb_NO', 'nd_ZW', 'ne_NP', 'nl_BE', 'nl_NL', 'nn_NO', 'ny_MW', 'or_IN', 'pa_IN', 'pl_PL', 'ps_AF', 'pt_BR', 'pt_PT', 'qc_GT', 'qu_PE', 'rm_CH', 'ro_RO', 'ru_RU', 'rw_RW', 'sa_IN', 'sc_IT', 'se_NO', 'si_LK', 'sk_SK', 'sl_SI', 'sn_ZW', 'so_SO', 'sq_AL', 'sr_RS', 'sv_SE', 'sw_KE', 'sy_SY', 'sz_PL', 'ta_IN', 'te_IN', 'tg_TJ', 'th_TH', 'tk_TM', 'tl_PH', 'tl_ST', 'tr_TR', 'tt_RU', 'tz_MA', 'uk_UA', 'ur_PK', 'uz_UZ', 'vi_VN', 'wo_SN', 'xh_ZA', 'yi_DE', 'yo_NG', 'zh_CN', 'zh_HK', 'zh_TW', 'zu_ZA', 'zz_TR', );
75
 
76
  // If our locale isn’t supported by Facebook, we’ll fallback to en_US
77
- if ( ! in_array( $locale, $fbLocales) ) {
78
  $locale = 'en_US';
79
  }
80
 
81
- return '<figure class="op-social"><iframe><script src="//connect.facebook.net/' . $locale . '/sdk.js#xfbml=1&amp;version=v2.2" async></script><div class="fb-post" data-href="' . esc_url( $url ) . '"></div></iframe></figure>';
82
  }
83
-
84
  }
39
  private function _fix_facebook_embed() {
40
 
41
  // All of these are registered in jetpack/modules/shortcodes/facebook.php
42
+
43
  if ( defined( 'JETPACK_FACEBOOK_EMBED_REGEX' ) ) {
44
  wp_embed_unregister_handler( 'facebook' );
45
  wp_embed_register_handler( 'facebook', JETPACK_FACEBOOK_EMBED_REGEX, array( __CLASS__, 'facebook_embed_handler' ) );
71
  $locale = get_locale();
72
 
73
  // Source: https://www.facebook.com/translations/FacebookLocales.xml
74
+ $fb_locales = array( 'af_ZA', 'ak_GH', 'am_ET', 'ar_AR', 'as_IN', 'ay_BO', 'az_AZ', 'be_BY', 'bg_BG', 'bn_IN', 'br_FR', 'bs_BA', 'ca_ES', 'cb_IQ', 'ck_US', 'co_FR', 'cs_CZ', 'cx_PH', 'cy_GB', 'da_DK', 'de_DE', 'el_GR', 'en_GB', 'en_IN', 'en_PI', 'en_UD', 'en_US', 'eo_EO', 'es_CL', 'es_CO', 'es_ES', 'es_LA', 'es_MX', 'es_VE', 'et_EE', 'eu_ES', 'fa_IR', 'fb_LT', 'ff_NG', 'fi_FI', 'fo_FO', 'fr_CA', 'fr_FR', 'fy_NL', 'ga_IE', 'gl_ES', 'gn_PY', 'gu_IN', 'gx_GR', 'ha_NG', 'he_IL', 'hi_IN', 'hr_HR', 'ht_HT', 'hu_HU', 'hy_AM', 'id_ID', 'ig_NG', 'is_IS', 'it_IT', 'ja_JP', 'ja_KS', 'jv_ID', 'ka_GE', 'kk_KZ', 'km_KH', 'kn_IN', 'ko_KR', 'ku_TR', 'ky_KG', 'la_VA', 'lg_UG', 'li_NL', 'ln_CD', 'lo_LA', 'lt_LT', 'lv_LV', 'mg_MG', 'mi_NZ', 'mk_MK', 'ml_IN', 'mn_MN', 'mr_IN', 'ms_MY', 'mt_MT', 'my_MM', 'nb_NO', 'nd_ZW', 'ne_NP', 'nl_BE', 'nl_NL', 'nn_NO', 'ny_MW', 'or_IN', 'pa_IN', 'pl_PL', 'ps_AF', 'pt_BR', 'pt_PT', 'qc_GT', 'qu_PE', 'rm_CH', 'ro_RO', 'ru_RU', 'rw_RW', 'sa_IN', 'sc_IT', 'se_NO', 'si_LK', 'sk_SK', 'sl_SI', 'sn_ZW', 'so_SO', 'sq_AL', 'sr_RS', 'sv_SE', 'sw_KE', 'sy_SY', 'sz_PL', 'ta_IN', 'te_IN', 'tg_TJ', 'th_TH', 'tk_TM', 'tl_PH', 'tl_ST', 'tr_TR', 'tt_RU', 'tz_MA', 'uk_UA', 'ur_PK', 'uz_UZ', 'vi_VN', 'wo_SN', 'xh_ZA', 'yi_DE', 'yo_NG', 'zh_CN', 'zh_HK', 'zh_TW', 'zu_ZA', 'zz_TR' );
75
 
76
  // If our locale isn’t supported by Facebook, we’ll fallback to en_US
77
+ if ( ! in_array( $locale, $fb_locales, true ) ) {
78
  $locale = 'en_US';
79
  }
80
 
81
+ return '<figure class="op-social"><iframe><script src="https://connect.facebook.net/' . $locale . '/sdk.js#xfbml=1&amp;version=v2.6" async></script><div class="fb-post" data-href="' . esc_url( $url ) . '"></div></iframe></figure>';
82
  }
 
83
  }
facebook-instant-articles.php CHANGED
@@ -4,7 +4,7 @@
4
  * Description: Add support for Instant Articles for Facebook to your WordPress site.
5
  * Author: Automattic, Dekode, Facebook
6
  * Author URI: https://vip.wordpress.com/plugins/instant-articles/
7
- * Version: 2.11
8
  * Text Domain: instant-articles
9
  * License: GPLv2
10
  * License URI: http://www.gnu.org/licenses/gpl-2.0.html
@@ -15,16 +15,10 @@
15
  if ( version_compare( PHP_VERSION, '5.4', '<' ) ) {
16
  add_action(
17
  'admin_notices',
18
- create_function(
19
- '',
20
- "echo '<div class=\"error\"><p>".
21
- __(
22
- 'Instant Articles for WP requires PHP 5.4 to function properly. '.
23
- 'Please upgrade PHP or deactivate Instant Articles for WP.',
24
- 'instant-articles'
25
- ).
26
- "</p></div>';"
27
- )
28
  );
29
  return;
30
  } else {
@@ -166,6 +160,18 @@ if ( version_compare( PHP_VERSION, '5.4', '<' ) ) {
166
  $query->set( 'posts_per_page', 10 );
167
  $query->set( 'posts_per_rss', 10 );
168
 
 
 
 
 
 
 
 
 
 
 
 
 
169
  /**
170
  * If the constant INSTANT_ARTICLES_LIMIT_POSTS is set to true, we will limit the feed
171
  * to only include posts which are modified within the last 24 hours.
4
  * Description: Add support for Instant Articles for Facebook to your WordPress site.
5
  * Author: Automattic, Dekode, Facebook
6
  * Author URI: https://vip.wordpress.com/plugins/instant-articles/
7
+ * Version: 3.0
8
  * Text Domain: instant-articles
9
  * License: GPLv2
10
  * License URI: http://www.gnu.org/licenses/gpl-2.0.html
15
  if ( version_compare( PHP_VERSION, '5.4', '<' ) ) {
16
  add_action(
17
  'admin_notices',
18
+ function () {
19
+ echo '<div class="error"><p>' .
20
+ esc_html__( 'Instant Articles for WP requires PHP 5.4 to function properly. Please upgrade PHP or deactivate Instant Articles for WP.', 'instant-articles' ) . '</p></div>';
21
+ }
 
 
 
 
 
 
22
  );
23
  return;
24
  } else {
160
  $query->set( 'posts_per_page', 10 );
161
  $query->set( 'posts_per_rss', 10 );
162
 
163
+ /**
164
+ * Filter the post types to include in the query.
165
+ *
166
+ * Default to `post` only, but allow other post types to be included by the theme/plugins.
167
+ *
168
+ * @since 2.12
169
+ *
170
+ * @param array $post_types Array of post types
171
+ */
172
+ $post_types = apply_filters( 'instant_articles_post_types', array( 'post' ) );
173
+ $query->set( 'post_type', $post_types );
174
+
175
  /**
176
  * If the constant INSTANT_ARTICLES_LIMIT_POSTS is set to true, we will limit the feed
177
  * to only include posts which are modified within the last 24 hours.
meta-box/class-instant-articles-meta-box.php CHANGED
@@ -57,7 +57,8 @@ class Instant_Articles_Meta_Box {
57
  * Renderer for the Metabox.
58
  */
59
  public static function render_meta_box() {
60
- $post = get_post( intval( filter_input( INPUT_POST, 'post_ID' ) ) );
 
61
  $adapter = new Instant_Articles_Post( $post );
62
  $article = $adapter->to_instant_article();
63
  $canonical_url = $adapter->get_canonical_url();
@@ -67,28 +68,35 @@ class Instant_Articles_Meta_Box {
67
  Instant_Articles_Settings::menu_items();
68
  $settings_page_href = Instant_Articles_Settings::get_href_to_settings_page();
69
 
70
- try {
71
- $fb_app_settings = Instant_Articles_Option_FB_App::get_option_decoded();
72
- $fb_page_settings = Instant_Articles_Option_FB_Page::get_option_decoded();
 
73
 
74
- if ( isset( $fb_app_settings['app_id'] )
75
- && isset( $fb_app_settings['app_secret'] )
76
- && isset( $fb_page_settings['page_access_token'] )
77
- && isset( $fb_page_settings['page_id'] ) ) {
78
- // Instantiate a new Client to get the status of this article.
79
- $client = Client::create(
80
- $fb_app_settings['app_id'],
81
- $fb_app_settings['app_secret'],
82
- $fb_page_settings['page_access_token'],
83
- $fb_page_settings['page_id']
84
- );
85
 
86
- // Grab the latest status of this article and display.
87
- $article_id = $client->getArticleIDFromCanonicalURL( $canonical_url );
88
- $submission_status = $client->getLastSubmissionStatus( $article_id );
 
 
 
 
 
 
 
 
89
  }
90
- } catch ( FacebookResponseException $e ) {
91
- $submission_status = null;
92
  }
93
 
94
  include( dirname( __FILE__ ) . '/meta-box-template.php' );
57
  * Renderer for the Metabox.
58
  */
59
  public static function render_meta_box() {
60
+ $post_id = intval( filter_input( INPUT_POST, 'post_ID' ) );
61
+ $post = get_post( $post_id );
62
  $adapter = new Instant_Articles_Post( $post );
63
  $article = $adapter->to_instant_article();
64
  $canonical_url = $adapter->get_canonical_url();
68
  Instant_Articles_Settings::menu_items();
69
  $settings_page_href = Instant_Articles_Settings::get_href_to_settings_page();
70
 
71
+ if ( $published ) {
72
+ try {
73
+ $fb_app_settings = Instant_Articles_Option_FB_App::get_option_decoded();
74
+ $fb_page_settings = Instant_Articles_Option_FB_Page::get_option_decoded();
75
 
76
+ if ( isset( $fb_app_settings['app_id'] )
77
+ && isset( $fb_app_settings['app_secret'] )
78
+ && isset( $fb_page_settings['page_access_token'] )
79
+ && isset( $fb_page_settings['page_id'] ) ) {
80
+ // Instantiate a new Client to get the status of this article.
81
+ $client = Client::create(
82
+ $fb_app_settings['app_id'],
83
+ $fb_app_settings['app_secret'],
84
+ $fb_page_settings['page_access_token'],
85
+ $fb_page_settings['page_id']
86
+ );
87
 
88
+ $submission_status_id = get_post_meta( $post_id, Instant_Articles_Publisher::SUBMISSION_ID_KEY, true );
89
+ if ( ! empty( $submission_status_id ) ) {
90
+ $submission_status = $client->getSubmissionStatus( $submission_status_id );
91
+ } else {
92
+ // Grab the latest status of this article and display.
93
+ $article_id = $client->getArticleIDFromCanonicalURL( $canonical_url );
94
+ $submission_status = $client->getLastSubmissionStatus( $article_id );
95
+ }
96
+ }
97
+ } catch ( FacebookResponseException $e ) {
98
+ $submission_status = null;
99
  }
 
 
100
  }
101
 
102
  include( dirname( __FILE__ ) . '/meta-box-template.php' );
meta-box/meta-box-template.php CHANGED
@@ -151,11 +151,11 @@ use Facebook\InstantArticles\Client\ServerMessage;
151
  <?php echo esc_html( $warning ); ?>
152
  <span>
153
  <?php
154
- if ( $warning->getNode() ) {
155
- echo esc_html(
156
- $warning->getNode()->ownerDocument->saveHTML( $warning->getNode() )
157
- );
158
- }
159
  ?>
160
  </span>
161
  </div>
151
  <?php echo esc_html( $warning ); ?>
152
  <span>
153
  <?php
154
+ if ( $warning->getNode() ) {
155
+ echo esc_html(
156
+ $warning->getNode()->ownerDocument->saveHTML( $warning->getNode() )
157
+ );
158
+ }
159
  ?>
160
  </span>
161
  </div>
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Contributors: trrine, olethomas, bjornjohansen, dekode, automattic, facebook
3
  Tags: instant articles, facebook, mobile
4
  Requires at least: 4.3
5
- Tested up to: 4.5
6
- Stable tag: 2.11
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -85,6 +85,21 @@ Usually simply visiting the permalinks settings page in the WordPress dashboard
85
 
86
  == Changelog ==
87
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  = 2.1 =
89
  * Fixes compatibility with PHP 5.4+
90
  * Bug fixes
2
  Contributors: trrine, olethomas, bjornjohansen, dekode, automattic, facebook
3
  Tags: instant articles, facebook, mobile
4
  Requires at least: 4.3
5
+ Tested up to: 4.5.3
6
+ Stable tag: 3.0
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
85
 
86
  == Changelog ==
87
 
88
+ = 3.0 =
89
+
90
+ * Fix versioning - use WP style
91
+ * Ignore hyperlinks with a #
92
+ * Allow filtering of post types used in the feed
93
+ * Use v2.6 of the Facebook API
94
+ * Coding standards & whitespace fixes
95
+ * Load Facebook SDK over HTTPS
96
+ * Avoid crawling of 404s
97
+ * Replace social embeds with interactives
98
+ * Use submission ID to check status in the admin
99
+ * Fix over-zealous escaping
100
+
101
+ props markbarnes, paulschreiber, diegoquinteiro, gemedet
102
+
103
  = 2.1 =
104
  * Fixes compatibility with PHP 5.4+
105
  * Bug fixes
rules-configuration.json CHANGED
@@ -17,6 +17,9 @@
17
  },{
18
  "class": "PassThroughRule",
19
  "selector" : "del"
 
 
 
20
  }, {
21
  "class": "PassThroughRule",
22
  "selector" : "span"
@@ -118,46 +121,66 @@
118
  "class": "H2Rule",
119
  "selector" : "h3,h4,h5,h6"
120
  }, {
121
- "class": "SocialEmbedRule",
122
  "selector" : "iframe",
123
  "properties" : {
124
- "socialembed.url" : {
125
  "type" : "string",
126
  "selector" : "iframe",
127
  "attribute": "src"
128
  },
129
- "socialembed.iframe" : {
 
 
 
 
 
 
 
 
 
 
130
  "type" : "children",
131
  "selector" : "iframe"
132
  },
133
- "socialembed.caption" : {
134
  "type" : "element",
135
  "selector" : "figcaption"
136
  }
137
  }
138
  }, {
139
- "class": "SocialEmbedRule",
140
  "selector" : "//p[iframe]",
141
  "properties" : {
142
- "socialembed.url" : {
143
  "type" : "string",
144
  "selector" : "iframe",
145
  "attribute": "src"
146
  },
147
- "socialembed.iframe" : {
 
 
 
 
 
 
 
 
 
 
148
  "type" : "children",
149
  "selector" : "iframe"
150
  },
151
- "socialembed.caption" : {
152
  "type" : "element",
153
  "selector" : "figcaption"
154
  }
155
  }
156
  }, {
157
- "class": "SocialEmbedRule",
158
  "selector" : "div.embed",
159
  "properties" : {
160
- "socialembed.iframe" : {
161
  "type" : "children",
162
  "selector" : "div.embed"
163
  }
@@ -181,13 +204,23 @@
181
  }
182
  }
183
  }, {
184
- "class": "SocialEmbedRule",
185
  "selector" : "//div[@class='embed' and iframe]",
186
  "properties" : {
187
- "socialembed.url" : {
188
  "type" : "string",
189
  "selector" : "iframe",
190
  "attribute": "src"
 
 
 
 
 
 
 
 
 
 
191
  }
192
  }
193
  }, {
17
  },{
18
  "class": "PassThroughRule",
19
  "selector" : "del"
20
+ },{
21
+ "class": "PassThroughRule",
22
+ "selector" : "mark"
23
  }, {
24
  "class": "PassThroughRule",
25
  "selector" : "span"
121
  "class": "H2Rule",
122
  "selector" : "h3,h4,h5,h6"
123
  }, {
124
+ "class": "InteractiveRule",
125
  "selector" : "iframe",
126
  "properties" : {
127
+ "interactive.url" : {
128
  "type" : "string",
129
  "selector" : "iframe",
130
  "attribute": "src"
131
  },
132
+ "interactive.width" : {
133
+ "type" : "int",
134
+ "selector" : "iframe",
135
+ "attribute": "width"
136
+ },
137
+ "interactive.height" : {
138
+ "type" : "int",
139
+ "selector" : "iframe",
140
+ "attribute": "height"
141
+ },
142
+ "interactive.iframe" : {
143
  "type" : "children",
144
  "selector" : "iframe"
145
  },
146
+ "interactive.caption" : {
147
  "type" : "element",
148
  "selector" : "figcaption"
149
  }
150
  }
151
  }, {
152
+ "class": "InteractiveRule",
153
  "selector" : "//p[iframe]",
154
  "properties" : {
155
+ "interactive.url" : {
156
  "type" : "string",
157
  "selector" : "iframe",
158
  "attribute": "src"
159
  },
160
+ "interactive.width" : {
161
+ "type" : "int",
162
+ "selector" : "iframe",
163
+ "attribute": "width"
164
+ },
165
+ "interactive.height" : {
166
+ "type" : "int",
167
+ "selector" : "iframe",
168
+ "attribute": "height"
169
+ },
170
+ "interactive.iframe" : {
171
  "type" : "children",
172
  "selector" : "iframe"
173
  },
174
+ "interactive.caption" : {
175
  "type" : "element",
176
  "selector" : "figcaption"
177
  }
178
  }
179
  }, {
180
+ "class": "InteractiveRule",
181
  "selector" : "div.embed",
182
  "properties" : {
183
+ "interactive.iframe" : {
184
  "type" : "children",
185
  "selector" : "div.embed"
186
  }
204
  }
205
  }
206
  }, {
207
+ "class": "InteractiveRule",
208
  "selector" : "//div[@class='embed' and iframe]",
209
  "properties" : {
210
+ "interactive.url" : {
211
  "type" : "string",
212
  "selector" : "iframe",
213
  "attribute": "src"
214
+ },
215
+ "interactive.width" : {
216
+ "type" : "int",
217
+ "selector" : "iframe",
218
+ "attribute": "width"
219
+ },
220
+ "interactive.height" : {
221
+ "type" : "int",
222
+ "selector" : "iframe",
223
+ "attribute": "height"
224
  }
225
  }
226
  }, {
settings/class-instant-articles-option-ads.php CHANGED
@@ -55,6 +55,7 @@ class Instant_Articles_Option_Ads extends Instant_Articles_Option {
55
  'description' => 'Add code to be used for displayed ads in your Instant Articles.',
56
  'default' => '',
57
  'placeholder' => '<script>...</script>',
 
58
  ),
59
 
60
  'dimensions' => array(
@@ -104,10 +105,7 @@ class Instant_Articles_Option_Ads extends Instant_Articles_Option {
104
  : '';
105
 
106
  ?>
107
- <select
108
- id="<?php echo esc_attr( $id ); ?>"
109
- name="<?php echo esc_attr( $name ); ?>"
110
- >
111
  <?php foreach ( $args['select_options'] as $ad_source_key => $ad_source_name ) : ?>
112
  <option
113
  value="<?php echo esc_attr( $ad_source_key ); ?>"
@@ -122,9 +120,7 @@ class Instant_Articles_Option_Ads extends Instant_Articles_Option {
122
  asort( $compat_plugins );
123
  if ( count( $compat_plugins ) > 0 ) :
124
  ?>
125
- <optgroup
126
- label="From Supported Plugins"
127
- >
128
  <?php foreach ( $compat_plugins as $ad_source_key => $ad_source_info ) : ?>
129
  <option
130
  value="<?php echo esc_attr( $ad_source_key ); ?>"
@@ -138,7 +134,7 @@ class Instant_Articles_Option_Ads extends Instant_Articles_Option {
138
 
139
  ?>
140
  </select>
141
- <?php echo $description; ?>
142
  <?php
143
  }
144
 
@@ -173,7 +169,7 @@ class Instant_Articles_Option_Ads extends Instant_Articles_Option {
173
  $all_options[] = $compat_id;
174
  }
175
 
176
- if ( ! in_array( $field_value, $all_options ) ) {
177
  $field_values[ $field_id ] = $field['default'];
178
  add_settings_error(
179
  $field_id,
@@ -198,7 +194,7 @@ class Instant_Articles_Option_Ads extends Instant_Articles_Option {
198
 
199
  case 'iframe_url':
200
  if ( isset( $field_values['ad_source'] ) && 'iframe' === $field_values['ad_source'] ) {
201
- $url = $field_values[$field_id];
202
  if ( substr( $url, 0, 2 ) === '//' ) {
203
  // Allow URLs without protocol prefix
204
  $url = 'http:' . $url;
55
  'description' => 'Add code to be used for displayed ads in your Instant Articles.',
56
  'default' => '',
57
  'placeholder' => '<script>...</script>',
58
+ 'double_encode' => true,
59
  ),
60
 
61
  'dimensions' => array(
105
  : '';
106
 
107
  ?>
108
+ <select id="<?php echo esc_attr( $id ); ?>" name="<?php echo esc_attr( $name ); ?>" >
 
 
 
109
  <?php foreach ( $args['select_options'] as $ad_source_key => $ad_source_name ) : ?>
110
  <option
111
  value="<?php echo esc_attr( $ad_source_key ); ?>"
120
  asort( $compat_plugins );
121
  if ( count( $compat_plugins ) > 0 ) :
122
  ?>
123
+ <optgroup label="From Supported Plugins">
 
 
124
  <?php foreach ( $compat_plugins as $ad_source_key => $ad_source_info ) : ?>
125
  <option
126
  value="<?php echo esc_attr( $ad_source_key ); ?>"
134
 
135
  ?>
136
  </select>
137
+ <?php echo esc_html( $description ); ?>
138
  <?php
139
  }
140
 
169
  $all_options[] = $compat_id;
170
  }
171
 
172
+ if ( ! in_array( $field_value, $all_options, true ) ) {
173
  $field_values[ $field_id ] = $field['default'];
174
  add_settings_error(
175
  $field_id,
194
 
195
  case 'iframe_url':
196
  if ( isset( $field_values['ad_source'] ) && 'iframe' === $field_values['ad_source'] ) {
197
+ $url = $field_values[ $field_id ];
198
  if ( substr( $url, 0, 2 ) === '//' ) {
199
  // Allow URLs without protocol prefix
200
  $url = 'http:' . $url;
settings/class-instant-articles-option-analytics.php CHANGED
@@ -43,6 +43,7 @@ class Instant_Articles_Option_Analytics extends Instant_Articles_Option {
43
  'placeholder' => '<script>...</script>',
44
  'description' => 'Note: You do not need to include any &lt;op-tracker&gt; tags. The plugin will automatically include them in the article markup.',
45
  'default' => '',
 
46
  ),
47
  );
48
 
43
  'placeholder' => '<script>...</script>',
44
  'description' => 'Note: You do not need to include any &lt;op-tracker&gt; tags. The plugin will automatically include them in the article markup.',
45
  'default' => '',
46
+ 'double_encode' => true,
47
  ),
48
  );
49
 
settings/class-instant-articles-option-publishing.php CHANGED
@@ -44,7 +44,7 @@ class Instant_Articles_Option_Publishing extends Instant_Articles_Option {
44
  'render' => 'textarea',
45
  'placeholder' => '{ "rules": [{ "class": "BoldRule", "selector": "span.bold" }, ... ] }',
46
  'description' => 'Read more about <a href="https://github.com/facebook/facebook-instant-articles-sdk-php/blob/master/docs/QuickStart.md#custom-transformer-rules" target="_blank">defining your own custom rules</a> to extend/override the <a href="https://github.com/Automattic/facebook-instant-articles-wp/blob/master/rules-configuration.json" target="_blank">built-in ruleset</a>. If you\'ve defined a common rule which you think this plugin should include by default, <a href="https://github.com/Automattic/facebook-instant-articles-wp/issues/new" target="_blank">tell us about it</a>!',
47
- 'default' => ''
48
  ),
49
 
50
  );
@@ -62,7 +62,7 @@ class Instant_Articles_Option_Publishing extends Instant_Articles_Option {
62
  );
63
  wp_localize_script( 'instant-articles-option-publishing', 'INSTANT_ARTICLES_OPTION_PUBLISHING', array(
64
  'option_field_id_custom_rules_enabled' => self::OPTION_KEY . '-custom_rules_enabled',
65
- 'option_field_id_custom_rules' => self::OPTION_KEY . '-custom_rules'
66
  ) );
67
  }
68
 
@@ -92,7 +92,7 @@ class Instant_Articles_Option_Publishing extends Instant_Articles_Option {
92
  case 'custom_rules':
93
  if ( isset( $field_values['custom_rules_enabled'] ) && $field_values['custom_rules_enabled'] ) {
94
  $custom_rules_json = json_decode( $field_values['custom_rules'] );
95
- if ( $custom_rules_json === null ) {
96
  $field_values['custom_rules'] = $field['default'];
97
  add_settings_error(
98
  'custom_embed',
44
  'render' => 'textarea',
45
  'placeholder' => '{ "rules": [{ "class": "BoldRule", "selector": "span.bold" }, ... ] }',
46
  'description' => 'Read more about <a href="https://github.com/facebook/facebook-instant-articles-sdk-php/blob/master/docs/QuickStart.md#custom-transformer-rules" target="_blank">defining your own custom rules</a> to extend/override the <a href="https://github.com/Automattic/facebook-instant-articles-wp/blob/master/rules-configuration.json" target="_blank">built-in ruleset</a>. If you\'ve defined a common rule which you think this plugin should include by default, <a href="https://github.com/Automattic/facebook-instant-articles-wp/issues/new" target="_blank">tell us about it</a>!',
47
+ 'default' => '',
48
  ),
49
 
50
  );
62
  );
63
  wp_localize_script( 'instant-articles-option-publishing', 'INSTANT_ARTICLES_OPTION_PUBLISHING', array(
64
  'option_field_id_custom_rules_enabled' => self::OPTION_KEY . '-custom_rules_enabled',
65
+ 'option_field_id_custom_rules' => self::OPTION_KEY . '-custom_rules',
66
  ) );
67
  }
68
 
92
  case 'custom_rules':
93
  if ( isset( $field_values['custom_rules_enabled'] ) && $field_values['custom_rules_enabled'] ) {
94
  $custom_rules_json = json_decode( $field_values['custom_rules'] );
95
+ if ( null === $custom_rules_json ) {
96
  $field_values['custom_rules'] = $field['default'];
97
  add_settings_error(
98
  'custom_embed',
settings/class-instant-articles-option.php CHANGED
@@ -176,11 +176,11 @@ class Instant_Articles_Option {
176
  array(
177
  'a' => array(
178
  'href' => array(),
179
- 'target' => array()
180
  ),
181
  'em' => array(),
182
  'p' => array(),
183
- 'strong' => array()
184
  )
185
  )
186
  : '';
@@ -189,7 +189,7 @@ class Instant_Articles_Option {
189
  $this->key,
190
  esc_html( $title ),
191
  function () use ( $description ) {
192
- echo $description;
193
  },
194
  $this->key
195
  );
@@ -291,10 +291,10 @@ class Instant_Articles_Option {
291
  array(
292
  'a' => array(
293
  'href' => array(),
294
- 'target' => array()
295
  ),
296
  'em' => array(),
297
- 'strong' => array()
298
  )
299
  )
300
  : '';
@@ -314,7 +314,7 @@ class Instant_Articles_Option {
314
  />
315
  <?php if ( $field_description ) : ?>
316
  <p class="description">
317
- <?php echo $field_description; ?>
318
  </p>
319
  <?php endif; ?>
320
  <?php
@@ -336,7 +336,7 @@ class Instant_Articles_Option {
336
  </label>
337
  <?php if ( $field_description ) : ?>
338
  <p class="description">
339
- <?php echo $field_description; ?>
340
  </p>
341
  <?php endif; ?>
342
  <?php
@@ -366,7 +366,7 @@ class Instant_Articles_Option {
366
  </select>
367
  <?php if ( $field_description ) : ?>
368
  <p class="description">
369
- <?php echo $field_description; ?>
370
  </p>
371
  <?php endif; ?>
372
  <?php
@@ -383,10 +383,10 @@ class Instant_Articles_Option {
383
  <?php echo esc_attr( $attr_disabled ); ?>
384
  class="large-text code"
385
  rows="8"
386
- ><?php echo esc_html( $option_value ); ?></textarea>
387
  <?php if ( $field_description ) : ?>
388
  <p class="description">
389
- <?php echo $field_description; ?>
390
  </p>
391
  <?php endif; ?>
392
  <?php
@@ -409,7 +409,7 @@ class Instant_Articles_Option {
409
  />
410
  <?php if ( $field_description ) : ?>
411
  <p class="description">
412
- <?php echo $field_description; ?>
413
  </p>
414
  <?php endif; ?>
415
  <?php
176
  array(
177
  'a' => array(
178
  'href' => array(),
179
+ 'target' => array(),
180
  ),
181
  'em' => array(),
182
  'p' => array(),
183
+ 'strong' => array(),
184
  )
185
  )
186
  : '';
189
  $this->key,
190
  esc_html( $title ),
191
  function () use ( $description ) {
192
+ echo esc_html( $description );
193
  },
194
  $this->key
195
  );
291
  array(
292
  'a' => array(
293
  'href' => array(),
294
+ 'target' => array(),
295
  ),
296
  'em' => array(),
297
+ 'strong' => array(),
298
  )
299
  )
300
  : '';
314
  />
315
  <?php if ( $field_description ) : ?>
316
  <p class="description">
317
+ <?php echo esc_html( $field_description ); ?>
318
  </p>
319
  <?php endif; ?>
320
  <?php
336
  </label>
337
  <?php if ( $field_description ) : ?>
338
  <p class="description">
339
+ <?php echo esc_html( $field_description ); ?>
340
  </p>
341
  <?php endif; ?>
342
  <?php
366
  </select>
367
  <?php if ( $field_description ) : ?>
368
  <p class="description">
369
+ <?php echo esc_html( $field_description ); ?>
370
  </p>
371
  <?php endif; ?>
372
  <?php
383
  <?php echo esc_attr( $attr_disabled ); ?>
384
  class="large-text code"
385
  rows="8"
386
+ ><?php echo $args[ 'double_encode' ] ? htmlspecialchars( $option_value ) : esc_html( $option_value ); ?></textarea>
387
  <?php if ( $field_description ) : ?>
388
  <p class="description">
389
+ <?php echo esc_html( $field_description ); ?>
390
  </p>
391
  <?php endif; ?>
392
  <?php
409
  />
410
  <?php if ( $field_description ) : ?>
411
  <p class="description">
412
+ <?php echo esc_html( $field_description ); ?>
413
  </p>
414
  <?php endif; ?>
415
  <?php
settings/class-instant-articles-settings-fb-page.php CHANGED
@@ -24,16 +24,16 @@ class Instant_Articles_Settings_FB_Page implements PersistentDataInterface {
24
  /**
25
  * @inheritdoc
26
  */
27
- public function get( $key )
28
- {
29
  return get_option( $this->session_prefix . $key );
30
  }
31
 
32
  /**
33
  * @inheritdoc
34
  */
35
- public function set( $key, $value )
36
- {
37
  update_option( $this->session_prefix . $key, $value );
38
  }
39
 
@@ -76,7 +76,7 @@ class Instant_Articles_Settings_FB_Page implements PersistentDataInterface {
76
  $this->fb_sdk = new Facebook\Facebook(array(
77
  'app_id' => $app_id,
78
  'app_secret' => $app_secret,
79
- 'default_graph_version' => 'v2.5',
80
  'persistent_data_handler' => $this
81
  ));
82
  }
24
  /**
25
  * @inheritdoc
26
  */
27
+ public function get( $key ) {
28
+
29
  return get_option( $this->session_prefix . $key );
30
  }
31
 
32
  /**
33
  * @inheritdoc
34
  */
35
+ public function set( $key, $value ) {
36
+
37
  update_option( $this->session_prefix . $key, $value );
38
  }
39
 
76
  $this->fb_sdk = new Facebook\Facebook(array(
77
  'app_id' => $app_id,
78
  'app_secret' => $app_secret,
79
+ 'default_graph_version' => 'v2.6',
80
  'persistent_data_handler' => $this
81
  ));
82
  }
settings/class-instant-articles-settings-wizard.php CHANGED
@@ -26,7 +26,7 @@ class Instant_Articles_Settings_Wizard {
26
  private static $steps = array(
27
  1 => self::STEP_ID_APP_SETUP,
28
  2 => self::STEP_ID_PAGE_SELECTION,
29
- 2 => self::STEP_ID_DONE
30
  );
31
 
32
  /**
26
  private static $steps = array(
27
  1 => self::STEP_ID_APP_SETUP,
28
  2 => self::STEP_ID_PAGE_SELECTION,
29
+ 2 => self::STEP_ID_DONE,
30
  );
31
 
32
  /**
settings/template-settings-advanced.php CHANGED
@@ -7,7 +7,7 @@
7
  * @package default
8
  */
9
 
10
- ?>
11
  <form method="post" action="options.php">
12
  <?php settings_fields( Instant_Articles_Option::PAGE_OPTION_GROUP ); ?>
13
 
7
  * @package default
8
  */
9
 
10
+ ?>
11
  <form method="post" action="options.php">
12
  <?php settings_fields( Instant_Articles_Option::PAGE_OPTION_GROUP ); ?>
13
 
settings/template-settings-info.php CHANGED
@@ -6,14 +6,14 @@
6
  *
7
  * @package default
8
  */
9
- ?>
10
- <p>
11
  Once you've activated this WordPress plugin, set up your Instant Articles and submit them to Facebook for a one-time review. The review is required before you can begin publishing. Follow these steps to get started:
12
  </p>
13
  <ol>
14
  <li><a href="https://www.facebook.com/instant_articles/signup" target="_blank">Sign up</a> for Instant Articles, if you haven't already, and come back to activate the plugin using the page you enabled.
15
- <li>Claim the URL you will use to publish articles. Right now, we think the URL you will use to publish to this Page is: <code><?php echo esc_url(home_url()); ?></code>.
16
- <?php if ( isset( $fb_page_settings['page_id'] ) && ! empty ( $fb_page_settings['page_id'] ) ) : ?>
17
  Claim your URL
18
  <a
19
  href="https://www.facebook.com/<?php echo esc_attr( $fb_page_settings['page_id'] ); ?>/settings/?tab=instant_articles#URL" target="_blank">here</a>.
@@ -21,13 +21,13 @@
21
  <li>Install the Pages Manager app to preview your articles and styles on <a href="http://itunes.apple.com/app/facebook-pages-manager/id514643583?ls=1&mt=8&ign-mscache=1" target="_blank">iOS</a> or <a href="https://play.google.com/store/apps/details?id=com.facebook.pages.app" target="_blank">Android</a>.
22
  <li>Create a style template for your articles, using the Style Editor. Be sure to provide the name of the template you want to use in the Plugin Configuration settings below.
23
  <li>[Optional] Enable Audience Network, if you choose. Learn more about <a href="https://fbinstantarticles.files.wordpress.com/2016/03/audience-network_wp_instant-articles-2-2-web_self-serve.pdf" target="_blank">Audience Network</a> for Instant Articles.
24
- <?php if ( isset( $fb_page_settings['page_id'] ) && ! empty ( $fb_page_settings['page_id'] ) ) : ?>
25
  Sign up for Audience Network
26
  <a
27
  href="https://www.facebook.com/<?php echo esc_attr( $fb_page_settings['page_id'] ); ?>/settings/?tab=instant_articles#Audience-Network" target="_blank">here</a>.
28
  <?php endif; ?>
29
  <li>[Optional] Set up your ads and analytics, including Audience Network, in the Configuration area, below.
30
- <?php if ( isset( $fb_page_settings['page_id'] ) && ! empty ( $fb_page_settings['page_id'] ) ) : ?>
31
  <li>
32
  <a
33
  href="https://www.facebook.com/<?php echo esc_attr( $fb_page_settings['page_id'] ); ?>/settings/?tab=instant_articles#Setup-Step2" target="_blank">Submit your articles for review</a>.
@@ -42,7 +42,7 @@
42
  <ol>
43
  <li>See the Instant Articles <a href="https://developers.facebook.com/docs/instant-articles" target="_blank">documentation</a> to answer any questions you might have about Instant Articles.
44
  <li>Check out the Instant Articles <a href="https://developers.facebook.com/ia/blog/" target="_blank">blog</a> and sign up to receive notifications of important updates.
45
- <?php if ( isset( $fb_page_settings['page_id'] ) && ! empty ( $fb_page_settings['page_id'] ) ) : ?>
46
  <li>
47
  To give other members of your team access to your Instant Articles
48
  <a
6
  *
7
  * @package default
8
  */
9
+ ?>
10
+ <p>
11
  Once you've activated this WordPress plugin, set up your Instant Articles and submit them to Facebook for a one-time review. The review is required before you can begin publishing. Follow these steps to get started:
12
  </p>
13
  <ol>
14
  <li><a href="https://www.facebook.com/instant_articles/signup" target="_blank">Sign up</a> for Instant Articles, if you haven't already, and come back to activate the plugin using the page you enabled.
15
+ <li>Claim the URL you will use to publish articles. Right now, we think the URL you will use to publish to this Page is: <code><?php echo esc_url( home_url() ); ?></code>.
16
+ <?php if ( isset( $fb_page_settings['page_id'] ) && ! empty( $fb_page_settings['page_id'] ) ) : ?>
17
  Claim your URL
18
  <a
19
  href="https://www.facebook.com/<?php echo esc_attr( $fb_page_settings['page_id'] ); ?>/settings/?tab=instant_articles#URL" target="_blank">here</a>.
21
  <li>Install the Pages Manager app to preview your articles and styles on <a href="http://itunes.apple.com/app/facebook-pages-manager/id514643583?ls=1&mt=8&ign-mscache=1" target="_blank">iOS</a> or <a href="https://play.google.com/store/apps/details?id=com.facebook.pages.app" target="_blank">Android</a>.
22
  <li>Create a style template for your articles, using the Style Editor. Be sure to provide the name of the template you want to use in the Plugin Configuration settings below.
23
  <li>[Optional] Enable Audience Network, if you choose. Learn more about <a href="https://fbinstantarticles.files.wordpress.com/2016/03/audience-network_wp_instant-articles-2-2-web_self-serve.pdf" target="_blank">Audience Network</a> for Instant Articles.
24
+ <?php if ( isset( $fb_page_settings['page_id'] ) && ! empty( $fb_page_settings['page_id'] ) ) : ?>
25
  Sign up for Audience Network
26
  <a
27
  href="https://www.facebook.com/<?php echo esc_attr( $fb_page_settings['page_id'] ); ?>/settings/?tab=instant_articles#Audience-Network" target="_blank">here</a>.
28
  <?php endif; ?>
29
  <li>[Optional] Set up your ads and analytics, including Audience Network, in the Configuration area, below.
30
+ <?php if ( isset( $fb_page_settings['page_id'] ) && ! empty( $fb_page_settings['page_id'] ) ) : ?>
31
  <li>
32
  <a
33
  href="https://www.facebook.com/<?php echo esc_attr( $fb_page_settings['page_id'] ); ?>/settings/?tab=instant_articles#Setup-Step2" target="_blank">Submit your articles for review</a>.
42
  <ol>
43
  <li>See the Instant Articles <a href="https://developers.facebook.com/docs/instant-articles" target="_blank">documentation</a> to answer any questions you might have about Instant Articles.
44
  <li>Check out the Instant Articles <a href="https://developers.facebook.com/ia/blog/" target="_blank">blog</a> and sign up to receive notifications of important updates.
45
+ <?php if ( isset( $fb_page_settings['page_id'] ) && ! empty( $fb_page_settings['page_id'] ) ) : ?>
46
  <li>
47
  To give other members of your team access to your Instant Articles
48
  <a
settings/template-settings-wizard.php CHANGED
@@ -7,7 +7,7 @@
7
  * @package default
8
  */
9
 
10
- if ( Instant_Articles_Settings_Wizard::get_current_step_id() === 'done' ) : ?>
11
 
12
  <p><strong>Success! Your Instant Articles plugin has been activated.</strong></p>
13
 
@@ -20,8 +20,8 @@
20
  echo esc_html( $fb_app_settings['app_id'] );
21
  ?></a>.
22
 
23
- <?php settings_fields( Instant_Articles_Option::PAGE_OPTION_GROUP_WIZARD ); ?>
24
- <?php submit_button( __( 'Update' ), 'default', 'submit', false ); ?>
25
  </p>
26
  </form>
27
 
@@ -29,15 +29,15 @@
29
  <p>
30
  Your page is
31
  <a
32
- href="http://facebook.com/<?php echo esc_attr( $fb_page_settings['page_id'] ); ?>"
33
- target="_blank"><?php
34
  echo esc_html( $fb_page_settings['page_name'] );
35
  ?></a>.
36
- <?php settings_fields( Instant_Articles_Option::PAGE_OPTION_GROUP_WIZARD ); ?>
37
- <?php submit_button( __( 'Update' ), 'default', 'submit', false ); ?>
38
- <div style="display: none">
39
- <?php do_settings_sections( Instant_Articles_Option_FB_App::OPTION_KEY ); ?>
40
- </div>
41
  </p>
42
  </form>
43
 
@@ -142,7 +142,7 @@
142
  'page_id' => $page_node->getField( 'id' ),
143
  'page_name' => $page_node->getField( 'name' ),
144
  'page_access_token' => $page_node->getField( 'access_token' ),
145
- 'supports_instant_articles' => $page_node->getField( 'supports_instant_articles' )
146
  );
147
  }, $helper->getPagesAndTokens( $access_token )->all() );
148
 
@@ -151,13 +151,13 @@
151
  } );
152
  ?>
153
 
154
- <?php if ( ! empty ( $pages_and_tokens ) ) : ?>
155
  <p>Select the Facebook Pages where you will publish Instant Articles:</p>
156
 
157
  <select id="<?php echo esc_attr( 'instant-articles-fb-page-selector' ) ?>">
158
  <option value="" disabled selected>Select Page</option>
159
  <?php foreach ( $pages_and_tokens as $page ) : ?>
160
- <option value="<?php echo esc_attr( json_encode( $page ) ) ?>">
161
  <?php echo esc_html( $page->page_name ) ?>
162
  </option>
163
  <?php endforeach; ?>
7
  * @package default
8
  */
9
 
10
+ if ( Instant_Articles_Settings_Wizard::get_current_step_id() === 'done' ) : ?>
11
 
12
  <p><strong>Success! Your Instant Articles plugin has been activated.</strong></p>
13
 
20
  echo esc_html( $fb_app_settings['app_id'] );
21
  ?></a>.
22
 
23
+ <?php settings_fields( Instant_Articles_Option::PAGE_OPTION_GROUP_WIZARD ); ?>
24
+ <?php submit_button( __( 'Update' ), 'default', 'submit', false ); ?>
25
  </p>
26
  </form>
27
 
29
  <p>
30
  Your page is
31
  <a
32
+ href="http://facebook.com/<?php echo esc_attr( $fb_page_settings['page_id'] ); ?>"
33
+ target="_blank"><?php
34
  echo esc_html( $fb_page_settings['page_name'] );
35
  ?></a>.
36
+ <?php settings_fields( Instant_Articles_Option::PAGE_OPTION_GROUP_WIZARD ); ?>
37
+ <?php submit_button( __( 'Update' ), 'default', 'submit', false ); ?>
38
+ <div style="display: none">
39
+ <?php do_settings_sections( Instant_Articles_Option_FB_App::OPTION_KEY ); ?>
40
+ </div>
41
  </p>
42
  </form>
43
 
142
  'page_id' => $page_node->getField( 'id' ),
143
  'page_name' => $page_node->getField( 'name' ),
144
  'page_access_token' => $page_node->getField( 'access_token' ),
145
+ 'supports_instant_articles' => $page_node->getField( 'supports_instant_articles' ),
146
  );
147
  }, $helper->getPagesAndTokens( $access_token )->all() );
148
 
151
  } );
152
  ?>
153
 
154
+ <?php if ( ! empty( $pages_and_tokens ) ) : ?>
155
  <p>Select the Facebook Pages where you will publish Instant Articles:</p>
156
 
157
  <select id="<?php echo esc_attr( 'instant-articles-fb-page-selector' ) ?>">
158
  <option value="" disabled selected>Select Page</option>
159
  <?php foreach ( $pages_and_tokens as $page ) : ?>
160
+ <option value="<?php echo esc_attr( wp_json_encode( $page ) ) ?>">
161
  <?php echo esc_html( $page->page_name ) ?>
162
  </option>
163
  <?php endforeach; ?>
shortcodes.php DELETED
@@ -1,254 +0,0 @@
1
- <?php
2
-
3
- add_shortcode( 'gallery', 'instant_articles_shortcode_handler_gallery' );
4
-
5
- /**
6
- * Gallery Shortcode. Based on the built in gallery shortcode
7
- * @param array $attr Array of attributes passed to shortcode.
8
- * @return string The generated content.
9
- */
10
- function instant_articles_shortcode_handler_gallery( $attr ) {
11
-
12
- $post = get_post();
13
-
14
- if ( ! empty( $attr['ids'] ) ) {
15
- // 'ids' is explicitly ordered, unless you specify otherwise.
16
- if ( empty( $attr['orderby'] ) ) {
17
- $attr['orderby'] = 'post__in';
18
- }
19
- $attr['include'] = $attr['ids'];
20
- }
21
-
22
- $atts = shortcode_atts( array(
23
- 'id' => $post ? $post->ID : 0,
24
- 'order' => 'ASC',
25
- 'orderby' => 'menu_order ID',
26
- 'include' => '',
27
- 'exclude' => '',
28
- ), $attr, 'gallery' );
29
-
30
- $id = intval( $atts['id'] );
31
-
32
- if ( ! empty( $atts['include'] ) ) {
33
- $include = explode( ',', $atts['include'] );
34
-
35
- $attachments = new WP_Query( array(
36
- 'post__in' => $include,
37
- 'post_status' => 'inherit',
38
- 'post_type' => 'attachment',
39
- 'post_mime_type' => 'image',
40
- 'order' => $atts['order'],
41
- 'orderby' => $atts['orderby']
42
- ) );
43
- } elseif ( ! empty( $atts['exclude'] ) ) {
44
- $exclude = explode( ',', $atts['exclude'] );
45
-
46
- $attachments = new WP_Query( array(
47
- 'post_parent' => $id,
48
- 'post__not_in' => $exclude,
49
- 'post_status' => 'inherit',
50
- 'post_type' => 'attachment',
51
- 'post_mime_type' => 'image',
52
- 'order' => $atts['order'],
53
- 'orderby' => $atts['orderby']
54
- ) );
55
- } else {
56
- $attachments = new WP_Query( array(
57
- 'post_parent' => $id,
58
- 'post_status' => 'inherit',
59
- 'post_type' => 'attachment',
60
- 'post_mime_type' => 'image',
61
- 'order' => $atts['order'],
62
- 'orderby' => $atts['orderby']
63
- ) );
64
- }
65
-
66
- $output = '';
67
-
68
- if ( $attachments->have_posts() ) {
69
- $output = '<figure class="op-slideshow">';
70
-
71
- while ( $attachments->have_posts() ) {
72
- $attachments->the_post();
73
-
74
- $image_src = wp_get_attachment_image_src( get_the_ID(), 'large' );
75
-
76
- if ( $image_src ) {
77
- $output .= '<figure>';
78
- $output .= '<img src="' . esc_url( $image_src[0] ) . '" alt="' . esc_attr( get_the_title() ) . '">';
79
-
80
- $caption = wp_strip_all_tags( $attachments->post->post_excerpt, true );
81
- if ( $caption ) {
82
- $output .= '<figcaption>' . esc_html( $caption ) . '</figcaption>';
83
- }
84
- $output .= '</figure>';
85
- }
86
- }
87
-
88
- $output .= '</figure>';
89
- }
90
-
91
- wp_reset_postdata();
92
-
93
- return $output;
94
- }
95
-
96
-
97
- add_shortcode( 'caption', 'instant_articles_shortcode_handler_caption' );
98
- add_shortcode( 'wp_caption', 'instant_articles_shortcode_handler_caption' );
99
-
100
- /**
101
- * Caption/WP-Caption Shortcode. Based on the built in caption shortcode
102
- * @param array $attr Array of attributes passed to shortcode.
103
- * @param string $content The content passed to the shortcode.
104
- * @return string $output The generated content.
105
- */
106
- function instant_articles_shortcode_handler_caption( $attr, $content = null ) {
107
- // New-style shortcode with the caption inside the shortcode with the link and image tags.
108
- if ( ! isset( $attr['caption'] ) ) {
109
- if ( preg_match( '#((?:<a [^>]+>\s*)?<img [^>]+>(?:\s*</a>)?)(.*)#is', $content, $matches ) ) {
110
- $content = $matches[1];
111
- $attr['caption'] = trim( $matches[2] );
112
- }
113
- }
114
-
115
- $atts = shortcode_atts( array(
116
- 'figcaptionclass' => '',
117
- 'caption' => '',
118
- 'cite' => '',
119
- 'subtitle' => '',
120
- ), $attr, 'caption' );
121
-
122
- if ( ! strlen( trim( $atts['caption'] ) ) ) {
123
- return '';
124
- }
125
-
126
- $output = '';
127
-
128
- $content = do_shortcode( $content );
129
-
130
- $doc = new DOMDocument();
131
- $doc->loadHTML( '<html><body>' . $content . '</body></html>' );
132
- $imgs = $doc->getElementsByTagName( 'img' );
133
-
134
- if ( $imgs->length > 0 ) {
135
- $img_src = $imgs->item(0)->getAttribute( 'src' );
136
- if ( $img_src ) {
137
-
138
- $alt = $imgs->item(0)->getAttribute( 'alt' );
139
-
140
- $classes = array();
141
- $classes = trim( $atts['figcaptionclass'] );
142
- $class_attr = ( strlen( $classes ) ) ? ' class="' . esc_attr( $classes ) . '"' : '';
143
-
144
- $caption = wp_strip_all_tags( $atts['caption'], true );
145
-
146
- $subtitle = ( strlen( $atts['subtitle'] ) ) ? '<h2>' . esc_html( $atts['subtitle'] ) . '</h2>' : '';
147
- $cite = ( strlen( $atts['cite'] ) ) ? '<cite>' . esc_html( $atts['cite'] ) . '</cite>' : '';
148
-
149
- $output = '<figure><img src="' . esc_url( $img_src ) . '" alt="' . esc_attr( $alt ) . '"><figcaption' . $class_attr . '><h1>' . esc_html( $caption ) . '</h1>' . $subtitle . $cite . '</figcaption></figure>';
150
- }
151
- }
152
-
153
- return $output;
154
- }
155
-
156
-
157
- add_shortcode( 'audio', 'instant_articles_shortcode_handler_audio' );
158
-
159
- /**
160
- * Audio Shortcode
161
- * @param array $atts Array of attributes passed to shortcode.
162
- * @return string The generated content.
163
- */
164
- function instant_articles_shortcode_handler_audio( $atts ) {
165
-
166
- if ( $atts['mp3'] ) {
167
- $audio_src = $atts['mp3'];
168
- } else if ( $atts['src'] ) {
169
- $audio_src = $atts['src'];
170
- } else if ( $atts['ogg'] ) {
171
- $audio_src = $atts['ogg'];
172
- } else if ( $atts['wav'] ) {
173
- $audio_src = $atts['wav'];
174
- } else {
175
- $audio_src = null;
176
- }
177
-
178
- if ( $audio_src ) :
179
- $file_url = array_reverse( explode( '/', $audio_src ) ) ;
180
-
181
- return '<figure><audio title="' . esc_html( $file_url[0] ) . '"><source src="' . esc_url( $audio_src ) .'"></audio></figure>';
182
-
183
- endif;
184
-
185
- }
186
-
187
- add_shortcode( 'video', 'instant_articles_shortcode_handler_video' );
188
-
189
- /**
190
- * Video Shortcode
191
- * @param array $atts Array of attributes passed to shortcode.
192
- * @return string The generated content.
193
- */
194
- function instant_articles_shortcode_handler_video( $atts ) {
195
-
196
- if ( $atts['mp4'] ) {
197
- $video_src = $atts['mp4'];
198
- $type = 'mp4';
199
- } else if ( $atts['src'] ) {
200
- $video_src = $atts['src'];
201
- $file_src_array = array_reverse( explode( '.', $video_src ) ) ;
202
- $type = $file_src_array[0];
203
- } else if ( $atts['ogv'] ) {
204
- $video_src = $atts['ogv'];
205
- $type = 'ogv';
206
- } else if ( $atts['webm'] ) {
207
- $video_src = $atts['webm'];
208
- $type = 'webm';
209
- } else {
210
- $video_src = null;
211
- }
212
-
213
- if ( $video_src ) :
214
-
215
- return '<figure><video><source src="' . esc_url( $video_src ) . '" type="video/' . esc_html( $type ) . '" /></video></figure>';
216
-
217
- endif;
218
- }
219
-
220
- add_shortcode( 'playlist', 'instant_articles_shortcode_handler_playlist' );
221
- /**
222
- * Playlist Shortcode
223
- * @param array $atts Array of attributes passed to shortcode.
224
- * @return string The generated content.
225
- */
226
- function instant_articles_shortcode_handler_playlist( $atts ) {
227
-
228
- if ( ! is_array( $atts ) || ! array_key_exists( 'ids', $atts ) ) {
229
- return '';
230
- }
231
-
232
- $ids = explode( ',', $atts['ids'] );
233
-
234
- $output = '<figure>';
235
-
236
- if ( isset( $atts['type'] ) && 'video' === $atts['type'] ) :
237
- foreach ($ids as $id) {
238
- $extension = wp_check_filetype( wp_get_attachment_url( $id ) );
239
- if ( is_array( $extension ) && array_key_exists( 'ext', $extension ) && false !== $extension['ext'] ) {
240
- $output .= '<video><source src="' . wp_get_attachment_url( $id ) . '" type="video/' . $extension['ext'] .'" /></video>';
241
- }
242
- }
243
- else :
244
- foreach ($ids as $id) {
245
- $output .= '<audio title="' . basename( get_attached_file( $id ) ) . '"><source src="' . wp_get_attachment_url( $id ) . '"></audio>';
246
- }
247
- endif;
248
-
249
- $output .= '</figure>';
250
-
251
- return $output;
252
- }
253
-
254
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer' . '/autoload_real.php';
6
 
7
- return ComposerAutoloaderInite7aef46e213cc4ff326adce2c422ab9d::getLoader();
4
 
5
  require_once __DIR__ . '/composer' . '/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInit337744729a91b1fdea5f68820e3d1dfe::getLoader();
vendor/composer/autoload_files.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_files.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ '7e702cccdb9dd904f2ccf22e5f37abae' => $vendorDir . '/facebook/php-sdk-v4/src/Facebook/polyfills.php',
10
+ );
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInite7aef46e213cc4ff326adce2c422ab9d
6
  {
7
  private static $loader;
8
 
@@ -19,27 +19,52 @@ class ComposerAutoloaderInite7aef46e213cc4ff326adce2c422ab9d
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInite7aef46e213cc4ff326adce2c422ab9d', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInite7aef46e213cc4ff326adce2c422ab9d', 'loadClassLoader'));
25
 
26
- $map = require __DIR__ . '/autoload_namespaces.php';
27
- foreach ($map as $namespace => $path) {
28
- $loader->set($namespace, $path);
29
- }
30
 
31
- $map = require __DIR__ . '/autoload_psr4.php';
32
- foreach ($map as $namespace => $path) {
33
- $loader->setPsr4($namespace, $path);
34
- }
 
 
 
 
 
 
 
35
 
36
- $classMap = require __DIR__ . '/autoload_classmap.php';
37
- if ($classMap) {
38
- $loader->addClassMap($classMap);
 
39
  }
40
 
41
  $loader->register(true);
42
 
 
 
 
 
 
 
 
 
 
43
  return $loader;
44
  }
45
  }
 
 
 
 
 
 
 
 
 
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInit337744729a91b1fdea5f68820e3d1dfe
6
  {
7
  private static $loader;
8
 
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInit337744729a91b1fdea5f68820e3d1dfe', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit337744729a91b1fdea5f68820e3d1dfe', 'loadClassLoader'));
25
 
26
+ $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION');
27
+ if ($useStaticLoader) {
28
+ require_once __DIR__ . '/autoload_static.php';
 
29
 
30
+ call_user_func(\Composer\Autoload\ComposerStaticInit337744729a91b1fdea5f68820e3d1dfe::getInitializer($loader));
31
+ } else {
32
+ $map = require __DIR__ . '/autoload_namespaces.php';
33
+ foreach ($map as $namespace => $path) {
34
+ $loader->set($namespace, $path);
35
+ }
36
+
37
+ $map = require __DIR__ . '/autoload_psr4.php';
38
+ foreach ($map as $namespace => $path) {
39
+ $loader->setPsr4($namespace, $path);
40
+ }
41
 
42
+ $classMap = require __DIR__ . '/autoload_classmap.php';
43
+ if ($classMap) {
44
+ $loader->addClassMap($classMap);
45
+ }
46
  }
47
 
48
  $loader->register(true);
49
 
50
+ if ($useStaticLoader) {
51
+ $includeFiles = Composer\Autoload\ComposerStaticInit337744729a91b1fdea5f68820e3d1dfe::$files;
52
+ } else {
53
+ $includeFiles = require __DIR__ . '/autoload_files.php';
54
+ }
55
+ foreach ($includeFiles as $fileIdentifier => $file) {
56
+ composerRequire337744729a91b1fdea5f68820e3d1dfe($fileIdentifier, $file);
57
+ }
58
+
59
  return $loader;
60
  }
61
  }
62
+
63
+ function composerRequire337744729a91b1fdea5f68820e3d1dfe($fileIdentifier, $file)
64
+ {
65
+ if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
66
+ require $file;
67
+
68
+ $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
69
+ }
70
+ }
vendor/composer/autoload_static.php ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_static.php @generated by Composer
4
+
5
+ namespace Composer\Autoload;
6
+
7
+ class ComposerStaticInit337744729a91b1fdea5f68820e3d1dfe
8
+ {
9
+ public static $files = array (
10
+ '7e702cccdb9dd904f2ccf22e5f37abae' => __DIR__ . '/..' . '/facebook/php-sdk-v4/src/Facebook/polyfills.php',
11
+ );
12
+
13
+ public static $prefixLengthsPsr4 = array (
14
+ 'S' =>
15
+ array (
16
+ 'Symfony\\Component\\CssSelector\\' => 30,
17
+ ),
18
+ 'F' =>
19
+ array (
20
+ 'Facebook\\InstantArticles\\' => 25,
21
+ 'Facebook\\' => 9,
22
+ ),
23
+ );
24
+
25
+ public static $prefixDirsPsr4 = array (
26
+ 'Symfony\\Component\\CssSelector\\' =>
27
+ array (
28
+ 0 => __DIR__ . '/..' . '/symfony/css-selector',
29
+ ),
30
+ 'Facebook\\InstantArticles\\' =>
31
+ array (
32
+ 0 => __DIR__ . '/..' . '/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles',
33
+ ),
34
+ 'Facebook\\' =>
35
+ array (
36
+ 0 => __DIR__ . '/..' . '/facebook/php-sdk-v4/src/Facebook',
37
+ ),
38
+ );
39
+
40
+ public static $classMap = array (
41
+ 'Logger' => __DIR__ . '/..' . '/apache/log4php/src/main/php/Logger.php',
42
+ 'LoggerAppender' => __DIR__ . '/..' . '/apache/log4php/src/main/php/LoggerAppender.php',
43
+ 'LoggerAppenderConsole' => __DIR__ . '/..' . '/apache/log4php/src/main/php/appenders/LoggerAppenderConsole.php',
44
+ 'LoggerAppenderDailyFile' => __DIR__ . '/..' . '/apache/log4php/src/main/php/appenders/LoggerAppenderDailyFile.php',
45
+ 'LoggerAppenderEcho' => __DIR__ . '/..' . '/apache/log4php/src/main/php/appenders/LoggerAppenderEcho.php',
46
+ 'LoggerAppenderFile' => __DIR__ . '/..' . '/apache/log4php/src/main/php/appenders/LoggerAppenderFile.php',
47
+ 'LoggerAppenderFirePHP' => __DIR__ . '/..' . '/apache/log4php/src/main/php/appenders/LoggerAppenderFirePHP.php',
48
+ 'LoggerAppenderMail' => __DIR__ . '/..' . '/apache/log4php/src/main/php/appenders/LoggerAppenderMail.php',
49
+ 'LoggerAppenderMailEvent' => __DIR__ . '/..' . '/apache/log4php/src/main/php/appenders/LoggerAppenderMailEvent.php',
50
+ 'LoggerAppenderMongoDB' => __DIR__ . '/..' . '/apache/log4php/src/main/php/appenders/LoggerAppenderMongoDB.php',
51
+ 'LoggerAppenderNull' => __DIR__ . '/..' . '/apache/log4php/src/main/php/appenders/LoggerAppenderNull.php',
52
+ 'LoggerAppenderPDO' => __DIR__ . '/..' . '/apache/log4php/src/main/php/appenders/LoggerAppenderPDO.php',
53
+ 'LoggerAppenderPhp' => __DIR__ . '/..' . '/apache/log4php/src/main/php/appenders/LoggerAppenderPhp.php',
54
+ 'LoggerAppenderPool' => __DIR__ . '/..' . '/apache/log4php/src/main/php/LoggerAppenderPool.php',
55
+ 'LoggerAppenderRollingFile' => __DIR__ . '/..' . '/apache/log4php/src/main/php/appenders/LoggerAppenderRollingFile.php',
56
+ 'LoggerAppenderSocket' => __DIR__ . '/..' . '/apache/log4php/src/main/php/appenders/LoggerAppenderSocket.php',
57
+ 'LoggerAppenderSyslog' => __DIR__ . '/..' . '/apache/log4php/src/main/php/appenders/LoggerAppenderSyslog.php',
58
+ 'LoggerAutoloader' => __DIR__ . '/..' . '/apache/log4php/src/main/php/LoggerAutoloader.php',
59
+ 'LoggerConfigurable' => __DIR__ . '/..' . '/apache/log4php/src/main/php/LoggerConfigurable.php',
60
+ 'LoggerConfigurationAdapter' => __DIR__ . '/..' . '/apache/log4php/src/main/php/configurators/LoggerConfigurationAdapter.php',
61
+ 'LoggerConfigurationAdapterINI' => __DIR__ . '/..' . '/apache/log4php/src/main/php/configurators/LoggerConfigurationAdapterINI.php',
62
+ 'LoggerConfigurationAdapterPHP' => __DIR__ . '/..' . '/apache/log4php/src/main/php/configurators/LoggerConfigurationAdapterPHP.php',
63
+ 'LoggerConfigurationAdapterXML' => __DIR__ . '/..' . '/apache/log4php/src/main/php/configurators/LoggerConfigurationAdapterXML.php',
64
+ 'LoggerConfigurator' => __DIR__ . '/..' . '/apache/log4php/src/main/php/LoggerConfigurator.php',
65
+ 'LoggerConfiguratorDefault' => __DIR__ . '/..' . '/apache/log4php/src/main/php/configurators/LoggerConfiguratorDefault.php',
66
+ 'LoggerException' => __DIR__ . '/..' . '/apache/log4php/src/main/php/LoggerException.php',
67
+ 'LoggerFilter' => __DIR__ . '/..' . '/apache/log4php/src/main/php/LoggerFilter.php',
68
+ 'LoggerFilterDenyAll' => __DIR__ . '/..' . '/apache/log4php/src/main/php/filters/LoggerFilterDenyAll.php',
69
+ 'LoggerFilterLevelMatch' => __DIR__ . '/..' . '/apache/log4php/src/main/php/filters/LoggerFilterLevelMatch.php',
70
+ 'LoggerFilterLevelRange' => __DIR__ . '/..' . '/apache/log4php/src/main/php/filters/LoggerFilterLevelRange.php',
71
+ 'LoggerFilterStringMatch' => __DIR__ . '/..' . '/apache/log4php/src/main/php/filters/LoggerFilterStringMatch.php',
72
+ 'LoggerFormattingInfo' => __DIR__ . '/..' . '/apache/log4php/src/main/php/helpers/LoggerFormattingInfo.php',
73
+ 'LoggerHierarchy' => __DIR__ . '/..' . '/apache/log4php/src/main/php/LoggerHierarchy.php',
74
+ 'LoggerLayout' => __DIR__ . '/..' . '/apache/log4php/src/main/php/LoggerLayout.php',
75
+ 'LoggerLayoutHtml' => __DIR__ . '/..' . '/apache/log4php/src/main/php/layouts/LoggerLayoutHtml.php',
76
+ 'LoggerLayoutPattern' => __DIR__ . '/..' . '/apache/log4php/src/main/php/layouts/LoggerLayoutPattern.php',
77
+ 'LoggerLayoutSerialized' => __DIR__ . '/..' . '/apache/log4php/src/main/php/layouts/LoggerLayoutSerialized.php',
78
+ 'LoggerLayoutSimple' => __DIR__ . '/..' . '/apache/log4php/src/main/php/layouts/LoggerLayoutSimple.php',
79
+ 'LoggerLayoutTTCC' => __DIR__ . '/..' . '/apache/log4php/src/main/php/layouts/LoggerLayoutTTCC.php',
80
+ 'LoggerLayoutXml' => __DIR__ . '/..' . '/apache/log4php/src/main/php/layouts/LoggerLayoutXml.php',
81
+ 'LoggerLevel' => __DIR__ . '/..' . '/apache/log4php/src/main/php/LoggerLevel.php',
82
+ 'LoggerLocationInfo' => __DIR__ . '/..' . '/apache/log4php/src/main/php/LoggerLocationInfo.php',
83
+ 'LoggerLoggingEvent' => __DIR__ . '/..' . '/apache/log4php/src/main/php/LoggerLoggingEvent.php',
84
+ 'LoggerMDC' => __DIR__ . '/..' . '/apache/log4php/src/main/php/LoggerMDC.php',
85
+ 'LoggerNDC' => __DIR__ . '/..' . '/apache/log4php/src/main/php/LoggerNDC.php',
86
+ 'LoggerOptionConverter' => __DIR__ . '/..' . '/apache/log4php/src/main/php/helpers/LoggerOptionConverter.php',
87
+ 'LoggerPatternConverter' => __DIR__ . '/..' . '/apache/log4php/src/main/php/pattern/LoggerPatternConverter.php',
88
+ 'LoggerPatternConverterClass' => __DIR__ . '/..' . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterClass.php',
89
+ 'LoggerPatternConverterCookie' => __DIR__ . '/..' . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterCookie.php',
90
+ 'LoggerPatternConverterDate' => __DIR__ . '/..' . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterDate.php',
91
+ 'LoggerPatternConverterEnvironment' => __DIR__ . '/..' . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterEnvironment.php',
92
+ 'LoggerPatternConverterFile' => __DIR__ . '/..' . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterFile.php',
93
+ 'LoggerPatternConverterLevel' => __DIR__ . '/..' . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterLevel.php',
94
+ 'LoggerPatternConverterLine' => __DIR__ . '/..' . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterLine.php',
95
+ 'LoggerPatternConverterLiteral' => __DIR__ . '/..' . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterLiteral.php',
96
+ 'LoggerPatternConverterLocation' => __DIR__ . '/..' . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterLocation.php',
97
+ 'LoggerPatternConverterLogger' => __DIR__ . '/..' . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterLogger.php',
98
+ 'LoggerPatternConverterMDC' => __DIR__ . '/..' . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterMDC.php',
99
+ 'LoggerPatternConverterMessage' => __DIR__ . '/..' . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterMessage.php',
100
+ 'LoggerPatternConverterMethod' => __DIR__ . '/..' . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterMethod.php',
101
+ 'LoggerPatternConverterNDC' => __DIR__ . '/..' . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterNDC.php',
102
+ 'LoggerPatternConverterNewLine' => __DIR__ . '/..' . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterNewLine.php',
103
+ 'LoggerPatternConverterProcess' => __DIR__ . '/..' . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterProcess.php',
104
+ 'LoggerPatternConverterRelative' => __DIR__ . '/..' . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterRelative.php',
105
+ 'LoggerPatternConverterRequest' => __DIR__ . '/..' . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterRequest.php',
106
+ 'LoggerPatternConverterServer' => __DIR__ . '/..' . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterServer.php',
107
+ 'LoggerPatternConverterSession' => __DIR__ . '/..' . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterSession.php',
108
+ 'LoggerPatternConverterSessionID' => __DIR__ . '/..' . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterSessionID.php',
109
+ 'LoggerPatternConverterSuperglobal' => __DIR__ . '/..' . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterSuperglobal.php',
110
+ 'LoggerPatternConverterThrowable' => __DIR__ . '/..' . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterThrowable.php',
111
+ 'LoggerPatternParser' => __DIR__ . '/..' . '/apache/log4php/src/main/php/helpers/LoggerPatternParser.php',
112
+ 'LoggerReflectionUtils' => __DIR__ . '/..' . '/apache/log4php/src/main/php/LoggerReflectionUtils.php',
113
+ 'LoggerRenderer' => __DIR__ . '/..' . '/apache/log4php/src/main/php/renderers/LoggerRenderer.php',
114
+ 'LoggerRendererDefault' => __DIR__ . '/..' . '/apache/log4php/src/main/php/renderers/LoggerRendererDefault.php',
115
+ 'LoggerRendererException' => __DIR__ . '/..' . '/apache/log4php/src/main/php/renderers/LoggerRendererException.php',
116
+ 'LoggerRendererMap' => __DIR__ . '/..' . '/apache/log4php/src/main/php/renderers/LoggerRendererMap.php',
117
+ 'LoggerRoot' => __DIR__ . '/..' . '/apache/log4php/src/main/php/LoggerRoot.php',
118
+ 'LoggerThrowableInformation' => __DIR__ . '/..' . '/apache/log4php/src/main/php/LoggerThrowableInformation.php',
119
+ 'LoggerUtils' => __DIR__ . '/..' . '/apache/log4php/src/main/php/helpers/LoggerUtils.php',
120
+ );
121
+
122
+ public static function getInitializer(ClassLoader $loader)
123
+ {
124
+ return \Closure::bind(function () use ($loader) {
125
+ $loader->prefixLengthsPsr4 = ComposerStaticInit337744729a91b1fdea5f68820e3d1dfe::$prefixLengthsPsr4;
126
+ $loader->prefixDirsPsr4 = ComposerStaticInit337744729a91b1fdea5f68820e3d1dfe::$prefixDirsPsr4;
127
+ $loader->classMap = ComposerStaticInit337744729a91b1fdea5f68820e3d1dfe::$classMap;
128
+
129
+ }, null, ClassLoader::class);
130
+ }
131
+ }
vendor/composer/installed.json CHANGED
@@ -33,22 +33,21 @@
33
  },
34
  {
35
  "name": "facebook/php-sdk-v4",
36
- "version": "5.1.4",
37
- "version_normalized": "5.1.4.0",
38
  "source": {
39
  "type": "git",
40
  "url": "https://github.com/facebook/facebook-php-sdk-v4.git",
41
- "reference": "38fd7187a6704d3ab14ded2f3a534ac4ee6f3481"
42
  },
43
  "dist": {
44
  "type": "zip",
45
- "url": "https://api.github.com/repos/facebook/facebook-php-sdk-v4/zipball/38fd7187a6704d3ab14ded2f3a534ac4ee6f3481",
46
- "reference": "38fd7187a6704d3ab14ded2f3a534ac4ee6f3481",
47
  "shasum": ""
48
  },
49
  "require": {
50
- "ext-mbstring": "*",
51
- "php": ">=5.4.0"
52
  },
53
  "require-dev": {
54
  "guzzlehttp/guzzle": "~5.0",
@@ -58,7 +57,7 @@
58
  "suggest": {
59
  "guzzlehttp/guzzle": "Allows for implementation of the Guzzle HTTP client"
60
  },
61
- "time": "2016-05-13 17:28:30",
62
  "type": "library",
63
  "extra": {
64
  "branch-alias": {
@@ -69,7 +68,10 @@
69
  "autoload": {
70
  "psr-4": {
71
  "Facebook\\": "src/Facebook/"
72
- }
 
 
 
73
  },
74
  "notification-url": "https://packagist.org/downloads/",
75
  "license": [
@@ -90,23 +92,23 @@
90
  },
91
  {
92
  "name": "symfony/css-selector",
93
- "version": "v2.8.6",
94
- "version_normalized": "2.8.6.0",
95
  "source": {
96
  "type": "git",
97
  "url": "https://github.com/symfony/css-selector.git",
98
- "reference": "07b7ced3ae0c12918477c095453ea8595000810e"
99
  },
100
  "dist": {
101
  "type": "zip",
102
- "url": "https://api.github.com/repos/symfony/css-selector/zipball/07b7ced3ae0c12918477c095453ea8595000810e",
103
- "reference": "07b7ced3ae0c12918477c095453ea8595000810e",
104
  "shasum": ""
105
  },
106
  "require": {
107
  "php": ">=5.3.9"
108
  },
109
- "time": "2016-03-04 07:54:35",
110
  "type": "library",
111
  "extra": {
112
  "branch-alias": {
@@ -145,17 +147,17 @@
145
  },
146
  {
147
  "name": "facebook/facebook-instant-articles-sdk-php",
148
- "version": "v1.1.0",
149
- "version_normalized": "1.1.0.0",
150
  "source": {
151
  "type": "git",
152
  "url": "https://github.com/facebook/facebook-instant-articles-sdk-php.git",
153
- "reference": "989a4d887dcd01b7480bbb685b9a6bf94c45b827"
154
  },
155
  "dist": {
156
  "type": "zip",
157
- "url": "https://api.github.com/repos/facebook/facebook-instant-articles-sdk-php/zipball/989a4d887dcd01b7480bbb685b9a6bf94c45b827",
158
- "reference": "989a4d887dcd01b7480bbb685b9a6bf94c45b827",
159
  "shasum": ""
160
  },
161
  "require": {
@@ -169,7 +171,7 @@
169
  "phpunit/phpunit": "^4.8",
170
  "squizlabs/php_codesniffer": "^2.6.0"
171
  },
172
- "time": "2016-05-17 13:59:18",
173
  "type": "library",
174
  "installation-source": "dist",
175
  "autoload": {
33
  },
34
  {
35
  "name": "facebook/php-sdk-v4",
36
+ "version": "5.2.0",
37
+ "version_normalized": "5.2.0.0",
38
  "source": {
39
  "type": "git",
40
  "url": "https://github.com/facebook/facebook-php-sdk-v4.git",
41
+ "reference": "c60fba1fe1de62db1e0776d32fc2fb778189459c"
42
  },
43
  "dist": {
44
  "type": "zip",
45
+ "url": "https://api.github.com/repos/facebook/facebook-php-sdk-v4/zipball/c60fba1fe1de62db1e0776d32fc2fb778189459c",
46
+ "reference": "c60fba1fe1de62db1e0776d32fc2fb778189459c",
47
  "shasum": ""
48
  },
49
  "require": {
50
+ "php": "^5.4|^7.0"
 
51
  },
52
  "require-dev": {
53
  "guzzlehttp/guzzle": "~5.0",
57
  "suggest": {
58
  "guzzlehttp/guzzle": "Allows for implementation of the Guzzle HTTP client"
59
  },
60
+ "time": "2016-05-18 22:04:36",
61
  "type": "library",
62
  "extra": {
63
  "branch-alias": {
68
  "autoload": {
69
  "psr-4": {
70
  "Facebook\\": "src/Facebook/"
71
+ },
72
+ "files": [
73
+ "src/Facebook/polyfills.php"
74
+ ]
75
  },
76
  "notification-url": "https://packagist.org/downloads/",
77
  "license": [
92
  },
93
  {
94
  "name": "symfony/css-selector",
95
+ "version": "v2.8.8",
96
+ "version_normalized": "2.8.8.0",
97
  "source": {
98
  "type": "git",
99
  "url": "https://github.com/symfony/css-selector.git",
100
+ "reference": "9da4c615ba303850986e0480cc472bf704cfdb64"
101
  },
102
  "dist": {
103
  "type": "zip",
104
+ "url": "https://api.github.com/repos/symfony/css-selector/zipball/9da4c615ba303850986e0480cc472bf704cfdb64",
105
+ "reference": "9da4c615ba303850986e0480cc472bf704cfdb64",
106
  "shasum": ""
107
  },
108
  "require": {
109
  "php": ">=5.3.9"
110
  },
111
+ "time": "2016-06-29 05:31:50",
112
  "type": "library",
113
  "extra": {
114
  "branch-alias": {
147
  },
148
  {
149
  "name": "facebook/facebook-instant-articles-sdk-php",
150
+ "version": "v1.3.0",
151
+ "version_normalized": "1.3.0.0",
152
  "source": {
153
  "type": "git",
154
  "url": "https://github.com/facebook/facebook-instant-articles-sdk-php.git",
155
+ "reference": "4b74463f347c49f9592ab35b70129bb15b4b1e6d"
156
  },
157
  "dist": {
158
  "type": "zip",
159
+ "url": "https://api.github.com/repos/facebook/facebook-instant-articles-sdk-php/zipball/4b74463f347c49f9592ab35b70129bb15b4b1e6d",
160
+ "reference": "4b74463f347c49f9592ab35b70129bb15b4b1e6d",
161
  "shasum": ""
162
  },
163
  "require": {
171
  "phpunit/phpunit": "^4.8",
172
  "squizlabs/php_codesniffer": "^2.6.0"
173
  },
174
+ "time": "2016-07-12 00:57:23",
175
  "type": "library",
176
  "installation-source": "dist",
177
  "autoload": {
vendor/facebook/facebook-instant-articles-sdk-php/CONTRIBUTING.md CHANGED
@@ -10,7 +10,7 @@ We accept contributions via pull requests on [GitHub](https://github.com/faceboo
10
 
11
  - **Add tests** - If you've added code that can be tested, add tests.
12
 
13
- - **Document any change in behaviour** - Make sure the README and the [documentation](https://github.com/facebook/facebook-instant-articles-sdk-php/tree/master/docs) are kept up-to-date.
14
 
15
  - **Consider our release cycle** - We try to follow [SemVer](http://semver.org/). Randomly breaking public APIs is not an option.
16
 
10
 
11
  - **Add tests** - If you've added code that can be tested, add tests.
12
 
13
+ - **Document any change in behaviour** - Make sure the README file is updated in your PR. Include any notes for documentation items which needs to be updated on the main [docs on Facebook's Developer site](https://developers.facebook.com/docs/instant-articles/sdk/).
14
 
15
  - **Consider our release cycle** - We try to follow [SemVer](http://semver.org/). Randomly breaking public APIs is not an option.
16
 
vendor/facebook/facebook-instant-articles-sdk-php/README.md CHANGED
@@ -11,7 +11,7 @@ The SDK consists of three components:
11
  - **Client**: A simple wrapper around the [Instant Articles API](https://developers.facebook.com/docs/instant-articles/api), which can be used for publishing Instant Articles on Facebook. The client provides a CRUD interface for Instant Articles as well as a helper for authentication. The client depends on the main [Facebook SDK for PHP](https://github.com/facebook/facebook-php-sdk-v4) as an interface to the Graph API and Facebook Login.
12
 
13
  ## Quick Start
14
- You can find examples on how to use **Elements**, **Transformer**, and **Client** in the [Quick Start guide](https://github.com/facebook/facebook-instant-articles-sdk-php/blob/master/docs/QuickStart.md).
15
 
16
  ## Installation
17
 
@@ -53,6 +53,18 @@ If you change structure, paths, namespaces, etc., make sure you run the [autoloa
53
  $ composer dump-autoload
54
  ```
55
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  ## Contributing
57
 
58
  For us to accept contributions you will have to first have signed the [Contributor License Agreement](https://code.facebook.com/cla). Please see [CONTRIBUTING](https://github.com/facebook/facebook-instant-articles-sdk-php/blob/master/CONTRIBUTING.md) for details.
11
  - **Client**: A simple wrapper around the [Instant Articles API](https://developers.facebook.com/docs/instant-articles/api), which can be used for publishing Instant Articles on Facebook. The client provides a CRUD interface for Instant Articles as well as a helper for authentication. The client depends on the main [Facebook SDK for PHP](https://github.com/facebook/facebook-php-sdk-v4) as an interface to the Graph API and Facebook Login.
12
 
13
  ## Quick Start
14
+ You can find examples on how to use the different components of this SDK to integrate with your CMS in the [Getting Started section](https://developers.facebook.com/docs/instant-articles/sdk/#getting-started) of the documentation.
15
 
16
  ## Installation
17
 
53
  $ composer dump-autoload
54
  ```
55
 
56
+ ## Troubleshooting
57
+
58
+ If you are encountering problems, the following tips may help in troubleshooting issues:
59
+
60
+ - Warnings from the Transformer can be seen with `$transformer->getWarnings()` method.
61
+
62
+ - If content is missing from your transformed article, more likely than not there isn't a **Transformer Rule** matching an element in your source markup. See how to configure appropriate rules for your content in the [Transformer Rules documentation](https://developers.facebook.com/docs/instant-articles/sdk/transformer-rules).
63
+
64
+ - Set the `threshold` in the [configuration of the Logger](https://logging.apache.org/log4php/docs/configuration.html#PHP) to `DEBUG` to expose more details about the items processed by the Transformer.
65
+
66
+ - Refer to the existing [tests of the `Elements`](https://github.com/facebook/facebook-instant-articles-sdk-php/tree/master/tests/Facebook/InstantArticles/Elements) for examples of what is required of each and to potentially create your own tests (which can be run with `$ composer test`).
67
+
68
  ## Contributing
69
 
70
  For us to accept contributions you will have to first have signed the [Contributor License Agreement](https://code.facebook.com/cla). Please see [CONTRIBUTING](https://github.com/facebook/facebook-instant-articles-sdk-php/blob/master/CONTRIBUTING.md) for details.
vendor/facebook/facebook-instant-articles-sdk-php/composer.lock CHANGED
@@ -39,21 +39,20 @@
39
  },
40
  {
41
  "name": "facebook/php-sdk-v4",
42
- "version": "5.1.4",
43
  "source": {
44
  "type": "git",
45
  "url": "https://github.com/facebook/facebook-php-sdk-v4.git",
46
- "reference": "38fd7187a6704d3ab14ded2f3a534ac4ee6f3481"
47
  },
48
  "dist": {
49
  "type": "zip",
50
- "url": "https://api.github.com/repos/facebook/facebook-php-sdk-v4/zipball/38fd7187a6704d3ab14ded2f3a534ac4ee6f3481",
51
- "reference": "38fd7187a6704d3ab14ded2f3a534ac4ee6f3481",
52
  "shasum": ""
53
  },
54
  "require": {
55
- "ext-mbstring": "*",
56
- "php": ">=5.4.0"
57
  },
58
  "require-dev": {
59
  "guzzlehttp/guzzle": "~5.0",
@@ -72,7 +71,10 @@
72
  "autoload": {
73
  "psr-4": {
74
  "Facebook\\": "src/Facebook/"
75
- }
 
 
 
76
  },
77
  "notification-url": "https://packagist.org/downloads/",
78
  "license": [
@@ -90,20 +92,20 @@
90
  "facebook",
91
  "sdk"
92
  ],
93
- "time": "2016-05-13 17:28:30"
94
  },
95
  {
96
  "name": "symfony/css-selector",
97
- "version": "v2.8.6",
98
  "source": {
99
  "type": "git",
100
  "url": "https://github.com/symfony/css-selector.git",
101
- "reference": "07b7ced3ae0c12918477c095453ea8595000810e"
102
  },
103
  "dist": {
104
  "type": "zip",
105
- "url": "https://api.github.com/repos/symfony/css-selector/zipball/07b7ced3ae0c12918477c095453ea8595000810e",
106
- "reference": "07b7ced3ae0c12918477c095453ea8595000810e",
107
  "shasum": ""
108
  },
109
  "require": {
@@ -143,7 +145,7 @@
143
  ],
144
  "description": "Symfony CssSelector Component",
145
  "homepage": "https://symfony.com",
146
- "time": "2016-03-04 07:54:35"
147
  }
148
  ],
149
  "packages-dev": [
@@ -300,32 +302,32 @@
300
  },
301
  {
302
  "name": "phpspec/prophecy",
303
- "version": "v1.6.0",
304
  "source": {
305
  "type": "git",
306
  "url": "https://github.com/phpspec/prophecy.git",
307
- "reference": "3c91bdf81797d725b14cb62906f9a4ce44235972"
308
  },
309
  "dist": {
310
  "type": "zip",
311
- "url": "https://api.github.com/repos/phpspec/prophecy/zipball/3c91bdf81797d725b14cb62906f9a4ce44235972",
312
- "reference": "3c91bdf81797d725b14cb62906f9a4ce44235972",
313
  "shasum": ""
314
  },
315
  "require": {
316
  "doctrine/instantiator": "^1.0.2",
317
  "php": "^5.3|^7.0",
318
- "phpdocumentor/reflection-docblock": "~2.0",
319
- "sebastian/comparator": "~1.1",
320
- "sebastian/recursion-context": "~1.0"
321
  },
322
  "require-dev": {
323
- "phpspec/phpspec": "~2.0"
324
  },
325
  "type": "library",
326
  "extra": {
327
  "branch-alias": {
328
- "dev-master": "1.5.x-dev"
329
  }
330
  },
331
  "autoload": {
@@ -358,7 +360,7 @@
358
  "spy",
359
  "stub"
360
  ],
361
- "time": "2016-02-15 07:46:21"
362
  },
363
  {
364
  "name": "phpunit/php-code-coverage",
@@ -605,16 +607,16 @@
605
  },
606
  {
607
  "name": "phpunit/phpunit",
608
- "version": "4.8.25",
609
  "source": {
610
  "type": "git",
611
  "url": "https://github.com/sebastianbergmann/phpunit.git",
612
- "reference": "6d1588a6542a52ed89636e5a9876bc7502bbb853"
613
  },
614
  "dist": {
615
  "type": "zip",
616
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/6d1588a6542a52ed89636e5a9876bc7502bbb853",
617
- "reference": "6d1588a6542a52ed89636e5a9876bc7502bbb853",
618
  "shasum": ""
619
  },
620
  "require": {
@@ -673,7 +675,7 @@
673
  "testing",
674
  "xunit"
675
  ],
676
- "time": "2016-05-10 18:47:12"
677
  },
678
  {
679
  "name": "phpunit/phpunit-mock-objects",
@@ -849,16 +851,16 @@
849
  },
850
  {
851
  "name": "sebastian/environment",
852
- "version": "1.3.6",
853
  "source": {
854
  "type": "git",
855
  "url": "https://github.com/sebastianbergmann/environment.git",
856
- "reference": "2292b116f43c272ff4328083096114f84ea46a56"
857
  },
858
  "dist": {
859
  "type": "zip",
860
- "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/2292b116f43c272ff4328083096114f84ea46a56",
861
- "reference": "2292b116f43c272ff4328083096114f84ea46a56",
862
  "shasum": ""
863
  },
864
  "require": {
@@ -895,20 +897,20 @@
895
  "environment",
896
  "hhvm"
897
  ],
898
- "time": "2016-05-04 07:59:13"
899
  },
900
  {
901
  "name": "sebastian/exporter",
902
- "version": "1.2.1",
903
  "source": {
904
  "type": "git",
905
  "url": "https://github.com/sebastianbergmann/exporter.git",
906
- "reference": "7ae5513327cb536431847bcc0c10edba2701064e"
907
  },
908
  "dist": {
909
  "type": "zip",
910
- "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e",
911
- "reference": "7ae5513327cb536431847bcc0c10edba2701064e",
912
  "shasum": ""
913
  },
914
  "require": {
@@ -916,12 +918,13 @@
916
  "sebastian/recursion-context": "~1.0"
917
  },
918
  "require-dev": {
 
919
  "phpunit/phpunit": "~4.4"
920
  },
921
  "type": "library",
922
  "extra": {
923
  "branch-alias": {
924
- "dev-master": "1.2.x-dev"
925
  }
926
  },
927
  "autoload": {
@@ -961,7 +964,7 @@
961
  "export",
962
  "exporter"
963
  ],
964
- "time": "2015-06-21 07:55:53"
965
  },
966
  {
967
  "name": "sebastian/global-state",
@@ -1104,16 +1107,16 @@
1104
  },
1105
  {
1106
  "name": "squizlabs/php_codesniffer",
1107
- "version": "2.6.0",
1108
  "source": {
1109
  "type": "git",
1110
  "url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
1111
- "reference": "1bcdf03b068a530ac1962ce671dead356eeba43b"
1112
  },
1113
  "dist": {
1114
  "type": "zip",
1115
- "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1bcdf03b068a530ac1962ce671dead356eeba43b",
1116
- "reference": "1bcdf03b068a530ac1962ce671dead356eeba43b",
1117
  "shasum": ""
1118
  },
1119
  "require": {
@@ -1178,20 +1181,20 @@
1178
  "phpcs",
1179
  "standards"
1180
  ],
1181
- "time": "2016-04-03 22:58:34"
1182
  },
1183
  {
1184
  "name": "symfony/yaml",
1185
- "version": "v2.8.6",
1186
  "source": {
1187
  "type": "git",
1188
  "url": "https://github.com/symfony/yaml.git",
1189
- "reference": "e4fbcc65f90909c999ac3b4dfa699ee6563a9940"
1190
  },
1191
  "dist": {
1192
  "type": "zip",
1193
- "url": "https://api.github.com/repos/symfony/yaml/zipball/e4fbcc65f90909c999ac3b4dfa699ee6563a9940",
1194
- "reference": "e4fbcc65f90909c999ac3b4dfa699ee6563a9940",
1195
  "shasum": ""
1196
  },
1197
  "require": {
@@ -1227,7 +1230,7 @@
1227
  ],
1228
  "description": "Symfony Yaml Component",
1229
  "homepage": "https://symfony.com",
1230
- "time": "2016-03-29 19:00:15"
1231
  }
1232
  ],
1233
  "aliases": [],
39
  },
40
  {
41
  "name": "facebook/php-sdk-v4",
42
+ "version": "5.2.0",
43
  "source": {
44
  "type": "git",
45
  "url": "https://github.com/facebook/facebook-php-sdk-v4.git",
46
+ "reference": "c60fba1fe1de62db1e0776d32fc2fb778189459c"
47
  },
48
  "dist": {
49
  "type": "zip",
50
+ "url": "https://api.github.com/repos/facebook/facebook-php-sdk-v4/zipball/c60fba1fe1de62db1e0776d32fc2fb778189459c",
51
+ "reference": "c60fba1fe1de62db1e0776d32fc2fb778189459c",
52
  "shasum": ""
53
  },
54
  "require": {
55
+ "php": "^5.4|^7.0"
 
56
  },
57
  "require-dev": {
58
  "guzzlehttp/guzzle": "~5.0",
71
  "autoload": {
72
  "psr-4": {
73
  "Facebook\\": "src/Facebook/"
74
+ },
75
+ "files": [
76
+ "src/Facebook/polyfills.php"
77
+ ]
78
  },
79
  "notification-url": "https://packagist.org/downloads/",
80
  "license": [
92
  "facebook",
93
  "sdk"
94
  ],
95
+ "time": "2016-05-18 22:04:36"
96
  },
97
  {
98
  "name": "symfony/css-selector",
99
+ "version": "v2.8.7",
100
  "source": {
101
  "type": "git",
102
  "url": "https://github.com/symfony/css-selector.git",
103
+ "reference": "9a0b2649328297fb6acd0c823789d92efcbd36ad"
104
  },
105
  "dist": {
106
  "type": "zip",
107
+ "url": "https://api.github.com/repos/symfony/css-selector/zipball/9a0b2649328297fb6acd0c823789d92efcbd36ad",
108
+ "reference": "9a0b2649328297fb6acd0c823789d92efcbd36ad",
109
  "shasum": ""
110
  },
111
  "require": {
145
  ],
146
  "description": "Symfony CssSelector Component",
147
  "homepage": "https://symfony.com",
148
+ "time": "2016-06-06 11:11:27"
149
  }
150
  ],
151
  "packages-dev": [
302
  },
303
  {
304
  "name": "phpspec/prophecy",
305
+ "version": "v1.6.1",
306
  "source": {
307
  "type": "git",
308
  "url": "https://github.com/phpspec/prophecy.git",
309
+ "reference": "58a8137754bc24b25740d4281399a4a3596058e0"
310
  },
311
  "dist": {
312
  "type": "zip",
313
+ "url": "https://api.github.com/repos/phpspec/prophecy/zipball/58a8137754bc24b25740d4281399a4a3596058e0",
314
+ "reference": "58a8137754bc24b25740d4281399a4a3596058e0",
315
  "shasum": ""
316
  },
317
  "require": {
318
  "doctrine/instantiator": "^1.0.2",
319
  "php": "^5.3|^7.0",
320
+ "phpdocumentor/reflection-docblock": "^2.0|^3.0.2",
321
+ "sebastian/comparator": "^1.1",
322
+ "sebastian/recursion-context": "^1.0"
323
  },
324
  "require-dev": {
325
+ "phpspec/phpspec": "^2.0"
326
  },
327
  "type": "library",
328
  "extra": {
329
  "branch-alias": {
330
+ "dev-master": "1.6.x-dev"
331
  }
332
  },
333
  "autoload": {
360
  "spy",
361
  "stub"
362
  ],
363
+ "time": "2016-06-07 08:13:47"
364
  },
365
  {
366
  "name": "phpunit/php-code-coverage",
607
  },
608
  {
609
  "name": "phpunit/phpunit",
610
+ "version": "4.8.26",
611
  "source": {
612
  "type": "git",
613
  "url": "https://github.com/sebastianbergmann/phpunit.git",
614
+ "reference": "fc1d8cd5b5de11625979125c5639347896ac2c74"
615
  },
616
  "dist": {
617
  "type": "zip",
618
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fc1d8cd5b5de11625979125c5639347896ac2c74",
619
+ "reference": "fc1d8cd5b5de11625979125c5639347896ac2c74",
620
  "shasum": ""
621
  },
622
  "require": {
675
  "testing",
676
  "xunit"
677
  ],
678
+ "time": "2016-05-17 03:09:28"
679
  },
680
  {
681
  "name": "phpunit/phpunit-mock-objects",
851
  },
852
  {
853
  "name": "sebastian/environment",
854
+ "version": "1.3.7",
855
  "source": {
856
  "type": "git",
857
  "url": "https://github.com/sebastianbergmann/environment.git",
858
+ "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716"
859
  },
860
  "dist": {
861
  "type": "zip",
862
+ "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/4e8f0da10ac5802913afc151413bc8c53b6c2716",
863
+ "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716",
864
  "shasum": ""
865
  },
866
  "require": {
897
  "environment",
898
  "hhvm"
899
  ],
900
+ "time": "2016-05-17 03:18:57"
901
  },
902
  {
903
  "name": "sebastian/exporter",
904
+ "version": "1.2.2",
905
  "source": {
906
  "type": "git",
907
  "url": "https://github.com/sebastianbergmann/exporter.git",
908
+ "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4"
909
  },
910
  "dist": {
911
  "type": "zip",
912
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4",
913
+ "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4",
914
  "shasum": ""
915
  },
916
  "require": {
918
  "sebastian/recursion-context": "~1.0"
919
  },
920
  "require-dev": {
921
+ "ext-mbstring": "*",
922
  "phpunit/phpunit": "~4.4"
923
  },
924
  "type": "library",
925
  "extra": {
926
  "branch-alias": {
927
+ "dev-master": "1.3.x-dev"
928
  }
929
  },
930
  "autoload": {
964
  "export",
965
  "exporter"
966
  ],
967
+ "time": "2016-06-17 09:04:28"
968
  },
969
  {
970
  "name": "sebastian/global-state",
1107
  },
1108
  {
1109
  "name": "squizlabs/php_codesniffer",
1110
+ "version": "2.6.1",
1111
  "source": {
1112
  "type": "git",
1113
  "url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
1114
+ "reference": "fb72ed32f8418db5e7770be1653e62e0d6f5dd3d"
1115
  },
1116
  "dist": {
1117
  "type": "zip",
1118
+ "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/fb72ed32f8418db5e7770be1653e62e0d6f5dd3d",
1119
+ "reference": "fb72ed32f8418db5e7770be1653e62e0d6f5dd3d",
1120
  "shasum": ""
1121
  },
1122
  "require": {
1181
  "phpcs",
1182
  "standards"
1183
  ],
1184
+ "time": "2016-05-30 22:24:32"
1185
  },
1186
  {
1187
  "name": "symfony/yaml",
1188
+ "version": "v2.8.7",
1189
  "source": {
1190
  "type": "git",
1191
  "url": "https://github.com/symfony/yaml.git",
1192
+ "reference": "815fabf3f48c7d1df345a69d1ad1a88f59757b34"
1193
  },
1194
  "dist": {
1195
  "type": "zip",
1196
+ "url": "https://api.github.com/repos/symfony/yaml/zipball/815fabf3f48c7d1df345a69d1ad1a88f59757b34",
1197
+ "reference": "815fabf3f48c7d1df345a69d1ad1a88f59757b34",
1198
  "shasum": ""
1199
  },
1200
  "require": {
1230
  ],
1231
  "description": "Symfony Yaml Component",
1232
  "homepage": "https://symfony.com",
1233
+ "time": "2016-06-06 11:11:27"
1234
  }
1235
  ],
1236
  "aliases": [],
vendor/facebook/facebook-instant-articles-sdk-php/docs/QuickStart.md CHANGED
@@ -1,686 +1,4 @@
1
- # Quick start
2
 
3
- This SDK contains three primary components:
4
- - [**Elements**](#elements) - Instant Article Markup renderer
5
- - [**Transformer**](#transformer) - Engine which transforms HTML into **Elements** objects
6
- - [**Client**](#client) - Client to publish Instant Articles
7
-
8
- [**Transformer Rules**](#custom-transformer-rules) - Within the Transformer are rules which define a mapping between elements in the *source markup* and valid *Instant Article components*. These rules are customizable to allow flexibility in the interpretation of the source markup and is a crucial part of the transformation process so it has a dedicated section.
9
-
10
- ---
11
-
12
- ## Elements
13
- `Elements` is the object tree class that represents the structure of an Instant Article. This object tree structure ensures that no invalid Instant Article HTML markup is generated. Here is a simple and complete object tree structure, starting with the `InstantArticle` class that holds the full Instant Article.
14
-
15
- ```php
16
- $fragment = $document->createDocumentFragment();
17
- $fragment->appendXML(
18
- '<h1>Some custom code</h1>'.
19
- '<script>alert("test");</script>'
20
- );
21
- $article =
22
- InstantArticle::create()
23
- ->withCanonicalUrl('http://foo.com/article.html')
24
- ->withHeader(
25
- Header::create()
26
- ->withTitle('Big Top Title')
27
- ->withSubTitle('Smaller SubTitle')
28
- ->withPublishTime(
29
- Time::create(Time::PUBLISHED)
30
- ->withDatetime(
31
- \DateTime::createFromFormat(
32
- 'j-M-Y G:i:s',
33
- '14-Aug-1984 19:30:00'
34
- )
35
- )
36
- )
37
- ->withModifyTime(
38
- Time::create(Time::MODIFIED)
39
- ->withDatetime(
40
- \DateTime::createFromFormat(
41
- 'j-M-Y G:i:s',
42
- '10-Feb-2016 10:00:00'
43
- )
44
- )
45
- )
46
- ->addAuthor(
47
- Author::create()
48
- ->withName('Author Name')
49
- ->withDescription('Author more detailed description')
50
- )
51
- ->addAuthor(
52
- Author::create()
53
- ->withName('Author in FB')
54
- ->withDescription('Author user in facebook')
55
- ->withURL('http://facebook.com/author')
56
- )
57
- ->withKicker('Some kicker of this article')
58
- ->withCover(
59
- Image::create()
60
- ->withURL('https://jpeg.org/images/jpegls-home.jpg')
61
- ->withCaption(
62
- Caption::create()
63
- ->appendText('Some caption to the image')
64
- )
65
- )
66
- )
67
- // Paragraph1
68
- ->addChild(
69
- Paragraph::create()
70
- ->appendText('Some text to be within a paragraph for testing.')
71
- )
72
- // Paragraph2
73
- ->addChild(
74
- Paragraph::create()
75
- ->appendText('Other text to be within a second paragraph for testing.')
76
- )
77
- // Slideshow
78
- ->addChild(
79
- SlideShow::create()
80
- ->addImage(
81
- Image::create()
82
- ->withURL('https://jpeg.org/images/jpegls-home.jpg')
83
- )
84
- ->addImage(
85
- Image::create()
86
- ->withURL('https://jpeg.org/images/jpegls-home2.jpg')
87
- )
88
- ->addImage(
89
- Image::create()
90
- ->withURL('https://jpeg.org/images/jpegls-home3.jpg')
91
- )
92
- )
93
- // Paragraph3
94
- ->addChild(
95
- Paragraph::create()
96
- ->appendText('Some text to be within a paragraph for testing.')
97
- )
98
- // Ad
99
- ->addChild(
100
- Ad::create()
101
- ->withSource('http://foo.com')
102
- )
103
- // Paragraph4
104
- ->addChild(
105
- Paragraph::create()
106
- ->appendText('Other text to be within a second paragraph for testing.')
107
- )
108
- // Analytics
109
- ->addChild(
110
- Analytics::create()
111
- ->withHTML($fragment)
112
- )
113
- // Footer
114
- ->withFooter(
115
- Footer::create()
116
- ->withCredits('Some plaintext credits.')
117
- );
118
- ```
119
-
120
- ### Rendering the `InstantArticle` Markup
121
-
122
- From above, `$article` now contains a complete `InstantArticle` object — a structured representation of an Instant Article — which can be rendered into valid Instant Article HTML Markup by simply calling its `render()` function:
123
-
124
- ```php
125
- $article->render('<!doctype html>');
126
- ```
127
-
128
- #### Rendered output of the `InstantArticle` object from above
129
- ```xml
130
- <!doctype html>
131
- <html>
132
- <head>
133
- <link rel="canonical" href="http://foo.com/article.html"/>
134
- <meta charset="utf-8"/>
135
- <meta property="op:markup_version" content="v1.0"/>
136
- <meta property="fb:use_automatic_ad_placement" content="true"/>
137
- </head>
138
- <body>
139
- <article>
140
- <header>
141
- <figure>
142
- <img src="https://jpeg.org/images/jpegls-home.jpg"/>
143
- <figcaption>Some caption to the image</figcaption>
144
- </figure>
145
- <h1>Big Top Title</h1>
146
- <h2>Smaller SubTitle</h2>
147
- <time class="op-published" datetime="1984-08-14T19:30:00+00:00">August 14th, 7:30pm</time>
148
- <time class="op-modified" datetime="2016-02-10T10:00:00+00:00">February 10th, 10:00am</time>
149
- <address>
150
- <a>Author Name</a>
151
- Author more detailed description
152
- </address>
153
- <address>
154
- <a href="http://facebook.com/author" rel="facebook">Author in FB</a>
155
- 'Author user in facebook'.
156
- </address>
157
- <h3 class="op-kicker">Some kicker of this article</h3>
158
- </header>
159
- <p>Some text to be within a paragraph for testing.</p>
160
- <p>Other text to be within a second paragraph for testing.</p>
161
- <figure class="op-slideshow">
162
- <figure>
163
- <img src="https://jpeg.org/images/jpegls-home.jpg"/>
164
- </figure>
165
- <figure>
166
- <img src="https://jpeg.org/images/jpegls-home2.jpg"/>
167
- </figure>
168
- <figure>
169
- <img src="https://jpeg.org/images/jpegls-home3.jpg"/>
170
- </figure>
171
- </figure>
172
- <p>Some text to be within a paragraph for testing.</p>
173
- <figure class="op-ad">
174
- <iframe src="http://foo.com"></iframe>
175
- </figure>
176
- <p>Other text to be within a second paragraph for testing.</p>
177
- <figure class="op-tracker">
178
- <iframe>
179
- <h1>Some custom code</h1>
180
- <script>alert("test");</script>
181
- </iframe>
182
- </figure>
183
- <footer>
184
- <aside>Some plaintext credits.</aside>
185
- </footer>
186
- </article>
187
- </body>
188
- </html>
189
- ```
190
-
191
- ## Transformer
192
- The `Transformer` interprets *any* markup in order to fill in the [`InstantArticle`](https://github.com/facebook/facebook-instant-articles-sdk-php/blob/master/src/Facebook/Instantarticles/Elements/InstantArticle.php) object structure. The transformation process follows a set of pre-defined selector rules which maps the markup of the input to known `InstantArticles` `Elements`. This user-defined configuration makes the Transformer versatile and powerful.
193
-
194
- ### Transformer Configuration
195
-
196
- The power of the **Transformer** lies in the configuration rules it uses to map elements from the input markup to Instant Article markup. Configuration rules are applied ***bottom-up*** so all new or custom rules should be added at the end of the file.
197
-
198
- - Each rule in the configuration file should live in the `rules` array
199
- - Each entry should have at least the `class` attribute set
200
- - All classes referred by this configuration file must implement the [`Rule`](https://github.com/facebook/facebook-instant-articles-sdk-php/blob/master/src/Facebook/InstantArticles/Transformer/Rules/Rule.php) class
201
-
202
- The transformer pseudo-algorithm is:
203
-
204
- ```php
205
- $document = loadHTML($input_file);
206
- foreach($document->childNodes as $node) {
207
- foreach($rules as $rule) {
208
- if ($rule->matches($context, $node)) {
209
- // Apply rule...
210
- }
211
- }
212
- }
213
- ```
214
-
215
- This transformer will run through all elements, and for each element checking all rules. The rule to be applied will need to match 2 conditions:
216
-
217
- - Matches context
218
- - Matches selector
219
-
220
- #### Matching context
221
- Context is the container element that is now in the pipe being processed. This is returned by the method:
222
-
223
- ```php
224
- public function getContextClass() {
225
- return InstantArticle::getClassName();
226
- }
227
- ```
228
-
229
- If the `Rule` will be handling more than one context, it is possible by returning an array of classes:
230
-
231
- ```php
232
- public function getContextClass() {
233
- return array(InstantArticle::getClassName(), Header::getClassName());
234
- }
235
- ```
236
-
237
- #### Matching selector
238
- The **selector** field will be used only by rules that extend [`ConfigurationSelectorRule`](https://github.com/facebook/facebook-instant-articles-sdk-php/blob/master/src/Facebook/InstantArticles/Transformer/Rules/ConfigurationSelectorRule.php).
239
-
240
- The selector field will be used as a *CSS selector*; or as an *Xpath selector* if beginning with `/`.
241
-
242
- **Example: using a *CSS Selector* to match a rule**
243
- ```javascript
244
- {
245
- "class": "HeaderRule",
246
- "selector" : "div.header"
247
- }
248
- ```
249
-
250
- **Example: using an *Xpath Selector* to match a rule**
251
- ```javascript
252
- {
253
- "class": "HeaderRule",
254
- "selector" : "//div[class=header]"
255
- }
256
- ```
257
-
258
- ### Example
259
-
260
- #### Input HTML
261
- The following markup is a sample of what could be used as input to the Transformer:
262
-
263
- ```html
264
- <html>
265
- <head>
266
- <script type="text/javascript" href="http://domain.com/javascript.js" />
267
- </head>
268
- <body>
269
- <div class="header">
270
- <div class="title">
271
- <h1>The article title</h1>
272
- <h2>Sub Title</h2>
273
- <span class="author">Author name</author>
274
- </div>
275
- <div class="hero-image">
276
- <img src="http://domain.com/image.png" />
277
- <div class="image-caption">
278
- Some amazing moment captured by Photographer
279
- </div>
280
- </div>
281
- </div>
282
- <p>Lorem <b>ipsum</b> dolor sit amet, consectetur adipiscing elit. Sed eu arcu porta, ultrices massa ut, porttitor diam. Integer id auctor augue.</p>
283
- <p>Vivamus mattis, sem id consequat dapibus, odio urna fermentum risus, in blandit dolor justo vel ex. Curabitur a neque bibendum, hendrerit sem in, congue lectus.</p>
284
- <div class="image">
285
- <img src="http://domain.com/image.png" />
286
- <div class="image-caption">
287
- Some amazing moment captured by Photographer
288
- </div>
289
- </div>
290
- <p>Curabitur vulputate odio eu justo <i>venenatis</i>, a pretium orci placerat. Nam sed neque quis eros vestibulum mattis. Donec vitae mi egestas, laoreet massa et, fringilla libero.</p>
291
- </body>
292
- </html>
293
- ```
294
-
295
- #### Full rule configuration file for the HTML above
296
-
297
- This rule configuration will:
298
-
299
- - run bottom-up
300
- - check if matches "class" (context)
301
- - check if matches "selector" (css or xpath)
302
- - Run the rule (calling the callback method `transform()`)
303
-
304
- ```javascript
305
- {
306
- "rules" :
307
- [
308
- {
309
- "class": "TextNodeRule"
310
- },
311
- {
312
- "class": "PassThroughRule",
313
- "selector" : "html"
314
- },
315
- {
316
- "class": "PassThroughRule",
317
- "selector" : "head"
318
- },
319
- {
320
- "class": "PassThroughRule",
321
- "selector" : "script"
322
- },
323
- {
324
- "class": "PassThroughRule",
325
- "selector" : "body"
326
- },
327
- {
328
- "class": "ItalicRule",
329
- "selector" : "i"
330
- },
331
- {
332
- "class": "BoldRule",
333
- "selector" : "b"
334
- },
335
- {
336
- "class": "ParagraphRule",
337
- "selector" : "p"
338
- },
339
- {
340
- "class": "HeaderTitleRule",
341
- "selector" : "div.title h1"
342
- },
343
- {
344
- "class": "HeaderSubTitleRule",
345
- "selector" : "div.title h2"
346
- },
347
- {
348
- "class": "HeaderRule",
349
- "selector" : "div.header"
350
- },
351
- {
352
- "class": "AuthorRule",
353
- "selector" : "span.author",
354
- "properties" : {
355
- "author.name" : {
356
- "type" : "string",
357
- "selector" : "span"
358
- }
359
- }
360
- },
361
- {
362
- "class": "CaptionRule",
363
- "selector" : "div.image-caption"
364
- },
365
- {
366
- "class": "ImageRule",
367
- "selector" : "div.image",
368
- "properties" : {
369
- "image.url" : {
370
- "type" : "string",
371
- "selector" : "img",
372
- "attribute": "src"
373
- },
374
- "image.caption" : {
375
- "type" : "element",
376
- "selector" : "div.image-caption"
377
- }
378
- }
379
- },
380
- {
381
- "class": "HeaderImageRule",
382
- "selector" : "div.hero-image",
383
- "properties" : {
384
- "image.url" : {
385
- "type" : "string",
386
- "selector" : "img",
387
- "attribute": "src"
388
- },
389
- "image.caption" : {
390
- "type" : "element",
391
- "selector" : "div.image-caption"
392
- }
393
- }
394
- }
395
- ]
396
- }
397
- ```
398
-
399
- ### Creating Custom Rules
400
- Each custom rule implemented should comply with full contract of the `Rule` abstract class.
401
-
402
- ```php
403
- class MyCustomRule extends Rule
404
- {
405
- public function matchesContext($context)
406
- {}
407
-
408
- public function matchesNode($node)
409
- {}
410
-
411
- public function apply($transformer, $container, $node)
412
- {}
413
- }
414
- ```
415
-
416
- The best option is to use the `ConfigurationSelectorRule` as base class for all custom Rules. This way the selector and more configurations are inherited by default.
417
-
418
- ### Invoking Transformer
419
-
420
- To transform your markup into InstantArticle markup, follow these steps:
421
-
422
- - Create an `InstantArticle` instance
423
- - Create a `Transformer` and load it with rules (programmatically or from a file)
424
- - Load/retrieve the HTML content file in the original markup
425
- - Run the Transformer
426
- - Check for errors/warnings
427
-
428
- #### Example
429
- ```php
430
- // Loads the rules content file
431
- $rules_file_content = file_get_contents("simple-rules.json", true);
432
-
433
- // Instantiate Instant article
434
- $instant_article = InstantArticle::create();
435
-
436
- // Creates the transformer and loads the rules
437
- $transformer = new Transformer();
438
- $transformer->loadRules($rules_file_content);
439
-
440
- // Example loads the html from a file
441
- $html_file = file_get_contents("simple.html", true);
442
-
443
- // Ignores errors on HTML parsing
444
- libxml_use_internal_errors(true);
445
- $document = new \DOMDocument();
446
- $document->loadHTML($html_file);
447
- libxml_use_internal_errors(false);
448
-
449
- // Invokes transformer
450
- $transformer->transform($instant_article, $document);
451
-
452
- // Get errors from transformer
453
- $warnings = $transformer->getWarnings();
454
-
455
- // Renders the InstantArticle markup format
456
- $result = $instant_article->render();
457
- ```
458
-
459
- ## Client
460
-
461
- The API Client is a lightweight layer on top of the [Facebook SDK for PHP](https://github.com/facebook/facebook-php-sdk-v4) making it easy to push articles to your Facebook Page. Example:
462
-
463
- ```php
464
- $article = InstantArticle::create();
465
- $transformer->transform($article, $someDocument);
466
-
467
- // Instantiate an API client
468
- $client = Client::create(
469
- 'APP_ID'
470
- 'APP_SECRET',
471
- 'ACCESS_TOKEN',
472
- 'PAGE_ID',
473
- false // development envirorment?
474
- );
475
-
476
- // Import the article
477
- try {
478
- $client->importArticle($article, $take_live);
479
- } catch (Exception $e) {
480
- echo 'Could not import the article: '.$e->getMessage();
481
- }
482
- ```
483
-
484
- ### `Helper` class
485
-
486
- Since publishing Instant Articles is done to an existing Facebook Page, the `Client` also contains a `Helper` class to simplify fetching the access token for Facebook Pages that you're an admin of. Example:
487
-
488
- ```php
489
- $userAccessToken = 'USER_ACCESS_TOKEN';
490
-
491
- // Instantiate a client helper
492
- $helper = Helper::create(
493
- 'APP_ID',
494
- 'APP_SECRET'
495
- );
496
-
497
- // Grab pages you are admin of and tokens
498
- $pagesAndTokens = $helper->getPagesAndTokens($userAccessToken)->all();
499
- foreach ($pagesAndTokens as $pageAndToken) {
500
- echo 'Page ID: ' . $pageAndToken->getField('id');
501
- echo 'Page name: ' . $pageAndToken->getField('name');
502
- echo 'Page access token: ' . $pageAndToken->getField('access_token');
503
- }
504
- ```
505
-
506
- ---
507
-
508
- ## Transformer Rules
509
-
510
- ### Overview
511
-
512
- A valid Instant Article is comprised of a subset of standard HTML tags, detailed in the [Format Reference](https://developers.facebook.com/docs/instant-articles/reference). Adhering to these restrictions ensures that content renders reliably and performant on mobile devices within Facebook but naturally constrains what is allowed within the markup. What's more, the hierarchy of the permitted tags also matters.
513
-
514
- > For example, to render text **bold** in an Instant Article, the `<strong>` tag *must* be used. But if your content makes use of `<b>` as a means to stylize text bold, you would find that your source markup is *valid HTML*, but ultimately is not *valid Instant Articles markup*.
515
-
516
- The Transformer of this SDK helps mitigate these constraints by converting *any markup* into *Instant Articles markup*, and it's the ***Transformer Rules*** which instructs it on how to do so. Collectively, these rules form a mapping between elements in the source markup and what they should be transformed into within the generated Instant Article. Analogous to a car, if the Transformer were the engine powering the conversion of the markup, the Transformer Rules would be the driver.
517
-
518
- Many [example rules](https://github.com/facebook/facebook-instant-articles-sdk-php/blob/master/tests/Facebook/InstantArticles/Transformer/instant-article-example-rules.json) have been defined which aim to cover most common scenarios. Additional rules can be added to amend or override existing ones.
519
-
520
- ### <a name="custom-transformer-rules"></a>Configuring Transformer Rules
521
-
522
- At a high level, configuring a Transformer Rule involves three steps:
523
-
524
- 1. Identifying a source element in your markup
525
- 2. Associating it with an existing [Transformer Rule Class](#transformer-classes) in a permitted context
526
- 3. Defining any value for attributes on the transformed element that the Rule Class expects (not always needed)
527
-
528
- Take the following example which would cause text within `<span class="bold">` to be stylized **bold** in the generated Instant Article.
529
-
530
- ```javascript
531
- // Transformer Rule associating <span class="bold"> to the `BoldRule` class
532
- {
533
- "class": "BoldRule",
534
- "selector": "span.bold"
535
- //"properties": {} // Not needed since the `BoldRule` class has no properties
536
- }
537
- ```
538
-
539
- *If you're curious, the resulting markup within the Instant Article for the `BoldRule` class is the `<b>` tag; the fact that this detail is abstracted by the Transformer is intentional.*
540
-
541
- > Caveat: the example above makes no mention of *context*. It turns out, the rule above would only work as expected if it were being processed within a particular parent context of the generated document. Read more about [rule context](#rule-context).
542
-
543
- #### Transformer Rule: Selector
544
-
545
- The selector is used to identify elements in the source markup. Both **CSS selectors** and **Xpath** are supported formats.
546
-
547
- #### Transformer Rule: Properties
548
-
549
- Some Transformer Rules have properties who's value are obtained from content in the source markup. The content itself isn't specified in the rule; rather, the rule defines where in the source element the value is located, again by use of a selector.
550
-
551
- In the configuration of your rule, you instruct the transformer where the value can be obtained from within the source markup with the following key-value pairs allowed for a property:
552
-
553
- Key name | Required? | Notes
554
- --- | --- | ---
555
- `type` | *Required* | Defines the behavior of the `selector` (below). Possible values: `"string"`, `"int"`, `"exists"`, `"sibling"`, `"children"`, `"xpath"`.
556
- `selector` | *Required* | The interpretation of the value of this item is affected by the `type` (above).
557
- `attribute` | *Required only if `type` is one of: `"string"`, `"int"`, `"exists"`, `"xpath"`* | The name of the attribute on the element, identified by the value in `selector`, whose value you want to use as the content for the property of the Transformer Rule.<br><br>When `type` is `"exists"`, the value of the property will be `true` simply by the presence of the attribute, regardless of its value.
558
-
559
- ##### Examples
560
-
561
- For example, take the standard case of configuring the transformer to recognize anchor tags, such as `<a href="http://example.com">` for generating links with an Instant Article:
562
-
563
- ```javascript
564
- {
565
- "class": "AnchorRule", // Rule class
566
- "selector": "a", // Matching source element (CSS selector)
567
- "properties" : { // All supported properties
568
-
569
- "anchor.href" : { // Name of property
570
- "type" : "string",
571
- "selector" : "a", // Additional selector specific to this property
572
- "attribute": "href" // Attribute whose value to use
573
- }
574
-
575
- }
576
- }
577
- ```
578
-
579
- As a contrived example, here's a rule which would transform source markup formatted as such: `<span class="custom-href" data-link="http://example.com">` into the same links within the generated Instant Article:
580
-
581
- ```javascript
582
- {
583
- "class": "AnchorRule",
584
- "selector": "span.custom-href",
585
- "properties" : {
586
-
587
- "anchor.href" : {
588
- "type" : "string",
589
- "selector" : "span.custom-href",
590
- "attribute": "data-link"
591
- }
592
-
593
- }
594
- }
595
- ```
596
-
597
- #### <a name="transformer-classes"></a>Transformer Rule: Class
598
-
599
- A *Rule Class* is simply a pre-determined link to a valid Instant Article component. It defines supported `properties` and permitted *context(s)* for the Rule.
600
-
601
- > <a name="rule-context"></a> **Rule Context**
602
-
603
- > The hierarchal nature of an HTML document implies that an element always exists within the *context of a parent element*. A similar hierarchy is built during a document's transformation into an Instant Article giving each individual element a *context*. This context plays an important role for the Transfer Rules since, along with the selector, it is a condition that must be matched before a rule is executed.
604
-
605
- > As the Transformer traverses through the entire HTML document, it attempts to execute all of rules for every tag element it encounters. But two criteria need to be met each time:
606
-
607
- > 1. the *selector* of the rule must match the current element
608
- > 2. the *context* in which the rule would run must match one of the allowed context(s) of the rule class
609
-
610
- > In other words, as the Transformer progresses, it uses the rules to build a hierarchy of transformed elements, giving *context* to each subsequent rule. Rules are only permitted to execute within an allowed *context* defined for the [Rule Class](#transformer-classes) is uses.
611
-
612
- ##### Available Rule Classes
613
-
614
- Listed below are all the available *Rule Classes*, along with their supported `properties` and permitted *context(s)*, whereby source markup can be mapped to a valid Instant Article component via its selectors. They are arranged into logical groups by function. For the `properties`, assume `type` of `"string"` unless noted otherwise.
615
-
616
- **Formatting**
617
-
618
- Rule Class | Properties | Permitted Context | Notes
619
- --- | --- | --- | ---
620
- `AnchorRule` | `anchor.href`<br>`anchor.rel` | *TextContainer* |
621
- `BoldRule` | | *TextContainer* |
622
- `ItalicRule` | | *TextContainer* |
623
- `LineBreakRule` | | *TextContainer* |
624
-
625
- **Layout**
626
-
627
- Rule Class | Properties | Permitted Context | Notes
628
- --- | --- | --- | ---
629
- `BlockquoteRule` | | *InstantArticle* |
630
- `H1Rule` | `type` = `"exists"` for one of either text alignment options:<br> `op-left`<br>`op-center`<br>`op-right`<br><br>`type` = `"exists"` for one of either vertical position options:<br>`op-vertical-below`<br>`op-vertical-above`<br>`op-vertical-center` <br><br>`type` = `"exists"` for one of either size options:<br>`op-size-medium`<br>`op-size-large`<br>`op-size-extra-large` | *Caption*, *InstantArticle* | Used to specify the Header value for multiple **Element** types.
631
- `H2Rule` | `type` = `"exists"` for one of either text alignment options:<br> `op-left`<br>`op-center`<br>`op-right`<br><br>`type` = `"exists"` for one of either vertical position options:<br>`op-vertical-below`<br>`op-vertical-above`<br>`op-vertical-center` | *Caption*, *InstantArticle* |
632
- `HeaderRule` | | *InstantArticle* |
633
- `ListElementRule` | | *InstantArticle* |
634
- `ListItemRule` | | *ListElement* |
635
- `ParagraphRule` | | *InstantArticle* |
636
- `PullquoteCiteRule` | | *Pullquote* |
637
- `PullquoteRule` | | *InstantArticle* |
638
-
639
- **Graphic**
640
-
641
- Rule Class | Properties | Permitted Context | Notes
642
- --- | --- | --- | ---
643
- `AdRule` | `ad.url`<br>`ad.height`<br>`ad.width`<br>`ad.embed` | *InstantArticle* |
644
- `AnalyticsRule` | `analytics.url`<br>`analytics.embed` | *InstantArticle* |
645
- `GeoTagRule` | `map.geotag` | *Image*, *Video*, *Map* | Used to specify the [Geotag](https://developers.facebook.com/docs/instant-articles/reference/map) value for multiple **Element** types.<br><br>Multiple definitions of the same `map.geotag` property are allowed and each one will be processed independently.
646
- `HeaderAdRule` | `ad.url`<br>`ad.height`<br>`ad.width`<br>`ad.embed` | *Header* |
647
- `HeaderImageRule` | `image.url` | *Header* |
648
- `ImageRule` | `image.url`<br>`image.like`<br>`image.comments` | *InstantArticle* |
649
- `InteractiveRule` | `interactive.iframe`<br>`interactive.url`<br>`interactive.height`<br>`no-margin`<br>`column-width` | *InstantArticle* |
650
- `MapRule` | | *InstantArticle* |
651
-
652
- **Media**
653
-
654
- Rule Class | Properties | Permitted Context | Notes
655
- --- | --- | --- | ---
656
- `AudioRule` | `audio.url`<br>`audio.title`<br>`audio.autoplay`<br>`audio.muted` | *Audible* |
657
- `RelatedArticlesRule` | `related.title` | *InstantArticle* | Wrapper for a [Related Article](https://developers.facebook.com/docs/instant-articles/reference/related-articles) component
658
- `RelatedItemRule` | `related.sponsored`<br>`related.url` | *RelatedArticles* | For individual articles within a `RelatedArticlesRule`
659
- `SlideshowImageRule` | `image.url`<br>`caption.title`<br>`caption.credit` | *Slideshow* | For individual images within a `SlideshowRule`
660
- `SlideshowRule` | | *InstantArticle* | Wrapper for a [Slideshow](https://developers.facebook.com/docs/instant-articles/reference/slideshow) component
661
- `SocialEmbedRule` | `socialembed.iframe`<br>`socialembed.url`<br>`socialembed.width`<br>`socialembed.height` | *InstantArticle* |
662
- `VideoRule` | `video.url`<br>`video.type`<br>`video.playback`<br>`video.controls`<br>`video.like`<br>`video.comments`<br><br>`type` = `"exists"` for any of the video player options:<br>`loop`<br>`data-fade`<br><br>one of the following:<br>`aspect-fit`<br>`aspect-fit-only`<br>`fullscreen`<br>`non-interactive` | *InstantArticle* |
663
-
664
- **Article Structure**
665
-
666
- Rule Class | Properties | Permitted Context | Notes
667
- --- | --- | --- | ---
668
- `AuthorRule` | `author.url`<br>`author.name`<br>`author.description`<br>`author.role_contribution` | *Header* |
669
- `CaptionCreditRule` | `type` = `"exists"` for one of either text alignment options:<br> `op-left`<br>`op-center`<br>`op-right`<br><br>`type` = `"exists"` for one of either vertical position options:<br>`op-vertical-below`<br>`op-vertical-above`<br>`op-vertical-center` | *Caption* |
670
- `CaptionRule` | `caption.default`<br><br>`type` = `"exists"` for one of either text alignment options:<br> `op-left`<br>`op-center`<br>`op-right`<br><br>`type` = `"exists"` for one of either vertical position options:<br>`op-vertical-below`<br>`op-vertical-above`<br>`op-vertical-center` <br><br>`type` = `"exists"` for one of either size options:<br>`op-size-medium`<br>`op-size-large`<br>`op-size-extra-large` | *Map*, *Image*, *Interactive*, *Slideshow*, *SocialEmbed*, *Video* | Used to specify the [Caption](https://developers.facebook.com/docs/instant-articles/reference/caption) value for multiple **Element** types.<br><br>Multiple definitions of the same `caption.default` property are allowed and each one will be processed independently.
671
- `FooterRelatedArticlesRule` | `related.title` | *Footer* |
672
- `FooterRule` | | *InstantArticle* |
673
- `HeaderKickerRule` | | *Header* |
674
- `HeaderSubTitleRule` | | *Header* |
675
- `HeaderTitleRule` | | *Header* |
676
- `ParagraphFooterRule` | | *Footer* |
677
- `TimeRule` | `article.time`<br>`article.time_type` | *Header* |
678
-
679
- **Special**
680
-
681
- Rule Class | Properties | Permitted Context | Notes
682
- --- | --- | --- | ---
683
- `IgnoreRule` | | *(any)* | This rule class will effectively strip out an element tag which matches the associated ***selector*** of the rule.
684
- `PassThroughRule` | | *(any)* | This rule class instructs the Transformer to not process any transformation on element tags which match the associated ***selector*** of the rule.
685
- `InstantArticleRule` | `article.canonical`<br>`article.charset`<br>`article.markup.version`<br>`article.auto.ad` | *InstantArticle* | This is the entry point, or root node, of the hierarchy.
686
- `TextNodeRule` | | *TextContainer* |
1
+ # Documentation Moved
2
 
3
+ The documentation is now hosted on Facebook's Developer site:<br>
4
+ https://developers.facebook.com/docs/instant-articles/sdk/
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Client/Client.php CHANGED
@@ -12,6 +12,7 @@ namespace Facebook\InstantArticles\Client;
12
  use Facebook\Exceptions\FacebookSDKException;
13
  use Facebook\Facebook;
14
  use Facebook\InstantArticles\Elements\InstantArticle;
 
15
  use Facebook\InstantArticles\Validators\Type;
16
 
17
  class Client
@@ -83,22 +84,26 @@ class Client
83
  * Import an article into your Instant Articles library.
84
  *
85
  * @param InstantArticle $article The article to import
86
- * @param bool|false $takeLive Specifies if this article should be taken live or not. Optional. Default: false.
 
 
87
  */
88
- public function importArticle($article, $takeLive = false)
89
  {
90
- Type::enforce($article, InstantArticle::getClassName());
91
- Type::enforce($takeLive, Type::BOOLEAN);
92
 
93
  // Never try to take live if we're in development (the API would throw an error if we tried)
94
- $takeLive = $this->developmentMode ? false : $takeLive;
95
 
96
  // Assume default access token is set on $this->facebook
97
- $this->facebook->post($this->pageID . Client::EDGE_NAME, [
98
  'html_source' => $article->render(),
99
- 'take_live' => $takeLive,
100
  'development_mode' => $this->developmentMode,
101
  ]);
 
 
102
  }
103
 
104
  /**
@@ -124,7 +129,7 @@ class Client
124
  $this->facebook->delete($articleID);
125
  return InstantArticleStatus::success();
126
  }
127
- return InstantArticleStatus::notFound(['An Instant Article ID ' . $articleID . ' was not found for ' . $canonicalURL . ' in ' . __FUNCTION__ . '.']);
128
  }
129
 
130
  /**
@@ -137,8 +142,10 @@ class Client
137
  {
138
  Type::enforce($canonicalURL, Type::STRING);
139
 
140
- $response = $this->facebook->get('?id=' . $canonicalURL . '&fields=instant_article');
141
- $instantArticle = $response->getGraphNode()->getField('instant_article');
 
 
142
 
143
  if (!$instantArticle) {
144
  return null;
@@ -148,7 +155,6 @@ class Client
148
  return $articleID;
149
  }
150
 
151
-
152
  /**
153
  * Get the last submission status of an Instant Article.
154
  *
@@ -176,4 +182,64 @@ class Client
176
 
177
  return InstantArticleStatus::fromStatus($articleStatus['status'], $messages);
178
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
  }
12
  use Facebook\Exceptions\FacebookSDKException;
13
  use Facebook\Facebook;
14
  use Facebook\InstantArticles\Elements\InstantArticle;
15
+ use Facebook\InstantArticles\Elements\InstantArticleInterface;
16
  use Facebook\InstantArticles\Validators\Type;
17
 
18
  class Client
84
  * Import an article into your Instant Articles library.
85
  *
86
  * @param InstantArticle $article The article to import
87
+ * @param bool|false $published Specifies if this article should be taken live or not. Optional. Default: false.
88
+ *
89
+ * @return int The submission status ID. It is not the article ID. (Since 1.3.0)
90
  */
91
+ public function importArticle($article, $published = false)
92
  {
93
+ Type::enforce($article, 'Facebook\InstantArticles\Elements\InstantArticleInterface');
94
+ Type::enforce($published, Type::BOOLEAN);
95
 
96
  // Never try to take live if we're in development (the API would throw an error if we tried)
97
+ $published = $this->developmentMode ? false : $published;
98
 
99
  // Assume default access token is set on $this->facebook
100
+ $response = $this->facebook->post($this->pageID . Client::EDGE_NAME, [
101
  'html_source' => $article->render(),
102
+ 'published' => $published,
103
  'development_mode' => $this->developmentMode,
104
  ]);
105
+
106
+ return $response->getGraphNode()->getField('id');
107
  }
108
 
109
  /**
129
  $this->facebook->delete($articleID);
130
  return InstantArticleStatus::success();
131
  }
132
+ return InstantArticleStatus::notFound([ServerMessage::info('An Instant Article ID ' . $articleID . ' was not found for ' . $canonicalURL . ' in ' . __FUNCTION__ . '.')]);
133
  }
134
 
135
  /**
142
  {
143
  Type::enforce($canonicalURL, Type::STRING);
144
 
145
+ $field = $this->developmentMode ? 'development_instant_article' : 'instant_article';
146
+
147
+ $response = $this->facebook->get('?id=' . $canonicalURL . '&fields=' . $field);
148
+ $instantArticle = $response->getGraphNode()->getField($field);
149
 
150
  if (!$instantArticle) {
151
  return null;
155
  return $articleID;
156
  }
157
 
 
158
  /**
159
  * Get the last submission status of an Instant Article.
160
  *
182
 
183
  return InstantArticleStatus::fromStatus($articleStatus['status'], $messages);
184
  }
185
+
186
+ /**
187
+ * Get the submission status of an Instant Article.
188
+ *
189
+ * @param string|null $submissionStatusID the submission status ID
190
+ * @return InstantArticleStatus
191
+ */
192
+ public function getSubmissionStatus($submissionStatusID)
193
+ {
194
+ if (!$submissionStatusID) {
195
+ return InstantArticleStatus::notFound();
196
+ }
197
+
198
+ Type::enforce($submissionStatusID, Type::STRING);
199
+
200
+ $response = $this->facebook->get($submissionStatusID . '?fields=status,errors');
201
+ $articleStatus = $response->getGraphNode();
202
+
203
+ $messages = [];
204
+ $errors = $articleStatus->getField('errors');
205
+ if (null !== $errors) {
206
+ foreach ($errors as $error) {
207
+ $messages[] = ServerMessage::fromLevel($error['level'], $error['message']);
208
+ }
209
+ }
210
+
211
+ return InstantArticleStatus::fromStatus($articleStatus->getField('status'), $messages);
212
+ }
213
+
214
+ /**
215
+ * Get the review submission status
216
+ *
217
+ * @return string The review status
218
+ */
219
+ public function getReviewSubmissionStatus()
220
+ {
221
+ $response = $this->facebook->get('me?fields=instant_articles_review_status');
222
+ return $response->getGraphNode()->getField('instant_articles_review_status');
223
+ }
224
+
225
+ /**
226
+ * Retrieve the article URLs already published on Instant Articles
227
+ *
228
+ * @return string[] The cannonical URLs from articles
229
+ */
230
+ public function getArticlesURLs($limit = 10, $development_mode = false)
231
+ {
232
+ $articleURLs = [];
233
+ $response = $this->facebook->get(
234
+ 'me/instant_articles?fields=canonical_url&'.
235
+ 'development_mode='.($development_mode ? 'true' : 'false').
236
+ '&limit='.$limit
237
+ );
238
+ $articles = $response->getGraphEdge();
239
+ foreach ($articles as $article) {
240
+ $articleURLs[] = $article['canonical_url'];
241
+ }
242
+
243
+ return $articleURLs;
244
+ }
245
  }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Ad.php CHANGED
@@ -22,7 +22,7 @@ use Facebook\InstantArticles\Validators\Type;
22
  *
23
  * @see {link:https://developers.intern.facebook.com/docs/instant-articles/reference/ad}
24
  */
25
- class Ad extends Element
26
  {
27
  /**
28
  * @var int The height of your ad.
@@ -39,11 +39,6 @@ class Ad extends Element
39
  */
40
  private $width;
41
 
42
- /**
43
- * @var \DOMNode The HTML of the content.
44
- */
45
- private $html;
46
-
47
  private function __construct()
48
  {
49
  }
@@ -121,21 +116,6 @@ class Ad extends Element
121
  return $this;
122
  }
123
 
124
- /**
125
- * Sets the unescaped HTML of your ad.
126
- *
127
- * @param \DOMNode $html The unescaped HTML of your ad.
128
- *
129
- * @return $this
130
- */
131
- public function withHTML($html)
132
- {
133
- Type::enforce($html, 'DOMNode');
134
- $this->html = $html;
135
-
136
- return $this;
137
- }
138
-
139
  /**
140
  * @return bool True if Ad has been set to reusable.
141
  */
@@ -174,16 +154,6 @@ class Ad extends Element
174
  return $this->width;
175
  }
176
 
177
- /**
178
- * Gets the unescaped HTML of your ad.
179
- *
180
- * @return \DOMNode The unescaped HTML of your ad.
181
- */
182
- public function getHtml()
183
- {
184
- return $this->html;
185
- }
186
-
187
  /**
188
  * Structure and create the full Ad in a DOMElement.
189
  *
22
  *
23
  * @see {link:https://developers.intern.facebook.com/docs/instant-articles/reference/ad}
24
  */
25
+ class Ad extends ElementWithHTML
26
  {
27
  /**
28
  * @var int The height of your ad.
39
  */
40
  private $width;
41
 
 
 
 
 
 
42
  private function __construct()
43
  {
44
  }
116
  return $this;
117
  }
118
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  /**
120
  * @return bool True if Ad has been set to reusable.
121
  */
154
  return $this->width;
155
  }
156
 
 
 
 
 
 
 
 
 
 
 
157
  /**
158
  * Structure and create the full Ad in a DOMElement.
159
  *
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Analytics.php CHANGED
@@ -28,18 +28,13 @@ use Facebook\InstantArticles\Validators\Type;
28
  *
29
  * @see {link:https://developers.intern.facebook.com/docs/instant-articles/reference/analytics}
30
  */
31
- class Analytics extends Element
32
  {
33
  /**
34
  * @var string The source of the content for your analytics code.
35
  */
36
  private $source;
37
 
38
- /**
39
- * @var \DOMNode The HTML of the content.
40
- */
41
- private $html;
42
-
43
  private function __construct()
44
  {
45
  }
@@ -64,21 +59,6 @@ class Analytics extends Element
64
  return $this;
65
  }
66
 
67
- /**
68
- * Sets the unescaped HTML of your ad.
69
- *
70
- * @param \DOMNode $html The unescaped HTML of your ad.
71
- *
72
- * @return $this
73
- */
74
- public function withHTML($html)
75
- {
76
- Type::enforce($html, 'DOMNode');
77
- $this->html = $html;
78
-
79
- return $this;
80
- }
81
-
82
  /**
83
  * Gets the source for the analytics.
84
  *
@@ -89,16 +69,6 @@ class Analytics extends Element
89
  return $this->source;
90
  }
91
 
92
- /**
93
- * Gets the unescaped HTML of your analytics.
94
- *
95
- * @return \DOMNode The unescaped HTML of your analytics.
96
- */
97
- public function getHtml()
98
- {
99
- return $this->html;
100
- }
101
-
102
  /**
103
  * Structure and create the full ArticleAd in a DOMElement.
104
  *
28
  *
29
  * @see {link:https://developers.intern.facebook.com/docs/instant-articles/reference/analytics}
30
  */
31
+ class Analytics extends ElementWithHTML
32
  {
33
  /**
34
  * @var string The source of the content for your analytics code.
35
  */
36
  private $source;
37
 
 
 
 
 
 
38
  private function __construct()
39
  {
40
  }
59
  return $this;
60
  }
61
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  /**
63
  * Gets the source for the analytics.
64
  *
69
  return $this->source;
70
  }
71
 
 
 
 
 
 
 
 
 
 
 
72
  /**
73
  * Structure and create the full ArticleAd in a DOMElement.
74
  *
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Caption.php CHANGED
@@ -18,7 +18,7 @@ use Facebook\InstantArticles\Validators\Type;
18
  * <li>Video</li>
19
  * <li>SlideShow</li>
20
  * <li>Map</li>
21
- * <li>SocialEmbed</li>
22
  * </ul>.
23
  *
24
  * Example:
@@ -31,7 +31,7 @@ use Facebook\InstantArticles\Validators\Type;
31
  * @see Video
32
  * @see SlideShow
33
  * @see Map
34
- * @see SocialEmbed
35
  * @see {link:https://developers.intern.facebook.com/docs/instant-articles/reference/caption}
36
  */
37
  class Caption extends FormattedText
@@ -51,6 +51,11 @@ class Caption extends FormattedText
51
  const POSITION_ABOVE = 'op-vertical-above';
52
  const POSITION_CENTER = 'op-vertical-center';
53
 
 
 
 
 
 
54
  /**
55
  * @var H1 The caption title. REQUIRED
56
  */
@@ -76,6 +81,11 @@ class Caption extends FormattedText
76
  */
77
  private $textAlignment;
78
 
 
 
 
 
 
79
  /**
80
  * @var string text position. Values: "op-vertical-below"|"op-vertical-above"|"op-vertical-center"
81
  */
@@ -200,6 +210,32 @@ class Caption extends FormattedText
200
  return $this;
201
  }
202
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
  /**
204
  * @deprecated
205
  *
@@ -336,11 +372,14 @@ class Caption extends FormattedText
336
  }
337
 
338
  // Formating markup
339
- if ($this->textAlignment || $this->fontSize || $this->position) {
340
  $classes = [];
341
  if ($this->textAlignment) {
342
  $classes[] = $this->textAlignment;
343
  }
 
 
 
344
  if ($this->fontSize) {
345
  $classes[] = $this->fontSize;
346
  }
18
  * <li>Video</li>
19
  * <li>SlideShow</li>
20
  * <li>Map</li>
21
+ * <li>Interactive</li>
22
  * </ul>.
23
  *
24
  * Example:
31
  * @see Video
32
  * @see SlideShow
33
  * @see Map
34
+ * @see Interactive
35
  * @see {link:https://developers.intern.facebook.com/docs/instant-articles/reference/caption}
36
  */
37
  class Caption extends FormattedText
51
  const POSITION_ABOVE = 'op-vertical-above';
52
  const POSITION_CENTER = 'op-vertical-center';
53
 
54
+ // Vertical alignment of the block
55
+ const VERTICAL_TOP = 'op-vertical-top';
56
+ const VERTICAL_BOTTOM = 'op-vertical-bottom';
57
+ const VERTICAL_CENTER = 'op-vertical-center';
58
+
59
  /**
60
  * @var H1 The caption title. REQUIRED
61
  */
81
  */
82
  private $textAlignment;
83
 
84
+ /**
85
+ * @var string vertical align. Values: "op-vertical-top"|"op-vertical-bottom"|"op-vertical-center"
86
+ */
87
+ private $verticalAlignment;
88
+
89
  /**
90
  * @var string text position. Values: "op-vertical-below"|"op-vertical-above"|"op-vertical-center"
91
  */
210
  return $this;
211
  }
212
 
213
+ /**
214
+ * The vertical alignment that will be used.
215
+ *
216
+ * @see Caption::VERTICAL_TOP
217
+ * @see Caption::VERTICAL_BOTTOM
218
+ * @see Caption::VERTICAL_CENTER
219
+ *
220
+ * @param string $vertical_alignment alignment option that will be used.
221
+ *
222
+ * @return $this
223
+ */
224
+ public function withVerticalAlignment($vertical_alignment)
225
+ {
226
+ Type::enforceWithin(
227
+ $vertical_alignment,
228
+ [
229
+ Caption::VERTICAL_TOP,
230
+ Caption::VERTICAL_BOTTOM,
231
+ Caption::VERTICAL_CENTER
232
+ ]
233
+ );
234
+ $this->verticalAlignment = $vertical_alignment;
235
+
236
+ return $this;
237
+ }
238
+
239
  /**
240
  * @deprecated
241
  *
372
  }
373
 
374
  // Formating markup
375
+ if ($this->textAlignment || $this->verticalAlignment || $this->fontSize || $this->position) {
376
  $classes = [];
377
  if ($this->textAlignment) {
378
  $classes[] = $this->textAlignment;
379
  }
380
+ if ($this->verticalAlignment) {
381
+ $classes[] = $this->verticalAlignment;
382
+ }
383
  if ($this->fontSize) {
384
  $classes[] = $this->fontSize;
385
  }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Cite.php CHANGED
@@ -25,6 +25,11 @@ class Cite extends TextContainer
25
  */
26
  private $textAlignment;
27
 
 
 
 
 
 
28
  /**
29
  * @var string text position. Values: "op-vertical-below"|"op-vertical-above"|"op-vertical-center"
30
  */
@@ -68,6 +73,32 @@ class Cite extends TextContainer
68
  return $this;
69
  }
70
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  /**
72
  * @deprecated
73
  *
@@ -130,6 +161,9 @@ class Cite extends TextContainer
130
  if ($this->textAlignment) {
131
  $classes[] = $this->textAlignment;
132
  }
 
 
 
133
  if (!empty($classes)) {
134
  $cite->setAttribute('class', implode(' ', $classes));
135
  }
25
  */
26
  private $textAlignment;
27
 
28
+ /**
29
+ * @var string vertical align. Values: "op-vertical-top"|"op-vertical-bottom"|"op-vertical-center"
30
+ */
31
+ private $verticalAlignment;
32
+
33
  /**
34
  * @var string text position. Values: "op-vertical-below"|"op-vertical-above"|"op-vertical-center"
35
  */
73
  return $this;
74
  }
75
 
76
+ /**
77
+ * The vertical alignment that will be used.
78
+ *
79
+ * @see Caption::VERTICAL_TOP
80
+ * @see Caption::VERTICAL_BOTTOM
81
+ * @see Caption::VERTICAL_CENTER
82
+ *
83
+ * @param string $vertical_alignment alignment option that will be used.
84
+ *
85
+ * @return $this
86
+ */
87
+ public function withVerticalAlignment($vertical_alignment)
88
+ {
89
+ Type::enforceWithin(
90
+ $vertical_alignment,
91
+ [
92
+ Caption::VERTICAL_TOP,
93
+ Caption::VERTICAL_BOTTOM,
94
+ Caption::VERTICAL_CENTER
95
+ ]
96
+ );
97
+ $this->verticalAlignment = $vertical_alignment;
98
+
99
+ return $this;
100
+ }
101
+
102
  /**
103
  * @deprecated
104
  *
161
  if ($this->textAlignment) {
162
  $classes[] = $this->textAlignment;
163
  }
164
+ if ($this->verticalAlignment) {
165
+ $classes[] = $this->verticalAlignment;
166
+ }
167
  if (!empty($classes)) {
168
  $cite->setAttribute('class', implode(' ', $classes));
169
  }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Element.php CHANGED
@@ -18,6 +18,8 @@ use Facebook\InstantArticles\Validators\Type;
18
  */
19
  abstract class Element
20
  {
 
 
21
  abstract public function toDOMElement();
22
 
23
  /**
@@ -37,21 +39,11 @@ abstract class Element
37
  $document->appendChild($element);
38
  $rendered = $doctype.$document->saveXML($element);
39
 
40
- return $rendered;
41
- }
 
42
 
43
- /**
44
- * Appends unescaped HTML to a element using the right strategy.
45
- *
46
- * @param \DOMNode $element - The element to append the HTML to.
47
- * @param \DOMNode $content - The unescaped HTML to append.
48
- */
49
- protected function dangerouslyAppendUnescapedHTML($element, $content)
50
- {
51
- Type::enforce($content, 'DOMNode');
52
- Type::enforce($element, 'DOMNode');
53
- $imported = $element->ownerDocument->importNode($content, true);
54
- $element->appendChild($imported);
55
  }
56
 
57
  /**
@@ -86,4 +78,31 @@ abstract class Element
86
  $fragment->appendChild($document->createTextNode(''));
87
  return $fragment;
88
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  }
18
  */
19
  abstract class Element
20
  {
21
+ private $empty_validation = true;
22
+
23
  abstract public function toDOMElement();
24
 
25
  /**
39
  $document->appendChild($element);
40
  $rendered = $doctype.$document->saveXML($element);
41
 
42
+ // We can't currently use DOMDocument::saveHTML, because it doesn't produce proper HTML5 markup, so we have to strip CDATA enclosures
43
+ // TODO Consider replacing this workaround with a parent class for elements that will be rendered and in this class use the `srcdoc` attribute to output the (escaped) markup
44
+ $rendered = preg_replace('/<!\[CDATA\[(.*?)\]\]>/is', '$1', $rendered);
45
 
46
+ return $rendered;
 
 
 
 
 
 
 
 
 
 
 
47
  }
48
 
49
  /**
78
  $fragment->appendChild($document->createTextNode(''));
79
  return $fragment;
80
  }
81
+
82
+ /**
83
+ * Method that checks if empty element will warn on InstantArticleValidator.
84
+ * @since v1.1.1
85
+ * @see InstantArticleValidator
86
+ * @return boolean true for ignore, false otherwise.
87
+ */
88
+ public function isEmptyValidationEnabled()
89
+ {
90
+ return $this->empty_validation;
91
+ }
92
+
93
+ /**
94
+ * Marks this Paragraph to be ignored on isValid if it is empty.
95
+ */
96
+ public function enableEmptyValidation()
97
+ {
98
+ return $this->empty_validation = true;
99
+ }
100
+
101
+ /**
102
+ * Marks this Paragraph to *not* be ignored on isValid if it is empty.
103
+ */
104
+ public function disableEmptyValidation()
105
+ {
106
+ return $this->empty_validation = false;
107
+ }
108
  }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/ElementWithHTML.php ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2016-present, Facebook, Inc.
4
+ * All rights reserved.
5
+ *
6
+ * This source code is licensed under the license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+ namespace Facebook\InstantArticles\Elements;
10
+
11
+ use Facebook\InstantArticles\Validators\Type;
12
+
13
+ /**
14
+ * Base class for elements that may contain embedded HTML
15
+ */
16
+ abstract class ElementWithHTML extends Element
17
+ {
18
+ /**
19
+ * @var \DOMNode The HTML of the content.
20
+ */
21
+ protected $html;
22
+
23
+ /**
24
+ * Sets the unescaped HTML.
25
+ *
26
+ * @param \DOMNode|string $html The unescaped HTML.
27
+ *
28
+ * @return $this
29
+ */
30
+ public function withHTML($html)
31
+ {
32
+ Type::enforce($html, ['DOMNode', Type::STRING]);
33
+ // If this is raw HTML source, wrap in a CDATA section as it could contain JS etc. with characters (such as &) that are not allowed in unescaped form
34
+ if (Type::is($html, Type::STRING)) {
35
+ $html = new \DOMCdataSection($html);
36
+ }
37
+ $this->html = $html;
38
+
39
+ return $this;
40
+ }
41
+
42
+ /**
43
+ * Gets the unescaped HTML.
44
+ *
45
+ * @return \DOMNode The unescaped HTML.
46
+ */
47
+ public function getHtml()
48
+ {
49
+ return $this->html;
50
+ }
51
+
52
+ /**
53
+ * Appends unescaped HTML to a element using the right strategy.
54
+ *
55
+ * @param \DOMNode $element - The element to append the HTML to.
56
+ * @param \DOMNode $content - The unescaped HTML to append.
57
+ */
58
+ protected function dangerouslyAppendUnescapedHTML($element, $content)
59
+ {
60
+ Type::enforce($content, 'DOMNode');
61
+ Type::enforce($element, 'DOMNode');
62
+ $imported = $element->ownerDocument->importNode($content, true);
63
+ $element->appendChild($imported);
64
+ }
65
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Header.php CHANGED
@@ -38,9 +38,10 @@ use Facebook\InstantArticles\Validators\Type;
38
  class Header extends Element implements Container
39
  {
40
  /**
41
- * @var Image|Video|null for the image or video on the header.
42
  *
43
  * @see Image
 
44
  * @see Video
45
  */
46
  private $cover;
@@ -81,6 +82,11 @@ class Header extends Element implements Container
81
  */
82
  private $ads = [];
83
 
 
 
 
 
 
84
  private function __construct()
85
  {
86
  }
@@ -96,13 +102,20 @@ class Header extends Element implements Container
96
  /**
97
  * Sets the cover of InstantArticle with Image or Video
98
  *
99
- * @param Image|Video $cover The cover for the header of the InstantArticle
100
  *
101
  * @return $this
102
  */
103
  public function withCover($cover)
104
  {
105
- Type::enforce($cover, [Image::getClassName(), Video::getClassName()]);
 
 
 
 
 
 
 
106
  $this->cover = $cover;
107
 
108
  return $this;
@@ -276,7 +289,22 @@ class Header extends Element implements Container
276
  }
277
 
278
  /**
279
- * @return Image|Video The cover for the header of the InstantArticle
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
280
  */
281
  public function getCover()
282
  {
@@ -339,6 +367,14 @@ class Header extends Element implements Container
339
  return $this->ads;
340
  }
341
 
 
 
 
 
 
 
 
 
342
  /**
343
  * Structure and create the full ArticleImage in a XML format DOMElement.
344
  *
@@ -424,6 +460,10 @@ class Header extends Element implements Container
424
  }
425
  }
426
 
 
 
 
 
427
  return $element;
428
  }
429
 
@@ -496,6 +536,10 @@ class Header extends Element implements Container
496
  }
497
  }
498
 
 
 
 
 
499
  return $children;
500
  }
501
  }
38
  class Header extends Element implements Container
39
  {
40
  /**
41
+ * @var Image|Video|Slideshow|null for the image or video on the header.
42
  *
43
  * @see Image
44
+ * @see Slideshow
45
  * @see Video
46
  */
47
  private $cover;
82
  */
83
  private $ads = [];
84
 
85
+ /**
86
+ * @var Sponsor The sponsor for this article. See Branded Content.
87
+ */
88
+ private $sponsor;
89
+
90
  private function __construct()
91
  {
92
  }
102
  /**
103
  * Sets the cover of InstantArticle with Image or Video
104
  *
105
+ * @param Image|Video|Slideshow $cover The cover for the header of the InstantArticle
106
  *
107
  * @return $this
108
  */
109
  public function withCover($cover)
110
  {
111
+ Type::enforce(
112
+ $cover,
113
+ [
114
+ Image::getClassName(),
115
+ Slideshow::getClassName(),
116
+ Video::getClassName()
117
+ ]
118
+ );
119
  $this->cover = $cover;
120
 
121
  return $this;
289
  }
290
 
291
  /**
292
+ * Sets the sponsor for this Article.
293
+ *
294
+ * @param Sponsor $sponsor The sponsor of article to be set.
295
+ *
296
+ * @return $this
297
+ */
298
+ public function withSponsor($sponsor)
299
+ {
300
+ Type::enforce($sponsor, Sponsor::getClassName());
301
+ $this->sponsor = $sponsor;
302
+
303
+ return $this;
304
+ }
305
+
306
+ /**
307
+ * @return Image|Slideshow|Video The cover for the header of the InstantArticle
308
  */
309
  public function getCover()
310
  {
367
  return $this->ads;
368
  }
369
 
370
+ /**
371
+ * @return Sponsor the sponsor of this Article.
372
+ */
373
+ public function getSponsor()
374
+ {
375
+ return $this->sponsor;
376
+ }
377
+
378
  /**
379
  * Structure and create the full ArticleImage in a XML format DOMElement.
380
  *
460
  }
461
  }
462
 
463
+ if ($this->sponsor && $this->sponsor->isValid()) {
464
+ $element->appendChild($this->sponsor->toDOMElement($document));
465
+ }
466
+
467
  return $element;
468
  }
469
 
536
  }
537
  }
538
 
539
+ if ($this->sponsor) {
540
+ $children[] = $this->sponsor;
541
+ }
542
+
543
  return $children;
544
  }
545
  }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/InstantArticle.php CHANGED
@@ -31,9 +31,10 @@ use Facebook\InstantArticles\Validators\Type;
31
  * </html>
32
  *
33
  */
34
- class InstantArticle extends Element implements Container
 
35
  {
36
- const CURRENT_VERSION = '1.1.0';
37
 
38
  /**
39
  * The meta properties that are used on <head>
31
  * </html>
32
  *
33
  */
34
+
35
+ class InstantArticle extends Element implements Container, InstantArticleInterface
36
  {
37
+ const CURRENT_VERSION = '1.3.0';
38
 
39
  /**
40
  * The meta properties that are used on <head>
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/InstantArticleInterface.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2016-present, Facebook, Inc.
4
+ * All rights reserved.
5
+ *
6
+ * This source code is licensed under the license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+ namespace Facebook\InstantArticles\Elements;
10
+
11
+ interface InstantArticleInterface
12
+ {
13
+ public function render();
14
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Interactive.php CHANGED
@@ -21,7 +21,7 @@ use Facebook\InstantArticles\Validators\Type;
21
  *
22
  * @see {link:https://developers.intern.facebook.com/docs/instant-articles/reference/interactive}
23
  */
24
- class Interactive extends Element implements Container
25
  {
26
  const NO_MARGIN = 'no-margin';
27
  const COLUMN_WIDTH = 'column-width';
@@ -31,6 +31,11 @@ class Interactive extends Element implements Container
31
  */
32
  private $caption;
33
 
 
 
 
 
 
34
  /**
35
  * @var int The height of your interactive graphic.
36
  */
@@ -46,12 +51,7 @@ class Interactive extends Element implements Container
46
  * @see Interactive::NO_MARGIN
47
  * @see Interactive::COLUMN_WIDTH
48
  */
49
- private $width;
50
-
51
- /**
52
- * @var \DOMNode The HTML of the content.
53
- */
54
- private $html;
55
 
56
  private function __construct()
57
  {
@@ -77,6 +77,21 @@ class Interactive extends Element implements Container
77
  return $this;
78
  }
79
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  /**
81
  * Sets the height of your interactive graphic.
82
  *
@@ -108,50 +123,43 @@ class Interactive extends Element implements Container
108
  }
109
 
110
  /**
111
- * Sets the width setting of your interactive graphic.
112
  *
113
- * @param string $width The width setting of your interactive graphic.
114
  *
115
  * @see Interactive::NO_MARGIN
116
  * @see Interactive::COLUMN_WIDTH
117
  *
118
  * @return $this
119
  */
120
- public function withWidth($width)
121
  {
122
  Type::enforceWithin(
123
- $width,
124
  [
125
  Interactive::NO_MARGIN,
126
  Interactive::COLUMN_WIDTH
127
  ]
128
  );
129
- $this->width = $width;
130
 
131
  return $this;
132
  }
133
 
134
  /**
135
- * Sets the unescaped HTML of your interactive graphic.
136
- *
137
- * @param \DOMNode $html The unescaped HTML of your interactive graphic.
138
- *
139
- * @return $this
140
  */
141
- public function withHTML($html)
142
  {
143
- Type::enforce($html, 'DOMNode');
144
- $this->html = $html;
145
-
146
- return $this;
147
  }
148
 
149
  /**
150
- * @return Caption the caption element
151
  */
152
- public function getCaption()
153
  {
154
- return $this->caption;
155
  }
156
 
157
  /**
@@ -171,19 +179,11 @@ class Interactive extends Element implements Container
171
  }
172
 
173
  /**
174
- * @return int the width
175
  */
176
- public function getWidth()
177
  {
178
- return $this->width;
179
- }
180
-
181
- /**
182
- * @return \DOMNode unescaped html
183
- */
184
- public function getHtml()
185
- {
186
- return $this->html;
187
  }
188
 
189
  /**
@@ -218,8 +218,12 @@ class Interactive extends Element implements Container
218
  $iframe->setAttribute('src', $this->source);
219
  }
220
 
 
 
 
 
221
  if ($this->width) {
222
- $iframe->setAttribute('class', $this->width);
223
  }
224
 
225
  if ($this->height) {
21
  *
22
  * @see {link:https://developers.intern.facebook.com/docs/instant-articles/reference/interactive}
23
  */
24
+ class Interactive extends ElementWithHTML implements Container
25
  {
26
  const NO_MARGIN = 'no-margin';
27
  const COLUMN_WIDTH = 'column-width';
31
  */
32
  private $caption;
33
 
34
+ /**
35
+ * @var int The width of your interactive graphic.
36
+ */
37
+ private $width;
38
+
39
  /**
40
  * @var int The height of your interactive graphic.
41
  */
51
  * @see Interactive::NO_MARGIN
52
  * @see Interactive::COLUMN_WIDTH
53
  */
54
+ private $margin;
 
 
 
 
 
55
 
56
  private function __construct()
57
  {
77
  return $this;
78
  }
79
 
80
+ /**
81
+ * Sets the width of your interactive graphic.
82
+ *
83
+ * @param int $width The height of your interactive graphic.
84
+ *
85
+ * @return $this
86
+ */
87
+ public function withWidth($width)
88
+ {
89
+ Type::enforce($width, Type::INTEGER);
90
+ $this->width = $width;
91
+
92
+ return $this;
93
+ }
94
+
95
  /**
96
  * Sets the height of your interactive graphic.
97
  *
123
  }
124
 
125
  /**
126
+ * Sets the margin setting of your interactive graphic.
127
  *
128
+ * @param string $margin The margin setting of your interactive graphic.
129
  *
130
  * @see Interactive::NO_MARGIN
131
  * @see Interactive::COLUMN_WIDTH
132
  *
133
  * @return $this
134
  */
135
+ public function withMargin($margin)
136
  {
137
  Type::enforceWithin(
138
+ $margin,
139
  [
140
  Interactive::NO_MARGIN,
141
  Interactive::COLUMN_WIDTH
142
  ]
143
  );
144
+ $this->margin = $margin;
145
 
146
  return $this;
147
  }
148
 
149
  /**
150
+ * @return Caption the caption element
 
 
 
 
151
  */
152
+ public function getCaption()
153
  {
154
+ return $this->caption;
 
 
 
155
  }
156
 
157
  /**
158
+ * @return int the width
159
  */
160
+ public function getWidth()
161
  {
162
+ return $this->width;
163
  }
164
 
165
  /**
179
  }
180
 
181
  /**
182
+ * @return string the margin
183
  */
184
+ public function getMargin()
185
  {
186
+ return $this->margin;
 
 
 
 
 
 
 
 
187
  }
188
 
189
  /**
218
  $iframe->setAttribute('src', $this->source);
219
  }
220
 
221
+ if ($this->margin) {
222
+ $iframe->setAttribute('class', $this->margin);
223
+ }
224
+
225
  if ($this->width) {
226
+ $iframe->setAttribute('width', $this->width);
227
  }
228
 
229
  if ($this->height) {
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/ListElement.php CHANGED
@@ -32,14 +32,14 @@ class ListElement extends Element implements Container
32
  /**
33
  * @var boolean Checks if it is ordered or unordered
34
  */
35
- private $isOrdered;
36
 
37
  /**
38
  * @var ListItem[] Items of the list
39
  */
40
  private $items = [];
41
 
42
- private function __construct()
43
  {
44
  }
45
 
@@ -97,6 +97,7 @@ class ListElement extends Element implements Container
97
  public function withItems($new_items)
98
  {
99
  Type::enforceArrayOf($new_items, [ListItem::getClassName(), Type::STRING]);
 
100
  foreach ($new_items as $new_item) {
101
  $this->addItem($new_item);
102
  }
32
  /**
33
  * @var boolean Checks if it is ordered or unordered
34
  */
35
+ private $isOrdered = false;
36
 
37
  /**
38
  * @var ListItem[] Items of the list
39
  */
40
  private $items = [];
41
 
42
+ protected function __construct()
43
  {
44
  }
45
 
97
  public function withItems($new_items)
98
  {
99
  Type::enforceArrayOf($new_items, [ListItem::getClassName(), Type::STRING]);
100
+ $this->items = [];
101
  foreach ($new_items as $new_item) {
102
  $this->addItem($new_item);
103
  }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/SocialEmbed.php CHANGED
@@ -11,249 +11,12 @@ namespace Facebook\InstantArticles\Elements;
11
  use Facebook\InstantArticles\Validators\Type;
12
 
13
  /**
14
- * Embeds content from social media
15
- *
16
- * Example:
17
- * <figure class="op-social">
18
- * <iframe>
19
- * <!-- Include Instagram embed code here -->
20
- * </iframe>
21
- * </figure>
22
  *
23
  * @see {link:https://developers.intern.facebook.com/docs/instant-articles/reference/social}
 
 
24
  */
25
- class SocialEmbed extends Element implements Container
26
  {
27
- /**
28
- * @var Caption Descriptive text for your social embed.
29
- */
30
- private $caption;
31
-
32
- /**
33
- * @var \DOMNode The HTML of the content.
34
- */
35
- private $html;
36
-
37
- /**
38
- * @var string The source of the content for your social embed.
39
- */
40
- private $source;
41
-
42
- /**
43
- * @var int The width of your social embed.
44
- */
45
- private $width;
46
-
47
- /**
48
- * @var int The height of your social embed.
49
- */
50
- private $height;
51
-
52
- private function __construct()
53
- {
54
- }
55
-
56
- /**
57
- * @return SocialEmbed
58
- */
59
- public static function create()
60
- {
61
- return new self();
62
- }
63
-
64
- /**
65
- * Sets the caption for the social embed.
66
- *
67
- * @param Caption $caption - Descriptive text for your social embed.
68
- *
69
- * @return $this
70
- */
71
- public function withCaption($caption)
72
- {
73
- Type::enforce($caption, Caption::getClassName());
74
- $this->caption = $caption;
75
-
76
- return $this;
77
- }
78
-
79
- /**
80
- * Sets the source for the social embed.
81
- *
82
- * @param string $source - The source of the content for your social embed.
83
- *
84
- * @return $this
85
- */
86
- public function withSource($source)
87
- {
88
- Type::enforce($source, Type::STRING);
89
- $this->source = $source;
90
-
91
- return $this;
92
- }
93
-
94
- /**
95
- * Sets the unescaped HTML of your social embed.
96
- *
97
- * @param \DOMNode $html - The unescaped HTML of your social embed.
98
- *
99
- * @return $this
100
- */
101
- public function withHTML($html)
102
- {
103
- Type::enforce($html, 'DOMNode');
104
- $this->html = $html;
105
-
106
- return $this;
107
- }
108
-
109
- /**
110
- * Sets the width of your social embed.
111
- *
112
- * @param int $width The width of your social embed.
113
- *
114
- * @return $this
115
- */
116
- public function withWidth($width)
117
- {
118
- Type::enforce($width, Type::INTEGER);
119
- $this->width = $width;
120
-
121
- return $this;
122
- }
123
-
124
- /**
125
- * Sets the height of your social embed.
126
- *
127
- * @param int $height The height of your social embed.
128
- *
129
- * @return $this
130
- */
131
- public function withHeight($height)
132
- {
133
- Type::enforce($height, Type::INTEGER);
134
- $this->height = $height;
135
-
136
- return $this;
137
- }
138
-
139
- /**
140
- * @return Caption - The caption for social embed block
141
- */
142
- public function getCaption()
143
- {
144
- return $this->caption;
145
- }
146
-
147
- /**
148
- * @return \DOMNode The unescaped HTML of your social embed.
149
- */
150
- public function getHtml()
151
- {
152
- return $this->html;
153
- }
154
-
155
- /**
156
- * @return string The source of the content for your social embed.
157
- */
158
- public function getSource()
159
- {
160
- return $this->source;
161
- }
162
-
163
- /**
164
- * @return int the width
165
- */
166
- public function getWidth()
167
- {
168
- return $this->width;
169
- }
170
-
171
- /**
172
- * @return int the height
173
- */
174
- public function getHeight()
175
- {
176
- return $this->height;
177
- }
178
-
179
- /**
180
- * Structure and create the full SocialEmbed in a DOMElement.
181
- *
182
- * @param \DOMDocument $document - The document where this element will be appended (optional).
183
- *
184
- * @return \DOMElement
185
- */
186
- public function toDOMElement($document = null)
187
- {
188
- if (!$document) {
189
- $document = new \DOMDocument();
190
- }
191
-
192
- if (!$this->isValid()) {
193
- return $this->emptyElement($document);
194
- }
195
-
196
- $figure = $document->createElement('figure');
197
- $iframe = $document->createElement('iframe');
198
-
199
- $figure->appendChild($iframe);
200
-
201
- // Caption markup optional
202
- if ($this->caption) {
203
- $figure->appendChild($this->caption->toDOMElement($document));
204
- }
205
-
206
- if ($this->source) {
207
- $iframe->setAttribute('src', $this->source);
208
- }
209
-
210
- if ($this->width) {
211
- $iframe->setAttribute('width', $this->width);
212
- }
213
-
214
- if ($this->height) {
215
- $iframe->setAttribute('height', $this->height);
216
- }
217
-
218
- $figure->setAttribute('class', 'op-social');
219
-
220
- // SocialEmbed markup
221
- if ($this->html) {
222
- // Here we do not care about what is inside the iframe
223
- // because it'll be rendered in a sandboxed webview
224
- $this->dangerouslyAppendUnescapedHTML($iframe, $this->html);
225
- } else {
226
- $iframe->appendChild($document->createTextNode(''));
227
- }
228
-
229
- return $figure;
230
- }
231
-
232
- /**
233
- * Overrides the Element::isValid().
234
- *
235
- * @see Element::isValid().
236
- * @return true for valid SocialEmbed that contains valid source or html, false otherwise.
237
- */
238
- public function isValid()
239
- {
240
- return !Type::isTextEmpty($this->source) || $this->html;
241
- }
242
-
243
- /**
244
- * Implements the Container::getContainerChildren().
245
- *
246
- * @see Container::getContainerChildren().
247
- * @return array of Elements contained by Image.
248
- */
249
- public function getContainerChildren()
250
- {
251
- $children = array();
252
-
253
- if ($this->caption) {
254
- $children[] = $this->caption;
255
- }
256
-
257
- return $children;
258
- }
259
  }
11
  use Facebook\InstantArticles\Validators\Type;
12
 
13
  /**
14
+ * This should not be used anymore. Will be removed soon. Use element Interactive.
 
 
 
 
 
 
 
15
  *
16
  * @see {link:https://developers.intern.facebook.com/docs/instant-articles/reference/social}
17
+ * @see Interactive
18
+ * @deprecated
19
  */
20
+ class SocialEmbed extends Interactive
21
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Sponsor.php ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2016-present, Facebook, Inc.
4
+ * All rights reserved.
5
+ *
6
+ * This source code is licensed under the license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+ namespace Facebook\InstantArticles\Elements;
10
+
11
+ use Facebook\InstantArticles\Validators\Type;
12
+
13
+ /**
14
+ * Class Sponsor that represents branded content.
15
+ *
16
+ * Example:
17
+ * <ul class="op-sponsors">
18
+ * <li><a href="http://facebook.com/your-sponsor" rel="facebook"></a></li>
19
+ * </ul>
20
+ *
21
+ */
22
+ class Sponsor extends Element
23
+ {
24
+ /**
25
+ * @var string page URL.
26
+ */
27
+ private $page_url;
28
+
29
+ /**
30
+ * Factory method for a Sponsor.
31
+ *
32
+ * @return Sponsor the new instance.
33
+ */
34
+ public static function create()
35
+ {
36
+ return new self();
37
+ }
38
+
39
+ /**
40
+ * Sets the page url sponsor. Overrides the previous set URL.
41
+ *
42
+ * @param string The page url that will be the sponsor.
43
+ *
44
+ * @return $this
45
+ */
46
+ public function withPageUrl($url)
47
+ {
48
+ Type::enforce($url, Type::STRING);
49
+ $this->page_url = $url;
50
+ return $this;
51
+ }
52
+
53
+ /**
54
+ * Overrides the Element::isValid().
55
+ *
56
+ * @see Element::isValid().
57
+ * @return true for valid ListElement that contains at least one ListItem's valid, false otherwise.
58
+ */
59
+ public function isValid()
60
+ {
61
+ return !Type::isTextEmpty($this->page_url);
62
+ }
63
+
64
+ /**
65
+ * Structure and create the full Video in a XML format DOMElement.
66
+ *
67
+ * @param \DOMDocument $document where this element will be appended. Optional
68
+ *
69
+ * @return \DOMElement
70
+ */
71
+ public function toDOMElement($document = null)
72
+ {
73
+ if (!$document) {
74
+ $document = new \DOMDocument();
75
+ }
76
+
77
+ if (!$this->isValid()) {
78
+ return $this->emptyElement($document);
79
+ }
80
+
81
+ $element = $document->createElement('ul');
82
+ $element->setAttribute('class', 'op-sponsors');
83
+
84
+ $item = $document->createElement('li');
85
+ $element->appendChild($item);
86
+
87
+ $anchor = $document->createElement('a');
88
+ $item->appendChild($anchor);
89
+
90
+ $anchor->setAttribute('href', $this->page_url);
91
+ $anchor->setAttribute('rel', 'facebook');
92
+ $anchor->appendChild($document->createTextNode(''));
93
+
94
+ return $element;
95
+ }
96
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Parser/Parser.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2016-present, Facebook, Inc.
4
+ * All rights reserved.
5
+ *
6
+ * This source code is licensed under the license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+ namespace Facebook\InstantArticles\Parser;
10
+
11
+ use Facebook\InstantArticles\Transformer\Transformer;
12
+ use Facebook\InstantArticles\Elements\InstantArticle;
13
+ use Facebook\InstantArticles\Validators\Type;
14
+
15
+ class Parser
16
+ {
17
+ /**
18
+ * @param string|DOMDocument $document The document html of an Instant Article
19
+ *
20
+ * @return InstantArticle filled element that was parsed from the DOMDocument parameter
21
+ */
22
+ public function parse($content)
23
+ {
24
+ if (Type::is($content, Type::STRING)) {
25
+ libxml_use_internal_errors(true);
26
+ $document = new \DOMDocument();
27
+ $document->loadHTML($content);
28
+ libxml_use_internal_errors(false);
29
+ } else {
30
+ $document = $content;
31
+ }
32
+
33
+ $json_file = file_get_contents(__DIR__ . '/instant-articles-rules.json');
34
+
35
+ $instant_article = InstantArticle::create();
36
+ $transformer = new Transformer();
37
+ $transformer->loadRules($json_file);
38
+
39
+ $transformer->transform($instant_article, $document);
40
+
41
+ return $instant_article;
42
+ }
43
+ }
vendor/facebook/facebook-instant-articles-sdk-php/{tests/Facebook/InstantArticles/Transformer/instant-article-example-rules.json → src/Facebook/InstantArticles/Parser/instant-articles-rules.json} RENAMED
@@ -76,6 +76,17 @@
76
  "class": "ListItemRule",
77
  "selector" : "li"
78
  },
 
 
 
 
 
 
 
 
 
 
 
79
  {
80
  "class": "ListElementRule",
81
  "selector" : "ul"
@@ -507,21 +518,6 @@
507
  }
508
  }
509
  },
510
- {
511
- "class": "SocialEmbedRule",
512
- "selector" : "figure.op-social",
513
- "properties" : {
514
- "socialembed.url" : {
515
- "type" : "string",
516
- "selector" : "iframe",
517
- "attribute": "src"
518
- },
519
- "socialembed.iframe" : {
520
- "type" : "children",
521
- "selector" : "iframe"
522
- }
523
- }
524
- },
525
  {
526
  "class": "InteractiveRule",
527
  "selector" : "figure.op-interactive",
@@ -544,6 +540,11 @@
544
  "selector" : "iframe",
545
  "attribute": "height"
546
  },
 
 
 
 
 
547
  "interactive.iframe" : {
548
  "type" : "children",
549
  "selector" : "iframe"
76
  "class": "ListItemRule",
77
  "selector" : "li"
78
  },
79
+ {
80
+ "class": "SponsorRule",
81
+ "selector" : "ul.op-sponsors",
82
+ "properties" : {
83
+ "sponsor.page_url" : {
84
+ "type" : "string",
85
+ "selector" : "a",
86
+ "attribute": "href"
87
+ }
88
+ }
89
+ },
90
  {
91
  "class": "ListElementRule",
92
  "selector" : "ul"
518
  }
519
  }
520
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
521
  {
522
  "class": "InteractiveRule",
523
  "selector" : "figure.op-interactive",
540
  "selector" : "iframe",
541
  "attribute": "height"
542
  },
543
+ "interactive.width": {
544
+ "type": "int",
545
+ "selector": "iframe",
546
+ "attribute": "width"
547
+ },
548
  "interactive.iframe" : {
549
  "type" : "children",
550
  "selector" : "iframe"
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/ConfigurationSelectorRule.php CHANGED
@@ -123,11 +123,14 @@ abstract class ConfigurationSelectorRule extends Rule
123
 
124
  $results = $domXPath->query($xpath);
125
 
126
- foreach ($results as $result) {
127
- if ($result === $node) {
128
- return true;
 
 
129
  }
130
  }
 
131
  return false;
132
  }
133
 
123
 
124
  $results = $domXPath->query($xpath);
125
 
126
+ if (false !== $results) {
127
+ foreach ($results as $result) {
128
+ if ($result === $node) {
129
+ return true;
130
+ }
131
  }
132
  }
133
+
134
  return false;
135
  }
136
 
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/ImageInsideParagraphRule.php ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2016-present, Facebook, Inc.
4
+ * All rights reserved.
5
+ *
6
+ * This source code is licensed under the license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+ namespace Facebook\InstantArticles\Transformer\Rules;
10
+
11
+ use Facebook\InstantArticles\Elements\Image;
12
+ use Facebook\InstantArticles\Elements\TextContainer;
13
+ use Facebook\InstantArticles\Elements\Paragraph;
14
+ use Facebook\InstantArticles\Transformer\Warnings\InvalidSelector;
15
+ use Facebook\InstantArticles\Transformer\Warnings\NoRootInstantArticleFoundWarning;
16
+
17
+ class ImageInsideParagraphRule extends ConfigurationSelectorRule
18
+ {
19
+ const PROPERTY_IMAGE_URL = 'image.url';
20
+ const PROPERTY_LIKE = 'image.like';
21
+ const PROPERTY_COMMENTS = 'image.comments';
22
+
23
+ public function getContextClass()
24
+ {
25
+ return Paragraph::getClassName();
26
+ }
27
+
28
+ public static function create()
29
+ {
30
+ return new ImageInsideParagraphRule();
31
+ }
32
+
33
+ public static function createFrom($configuration)
34
+ {
35
+ $image_rule = self::create();
36
+ $image_rule->withSelector($configuration['selector']);
37
+
38
+ $image_rule->withProperties(
39
+ [
40
+ self::PROPERTY_IMAGE_URL,
41
+ self::PROPERTY_LIKE,
42
+ self::PROPERTY_COMMENTS
43
+ ],
44
+ $configuration
45
+ );
46
+
47
+ return $image_rule;
48
+ }
49
+
50
+ public function apply($transformer, $context, $node)
51
+ {
52
+ $image = Image::create();
53
+
54
+ // Builds the image
55
+ $url = $this->getProperty(self::PROPERTY_IMAGE_URL, $node);
56
+ if ($url) {
57
+ $image->withURL($url);
58
+ $instant_article = $transformer->getInstantArticle();
59
+ if ($instant_article) {
60
+ $instant_article->addChild($image);
61
+ $context->disableEmptyValidation();
62
+ $context = Paragraph::create();
63
+ $context->disableEmptyValidation();
64
+ $instant_article->addChild($context);
65
+ } else {
66
+ $transformer->addWarning(
67
+ // This new error message should be something like:
68
+ // Could not transform Image, as no root InstantArticle was provided.
69
+ new NoRootInstantArticleFoundWarning(null, $node)
70
+ );
71
+ }
72
+ } else {
73
+ $transformer->addWarning(
74
+ new InvalidSelector(
75
+ self::PROPERTY_IMAGE_URL,
76
+ $instant_article,
77
+ $node,
78
+ $this
79
+ )
80
+ );
81
+ }
82
+
83
+ if ($this->getProperty(self::PROPERTY_LIKE, $node)) {
84
+ $image->enableLike();
85
+ }
86
+
87
+ if ($this->getProperty(self::PROPERTY_COMMENTS, $node)) {
88
+ $image->enableComments();
89
+ }
90
+
91
+ $suppress_warnings = $transformer->suppress_warnings;
92
+ $transformer->suppress_warnings = true;
93
+ $transformer->transform($image, $node);
94
+ $transformer->suppress_warnings = $suppress_warnings;
95
+
96
+ return $context;
97
+ }
98
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/InteractiveRule.php CHANGED
@@ -19,6 +19,7 @@ class InteractiveRule extends ConfigurationSelectorRule
19
  const PROPERTY_WIDTH_NO_MARGIN = Interactive::NO_MARGIN;
20
  const PROPERTY_WIDTH_COLUMN_WIDTH = Interactive::COLUMN_WIDTH;
21
  const PROPERTY_HEIGHT = 'interactive.height';
 
22
 
23
  public function getContextClass()
24
  {
@@ -41,6 +42,7 @@ class InteractiveRule extends ConfigurationSelectorRule
41
  self::PROPERTY_URL,
42
  self::PROPERTY_WIDTH_NO_MARGIN,
43
  self::PROPERTY_WIDTH_COLUMN_WIDTH,
 
44
  self::PROPERTY_HEIGHT
45
  ],
46
  $configuration
@@ -76,9 +78,14 @@ class InteractiveRule extends ConfigurationSelectorRule
76
  }
77
 
78
  if ($this->getProperty(self::PROPERTY_WIDTH_COLUMN_WIDTH, $node)) {
79
- $interactive->withWidth(Interactive::COLUMN_WIDTH);
80
  } else {
81
- $interactive->withWidth(Interactive::NO_MARGIN);
 
 
 
 
 
82
  }
83
 
84
  $height = $this->getProperty(self::PROPERTY_HEIGHT, $node);
19
  const PROPERTY_WIDTH_NO_MARGIN = Interactive::NO_MARGIN;
20
  const PROPERTY_WIDTH_COLUMN_WIDTH = Interactive::COLUMN_WIDTH;
21
  const PROPERTY_HEIGHT = 'interactive.height';
22
+ const PROPERTY_WIDTH = 'interactive.width';
23
 
24
  public function getContextClass()
25
  {
42
  self::PROPERTY_URL,
43
  self::PROPERTY_WIDTH_NO_MARGIN,
44
  self::PROPERTY_WIDTH_COLUMN_WIDTH,
45
+ self::PROPERTY_WIDTH,
46
  self::PROPERTY_HEIGHT
47
  ],
48
  $configuration
78
  }
79
 
80
  if ($this->getProperty(self::PROPERTY_WIDTH_COLUMN_WIDTH, $node)) {
81
+ $interactive->withMargin(Interactive::COLUMN_WIDTH);
82
  } else {
83
+ $interactive->withMargin(Interactive::NO_MARGIN);
84
+ }
85
+
86
+ $width = $this->getProperty(self::PROPERTY_WIDTH, $node);
87
+ if ($width) {
88
+ $interactive->withWidth($width);
89
  }
90
 
91
  $height = $this->getProperty(self::PROPERTY_HEIGHT, $node);
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/SocialEmbedRule.php CHANGED
@@ -11,7 +11,11 @@ namespace Facebook\InstantArticles\Transformer\Rules;
11
  use Facebook\InstantArticles\Elements\SocialEmbed;
12
  use Facebook\InstantArticles\Elements\InstantArticle;
13
  use Facebook\InstantArticles\Transformer\Warnings\InvalidSelector;
 
14
 
 
 
 
15
  class SocialEmbedRule extends ConfigurationSelectorRule
16
  {
17
  const PROPERTY_IFRAME = 'socialembed.iframe';
@@ -88,6 +92,15 @@ class SocialEmbedRule extends ConfigurationSelectorRule
88
  $transformer->transform($social_embed, $node);
89
  $transformer->suppress_warnings = $suppress_warnings;
90
 
 
 
 
 
 
 
 
 
 
91
  return $instant_article;
92
  }
93
  }
11
  use Facebook\InstantArticles\Elements\SocialEmbed;
12
  use Facebook\InstantArticles\Elements\InstantArticle;
13
  use Facebook\InstantArticles\Transformer\Warnings\InvalidSelector;
14
+ use Facebook\InstantArticles\Transformer\Warnings\DeprecatedRuleWarning;
15
 
16
+ /**
17
+ * @deprecated
18
+ */
19
  class SocialEmbedRule extends ConfigurationSelectorRule
20
  {
21
  const PROPERTY_IFRAME = 'socialembed.iframe';
92
  $transformer->transform($social_embed, $node);
93
  $transformer->suppress_warnings = $suppress_warnings;
94
 
95
+ $transformer->addWarning(
96
+ new DeprecatedRuleWarning(
97
+ 'The rule SocialEmbedRule is deprecated. Use InteractiveRule instead.',
98
+ $instant_article,
99
+ $node,
100
+ $this
101
+ )
102
+ );
103
+
104
  return $instant_article;
105
  }
106
  }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/SponsorRule.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2016-present, Facebook, Inc.
4
+ * All rights reserved.
5
+ *
6
+ * This source code is licensed under the license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+ namespace Facebook\InstantArticles\Transformer\Rules;
10
+
11
+ use Facebook\InstantArticles\Elements\Header;
12
+ use Facebook\InstantArticles\Elements\Sponsor;
13
+ use Facebook\InstantArticles\Validators\Type;
14
+
15
+ class SponsorRule extends ConfigurationSelectorRule
16
+ {
17
+ const PROPERTY_SPONSOR_PAGE_URL = 'sponsor.page_url';
18
+
19
+ public function getContextClass()
20
+ {
21
+ return Header::getClassName();
22
+ }
23
+
24
+ public static function create()
25
+ {
26
+ return new SponsorRule();
27
+ }
28
+
29
+ public static function createFrom($configuration)
30
+ {
31
+ $sponsor_rule = SponsorRule::create();
32
+
33
+ $sponsor_rule->withSelector($configuration['selector']);
34
+ $sponsor_rule->withProperty(
35
+ self::PROPERTY_SPONSOR_PAGE_URL,
36
+ self::retrieveProperty($configuration, self::PROPERTY_SPONSOR_PAGE_URL)
37
+ );
38
+
39
+ return $sponsor_rule;
40
+ }
41
+
42
+ public function apply($transformer, $header, $node)
43
+ {
44
+ $page_url = $this->getProperty(self::PROPERTY_SPONSOR_PAGE_URL, $node);
45
+ if ($page_url && !Type::isTextEmpty($page_url)) {
46
+ $sponsor = Sponsor::create();
47
+ $header->withSponsor($sponsor);
48
+ $sponsor->withPageUrl($page_url);
49
+ }
50
+ return $header;
51
+ }
52
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Transformer.php CHANGED
@@ -41,6 +41,11 @@ class Transformer
41
  */
42
  private static $allClassTypes = [];
43
 
 
 
 
 
 
44
  /**
45
  * Gets all types a given class is, including itself, parent classes and interfaces.
46
  *
@@ -107,6 +112,14 @@ class Transformer
107
  $this->warnings[] = $warning;
108
  }
109
 
 
 
 
 
 
 
 
 
110
  /**
111
  * @param InstantArticle $context
112
  * @param \DOMNode $node
@@ -118,6 +131,7 @@ class Transformer
118
  if (Type::is($context, InstantArticle::getClassName())) {
119
  $context->addMetaProperty('op:generator:transformer', 'facebook-instant-articles-sdk-php');
120
  $context->addMetaProperty('op:generator:transformer:version', InstantArticle::CURRENT_VERSION);
 
121
  }
122
 
123
  $log = \Logger::getLogger('facebook-instantarticles-transformer');
@@ -135,6 +149,7 @@ class Transformer
135
  foreach ($node->childNodes as $child) {
136
  $matched = false;
137
  $log->debug("===========================");
 
138
 
139
  // Get all classes and interfaces this context extends/implements
140
  $contextClassNames = self::getAllClassTypes($context->getClassName());
@@ -187,13 +202,6 @@ class Transformer
187
  }
188
  }
189
 
190
- if (Type::is($context, InstantArticle::getClassName())) {
191
- $ia_warnings = InstantArticleValidator::check($context);
192
- foreach ($ia_warnings as $ia_warning) {
193
- $this->addWarning($ia_warning);
194
- }
195
- }
196
-
197
  return $context;
198
  }
199
 
41
  */
42
  private static $allClassTypes = [];
43
 
44
+ /**
45
+ * @var InstantArticle the initial context.
46
+ */
47
+ private $instantArticle;
48
+
49
  /**
50
  * Gets all types a given class is, including itself, parent classes and interfaces.
51
  *
112
  $this->warnings[] = $warning;
113
  }
114
 
115
+ /**
116
+ * @return InstantArticle the initial context of this Transformer
117
+ */
118
+ public function getInstantArticle()
119
+ {
120
+ return $this->instantArticle;
121
+ }
122
+
123
  /**
124
  * @param InstantArticle $context
125
  * @param \DOMNode $node
131
  if (Type::is($context, InstantArticle::getClassName())) {
132
  $context->addMetaProperty('op:generator:transformer', 'facebook-instant-articles-sdk-php');
133
  $context->addMetaProperty('op:generator:transformer:version', InstantArticle::CURRENT_VERSION);
134
+ $this->instantArticle = $context;
135
  }
136
 
137
  $log = \Logger::getLogger('facebook-instantarticles-transformer');
149
  foreach ($node->childNodes as $child) {
150
  $matched = false;
151
  $log->debug("===========================");
152
+ $log->debug($child->ownerDocument->saveHtml($child));
153
 
154
  // Get all classes and interfaces this context extends/implements
155
  $contextClassNames = self::getAllClassTypes($context->getClassName());
202
  }
203
  }
204
 
 
 
 
 
 
 
 
205
  return $context;
206
  }
207
 
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Warnings/DeprecatedRuleWarning.php ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2016-present, Facebook, Inc.
4
+ * All rights reserved.
5
+ *
6
+ * This source code is licensed under the license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+ namespace Facebook\InstantArticles\Transformer\Warnings;
10
+
11
+ use Facebook\InstantArticles\Elements\Element;
12
+ use Facebook\InstantArticles\Validators\Type;
13
+
14
+ class DeprecatedRuleWarning
15
+ {
16
+ /**
17
+ * @var string
18
+ */
19
+ private $message;
20
+
21
+ /**
22
+ * @var Element
23
+ */
24
+ private $context;
25
+
26
+ /**
27
+ * @var \DOMNode
28
+ */
29
+ private $node;
30
+
31
+ /**
32
+ * @var ConfigurationSelectorRule
33
+ */
34
+ private $rule;
35
+
36
+ /**
37
+ * @param string $message
38
+ * @param Element $context
39
+ * @param \DOMNode $node
40
+ * @param ConfigurationSelectorRule $rule
41
+ */
42
+ public function __construct($message, $context, $node, $rule)
43
+ {
44
+ $this->message = $message;
45
+ $this->context = $context;
46
+ $this->node = $node;
47
+ $this->rule = $rule;
48
+ }
49
+
50
+ /**
51
+ * @return string
52
+ */
53
+ public function __toString()
54
+ {
55
+ return $this->message;
56
+ }
57
+
58
+ /**
59
+ * @return Element
60
+ */
61
+ public function getContext()
62
+ {
63
+ return $this->context;
64
+ }
65
+
66
+ /**
67
+ * @return \DOMNode
68
+ */
69
+ public function getNode()
70
+ {
71
+ return $this->node;
72
+ }
73
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Warnings/NoRootInstantArticleFoundWarning.php ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2016-present, Facebook, Inc.
4
+ * All rights reserved.
5
+ *
6
+ * This source code is licensed under the license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+ namespace Facebook\InstantArticles\Transformer\Warnings;
10
+
11
+ use Facebook\InstantArticles\Elements\Element;
12
+ use Facebook\InstantArticles\Validators\Type;
13
+
14
+ class NoRootInstantArticleFoundWarning
15
+ {
16
+ /**
17
+ * @var Element
18
+ */
19
+ private $element;
20
+
21
+ /**
22
+ * @var DOMNode
23
+ */
24
+ private $node;
25
+
26
+ /**
27
+ * @var array the configuration content
28
+ */
29
+ private $configuration;
30
+
31
+ /**
32
+ * @param Element $element
33
+ * @param DOMNode $node
34
+ */
35
+ public function __construct($element, $node = null)
36
+ {
37
+ $this->element = $element;
38
+ $this->node = $node;
39
+ }
40
+
41
+ /**
42
+ * @return string
43
+ */
44
+ public function __toString()
45
+ {
46
+ return $this->formatWarningMessage();
47
+ }
48
+
49
+ /**
50
+ * @return Element
51
+ */
52
+ public function getElement()
53
+ {
54
+ return $this->element;
55
+ }
56
+
57
+ /**
58
+ * @return DOMNode
59
+ */
60
+ public function getNode()
61
+ {
62
+ return $this->node;
63
+ }
64
+
65
+ private function formatWarningMessage()
66
+ {
67
+ $node_string = $this->node->ownerDocument->saveHtml($this->node);
68
+ return "No instant article was informed in the context for Transformer. This element will be lost during transformation: " . $node_string;
69
+ }
70
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Warnings/ValidatorWarning.php CHANGED
@@ -71,9 +71,9 @@ class ValidatorWarning
71
  $simple_class_name = substr(strrchr($this->element->getClassName(), '\\'), 1);
72
 
73
  if (!isset($this->configuration['warning_messages'][$simple_class_name])) {
74
- $message = 'Invalid content on the object: '.$object;
75
  } else {
76
- $message = $this->configuration['warning_messages'][$simple_class_name] . 'Element content: '.$object;
77
  }
78
  return $message;
79
  }
71
  $simple_class_name = substr(strrchr($this->element->getClassName(), '\\'), 1);
72
 
73
  if (!isset($this->configuration['warning_messages'][$simple_class_name])) {
74
+ $message = 'Invalid content on the object.';
75
  } else {
76
+ $message = $this->configuration['warning_messages'][$simple_class_name];
77
  }
78
  return $message;
79
  }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Warnings/validator_warning_messages.ini CHANGED
@@ -35,7 +35,7 @@ Pullquote = "This is a text container that must not be empty nor contain only wh
35
  RelatedArticles = "RelatedArticles must have at least one of its items valid."
36
  RelatedItem = "RelatedItem must have a valid URL link."
37
  Slideshow = "Slideshow must have at least one valid Image or Video."
38
- SocialEmbed = "SocialEmbed must have a URL and/or HTML."
39
  Span = "This is a text container that must not be empty nor contain only whitespace characters such as spaces, tabs, new lines or &nbsp;."
40
  TextContainer = "This is a text container that must not be empty nor contain only whitespace characters such as spaces, tabs, new lines or &nbsp;."
41
  Time = "Time must have datetime set."
35
  RelatedArticles = "RelatedArticles must have at least one of its items valid."
36
  RelatedItem = "RelatedItem must have a valid URL link."
37
  Slideshow = "Slideshow must have at least one valid Image or Video."
38
+ SocialEmbed = "SocialEmbed must have a URL and/or HTML. SocialEmbed is deprecated, use Interactive instead."
39
  Span = "This is a text container that must not be empty nor contain only whitespace characters such as spaces, tabs, new lines or &nbsp;."
40
  TextContainer = "This is a text container that must not be empty nor contain only whitespace characters such as spaces, tabs, new lines or &nbsp;."
41
  Time = "Time must have datetime set."
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Validators/InstantArticleValidator.php CHANGED
@@ -10,6 +10,7 @@ namespace Facebook\InstantArticles\Validators;
10
 
11
  use Facebook\InstantArticles\Elements\InstantArticle;
12
  use Facebook\InstantArticles\Elements\Container;
 
13
  use Facebook\InstantArticles\Transformer\Warnings\ValidatorWarning;
14
 
15
  /**
@@ -42,7 +43,7 @@ class InstantArticleValidator
42
  public static function getReport($elements, &$warnings)
43
  {
44
  foreach ($elements as $element) {
45
- if (!$element->isValid()) {
46
  // Adds a warning to the result report.
47
  $warnings[] = new ValidatorWarning($element);
48
  }
10
 
11
  use Facebook\InstantArticles\Elements\InstantArticle;
12
  use Facebook\InstantArticles\Elements\Container;
13
+ use Facebook\InstantArticles\Elements\Paragraph;
14
  use Facebook\InstantArticles\Transformer\Warnings\ValidatorWarning;
15
 
16
  /**
43
  public static function getReport($elements, &$warnings)
44
  {
45
  foreach ($elements as $element) {
46
+ if (!$element->isValid() && $element->isEmptyValidationEnabled()) {
47
  // Adds a warning to the result report.
48
  $warnings[] = new ValidatorWarning($element);
49
  }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Client/ClientTest.php CHANGED
@@ -38,30 +38,74 @@ class ClientTest extends \PHPUnit_Framework_TestCase
38
 
39
  public function testImportArticle()
40
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  $this->facebook
42
  ->expects($this->once())
43
  ->method('post')
44
  ->with('PAGE_ID' . Client::EDGE_NAME, [
45
  'html_source' => $this->article->render(),
46
- 'take_live' => false,
47
  'development_mode' => false,
48
- ]);
 
49
 
50
- $this->client->importArticle($this->article);
 
51
  }
52
 
53
- public function testImportArticleTakeLive()
54
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  $this->facebook
56
  ->expects($this->once())
57
  ->method('post')
58
  ->with('PAGE_ID' . Client::EDGE_NAME, [
59
  'html_source' => $this->article->render(),
60
- 'take_live' => true,
61
  'development_mode' => false,
62
- ]);
 
63
 
64
- $this->client->importArticle($this->article, true);
 
65
  }
66
 
67
  /**
@@ -104,35 +148,81 @@ class ClientTest extends \PHPUnit_Framework_TestCase
104
  "PAGE_ID",
105
  true // developmentMode
106
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  $this->facebook
108
  ->expects($this->once())
109
  ->method('post')
110
  ->with('PAGE_ID' . Client::EDGE_NAME, [
111
  'html_source' => $this->article->render(),
112
- 'take_live' => false,
113
  'development_mode' => true,
114
- ]);
 
115
 
116
- $this->client->importArticle($this->article);
 
117
  }
118
 
119
- public function testImportArticleDevelopmentModeTakeLive()
120
  {
121
  $this->client = new Client(
122
  $this->facebook,
123
  "PAGE_ID",
124
  true // developmentMode
125
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  $this->facebook
127
  ->expects($this->once())
128
  ->method('post')
129
  ->with('PAGE_ID' . Client::EDGE_NAME, [
130
  'html_source' => $this->article->render(),
131
- 'take_live' => false,
132
  'development_mode' => true,
133
- ]);
 
134
 
135
- $this->client->importArticle($this->article, true);
 
136
  }
137
 
138
  public function testGetArticleIDFromCanonicalURL()
@@ -212,6 +302,97 @@ class ClientTest extends \PHPUnit_Framework_TestCase
212
  $this->assertEquals($expectedArticleID, $articleID);
213
  }
214
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
215
  public function testGetLastSubmissionStatus()
216
  {
217
  $articleID = '123';
@@ -296,4 +477,157 @@ class ClientTest extends \PHPUnit_Framework_TestCase
296
  $status->getMessages()[3]->getMessage()
297
  );
298
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
299
  }
38
 
39
  public function testImportArticle()
40
  {
41
+ $expectedSubmissionStatusID = 1;
42
+
43
+ $serverResponseMock =
44
+ $this->getMockBuilder('Facebook\FacebookResponse')
45
+ ->disableOriginalConstructor()
46
+ ->getMock();
47
+ $graphNodeMock =
48
+ $this->getMockBuilder('Facebook\GraphNodes\GraphNode')
49
+ ->disableOriginalConstructor()
50
+ ->getMock();
51
+ $serverResponseMock
52
+ ->expects($this->once())
53
+ ->method('getGraphNode')
54
+ ->willReturn($graphNodeMock);
55
+ $graphNodeMock
56
+ ->expects($this->once())
57
+ ->method('getField')
58
+ ->with('id')
59
+ ->willReturn($expectedSubmissionStatusID);
60
+
61
  $this->facebook
62
  ->expects($this->once())
63
  ->method('post')
64
  ->with('PAGE_ID' . Client::EDGE_NAME, [
65
  'html_source' => $this->article->render(),
66
+ 'published' => false,
67
  'development_mode' => false,
68
+ ])
69
+ ->willReturn($serverResponseMock);
70
 
71
+ $resultSubmissionStatusID = $this->client->importArticle($this->article);
72
+ $this->assertEquals($expectedSubmissionStatusID, $resultSubmissionStatusID);
73
  }
74
 
75
+ public function testImportArticlePublished()
76
  {
77
+ $expectedSubmissionStatusID = 1;
78
+
79
+ $serverResponseMock =
80
+ $this->getMockBuilder('Facebook\FacebookResponse')
81
+ ->disableOriginalConstructor()
82
+ ->getMock();
83
+ $graphNodeMock =
84
+ $this->getMockBuilder('Facebook\GraphNodes\GraphNode')
85
+ ->disableOriginalConstructor()
86
+ ->getMock();
87
+ $serverResponseMock
88
+ ->expects($this->once())
89
+ ->method('getGraphNode')
90
+ ->willReturn($graphNodeMock);
91
+ $graphNodeMock
92
+ ->expects($this->once())
93
+ ->method('getField')
94
+ ->with('id')
95
+ ->willReturn($expectedSubmissionStatusID);
96
+
97
  $this->facebook
98
  ->expects($this->once())
99
  ->method('post')
100
  ->with('PAGE_ID' . Client::EDGE_NAME, [
101
  'html_source' => $this->article->render(),
102
+ 'published' => true,
103
  'development_mode' => false,
104
+ ])
105
+ ->willReturn($serverResponseMock);
106
 
107
+ $resultSubmissionStatusID = $this->client->importArticle($this->article, true);
108
+ $this->assertEquals($expectedSubmissionStatusID, $resultSubmissionStatusID);
109
  }
110
 
111
  /**
148
  "PAGE_ID",
149
  true // developmentMode
150
  );
151
+
152
+ $expectedSubmissionStatusID = 1;
153
+
154
+ $serverResponseMock =
155
+ $this->getMockBuilder('Facebook\FacebookResponse')
156
+ ->disableOriginalConstructor()
157
+ ->getMock();
158
+ $graphNodeMock =
159
+ $this->getMockBuilder('Facebook\GraphNodes\GraphNode')
160
+ ->disableOriginalConstructor()
161
+ ->getMock();
162
+ $serverResponseMock
163
+ ->expects($this->once())
164
+ ->method('getGraphNode')
165
+ ->willReturn($graphNodeMock);
166
+ $graphNodeMock
167
+ ->expects($this->once())
168
+ ->method('getField')
169
+ ->with('id')
170
+ ->willReturn($expectedSubmissionStatusID);
171
+
172
  $this->facebook
173
  ->expects($this->once())
174
  ->method('post')
175
  ->with('PAGE_ID' . Client::EDGE_NAME, [
176
  'html_source' => $this->article->render(),
177
+ 'published' => false,
178
  'development_mode' => true,
179
+ ])
180
+ ->willReturn($serverResponseMock);
181
 
182
+ $resultSubmissionStatusID = $this->client->importArticle($this->article);
183
+ $this->assertEquals($expectedSubmissionStatusID, $resultSubmissionStatusID);
184
  }
185
 
186
+ public function testImportArticleDevelopmentModePublished()
187
  {
188
  $this->client = new Client(
189
  $this->facebook,
190
  "PAGE_ID",
191
  true // developmentMode
192
  );
193
+
194
+ $expectedSubmissionStatusID = 1;
195
+
196
+ $serverResponseMock =
197
+ $this->getMockBuilder('Facebook\FacebookResponse')
198
+ ->disableOriginalConstructor()
199
+ ->getMock();
200
+ $graphNodeMock =
201
+ $this->getMockBuilder('Facebook\GraphNodes\GraphNode')
202
+ ->disableOriginalConstructor()
203
+ ->getMock();
204
+ $serverResponseMock
205
+ ->expects($this->once())
206
+ ->method('getGraphNode')
207
+ ->willReturn($graphNodeMock);
208
+ $graphNodeMock
209
+ ->expects($this->once())
210
+ ->method('getField')
211
+ ->with('id')
212
+ ->willReturn($expectedSubmissionStatusID);
213
+
214
  $this->facebook
215
  ->expects($this->once())
216
  ->method('post')
217
  ->with('PAGE_ID' . Client::EDGE_NAME, [
218
  'html_source' => $this->article->render(),
219
+ 'published' => false,
220
  'development_mode' => true,
221
+ ])
222
+ ->willReturn($serverResponseMock);
223
 
224
+ $resultSubmissionStatusID = $this->client->importArticle($this->article, true);
225
+ $this->assertEquals($expectedSubmissionStatusID, $resultSubmissionStatusID);
226
  }
227
 
228
  public function testGetArticleIDFromCanonicalURL()
302
  $this->assertEquals($expectedArticleID, $articleID);
303
  }
304
 
305
+ public function testDevelopmentModeGetArticleIDFromCanonicalURL()
306
+ {
307
+ $canonicalURL = "http://facebook.com";
308
+
309
+ $expectedArticleID = 123;
310
+
311
+ $serverResponseMock =
312
+ $this->getMockBuilder('Facebook\FacebookResponse')
313
+ ->disableOriginalConstructor()
314
+ ->getMock();
315
+ $graphNodeMock =
316
+ $this->getMockBuilder('Facebook\GraphNodes\GraphNode')
317
+ ->disableOriginalConstructor()
318
+ ->getMock();
319
+ $instantArticleMock =
320
+ $this->getMockBuilder('Facebook\GraphNodes\GraphNode')
321
+ ->disableOriginalConstructor()
322
+ ->getMock();
323
+
324
+ $instantArticleMock
325
+ ->expects($this->once())
326
+ ->method('getField')
327
+ ->with($this->equalTo('id'))
328
+ ->willReturn($expectedArticleID);
329
+ $graphNodeMock
330
+ ->expects($this->once())
331
+ ->method('getField')
332
+ ->with($this->equalTo('development_instant_article'))
333
+ ->willReturn($instantArticleMock);
334
+ $serverResponseMock
335
+ ->expects($this->once())
336
+ ->method('getGraphNode')
337
+ ->willReturn($graphNodeMock);
338
+ $this->facebook
339
+ ->expects($this->once())
340
+ ->method('get')
341
+ ->with($this->equalTo('?id='.$canonicalURL.'&fields=development_instant_article'))
342
+ ->willReturn($serverResponseMock);
343
+
344
+ // Set up new client in development mode
345
+ $this->client = new Client(
346
+ $this->facebook,
347
+ "PAGE_ID",
348
+ true // developmentMode
349
+ );
350
+
351
+ $articleID = $this->client->getArticleIDFromCanonicalURL($canonicalURL);
352
+ $this->assertEquals($expectedArticleID, $articleID);
353
+ }
354
+
355
+ public function testDevelopmentModeGetArticleIDFromNotFoundCanonicalURL()
356
+ {
357
+ $canonicalURL = "http://facebook.com";
358
+
359
+ $expectedArticleID = null;
360
+
361
+ $serverResponseMock =
362
+ $this->getMockBuilder('Facebook\FacebookResponse')
363
+ ->disableOriginalConstructor()
364
+ ->getMock();
365
+ $graphNodeMock =
366
+ $this->getMockBuilder('Facebook\GraphNodes\GraphNode')
367
+ ->disableOriginalConstructor()
368
+ ->getMock();
369
+
370
+ $graphNodeMock
371
+ ->expects($this->once())
372
+ ->method('getField')
373
+ ->with($this->equalTo('development_instant_article'))
374
+ ->willReturn(null);
375
+ $serverResponseMock
376
+ ->expects($this->once())
377
+ ->method('getGraphNode')
378
+ ->willReturn($graphNodeMock);
379
+ $this->facebook
380
+ ->expects($this->once())
381
+ ->method('get')
382
+ ->with($this->equalTo('?id='.$canonicalURL.'&fields=development_instant_article'))
383
+ ->willReturn($serverResponseMock);
384
+
385
+ // Set up new client in development mode
386
+ $this->client = new Client(
387
+ $this->facebook,
388
+ "PAGE_ID",
389
+ true // developmentMode
390
+ );
391
+
392
+ $articleID = $this->client->getArticleIDFromCanonicalURL($canonicalURL);
393
+ $this->assertEquals($expectedArticleID, $articleID);
394
+ }
395
+
396
  public function testGetLastSubmissionStatus()
397
  {
398
  $articleID = '123';
477
  $status->getMessages()[3]->getMessage()
478
  );
479
  }
480
+
481
+ public function testGetSubmissionStatus()
482
+ {
483
+ $submissionStatusID = '456';
484
+
485
+ $serverResponseMock =
486
+ $this->getMockBuilder('Facebook\FacebookResponse')
487
+ ->disableOriginalConstructor()
488
+ ->getMock();
489
+ $graphNodeMock =
490
+ $this->getMockBuilder('Facebook\GraphNodes\GraphNode')
491
+ ->disableOriginalConstructor()
492
+ ->getMock();
493
+
494
+ $graphNodeMock
495
+ ->expects($this->exactly(2))
496
+ ->method('getField')
497
+ ->withConsecutive(
498
+ [$this->equalTo('errors')],
499
+ [$this->equalTo('status')]
500
+ )
501
+ ->will($this->onConsecutiveCalls(
502
+ [
503
+ [
504
+ "level" => "warning",
505
+ "message" => "Test warning"
506
+ ],
507
+ [
508
+ "level" => "fatal",
509
+ "message" => "Test fatal"
510
+ ],
511
+ [
512
+ "level" => "error",
513
+ "message" => "Test error"
514
+ ],
515
+ [
516
+ "level" => "info",
517
+ "message" => "Test info"
518
+ ]
519
+ ],
520
+ 'success'
521
+ ));
522
+ $serverResponseMock
523
+ ->expects($this->once())
524
+ ->method('getGraphNode')
525
+ ->willReturn($graphNodeMock);
526
+ $this->facebook
527
+ ->expects($this->once())
528
+ ->method('get')
529
+ ->with($this->equalTo($submissionStatusID . '?fields=status,errors'))
530
+ ->willReturn($serverResponseMock);
531
+
532
+ $status = $this->client->getSubmissionStatus($submissionStatusID);
533
+ $this->assertEquals(InstantArticleStatus::SUCCESS, $status->getStatus());
534
+ $this->assertEquals(
535
+ ServerMessage::WARNING,
536
+ $status->getMessages()[0]->getLevel()
537
+ );
538
+ $this->assertEquals(
539
+ 'Test warning',
540
+ $status->getMessages()[0]->getMessage()
541
+ );
542
+ $this->assertEquals(
543
+ $status->getMessages()[1]->getLevel(),
544
+ ServerMessage::FATAL
545
+ );
546
+ $this->assertEquals(
547
+ 'Test fatal',
548
+ $status->getMessages()[1]->getMessage()
549
+ );
550
+ $this->assertEquals(
551
+ ServerMessage::ERROR,
552
+ $status->getMessages()[2]->getLevel()
553
+ );
554
+ $this->assertEquals(
555
+ 'Test error',
556
+ $status->getMessages()[2]->getMessage()
557
+ );
558
+ $this->assertEquals(
559
+ ServerMessage::INFO,
560
+ $status->getMessages()[3]->getLevel()
561
+ );
562
+ $this->assertEquals(
563
+ 'Test info',
564
+ $status->getMessages()[3]->getMessage()
565
+ );
566
+ }
567
+
568
+ public function testGetReviewSubmissionStatus()
569
+ {
570
+ $serverResponseMock =
571
+ $this->getMockBuilder('Facebook\FacebookResponse')
572
+ ->disableOriginalConstructor()
573
+ ->getMock();
574
+ $graphNodeMock =
575
+ $this->getMockBuilder('Facebook\GraphNodes\GraphNode')
576
+ ->disableOriginalConstructor()
577
+ ->getMock();
578
+
579
+ $graphNodeMock
580
+ ->expects($this->once())
581
+ ->method('getField')
582
+ ->with($this->equalTo('instant_articles_review_status'))
583
+ ->willReturn('NOT_SUBMITTED');
584
+ $serverResponseMock
585
+ ->expects($this->once())
586
+ ->method('getGraphNode')
587
+ ->willReturn($graphNodeMock);
588
+
589
+ $this->facebook
590
+ ->expects($this->once())
591
+ ->method('get')
592
+ ->with('me?fields=instant_articles_review_status')
593
+ ->willReturn($serverResponseMock);
594
+
595
+ $result = $this->client->getReviewSubmissionStatus();
596
+ $this->assertEquals('NOT_SUBMITTED', $result);
597
+ }
598
+
599
+ public function testGetArticlesURLs()
600
+ {
601
+ $mockedMap = array(
602
+ array('canonical_url'=>'http://url.com/1'),
603
+ array('canonical_url'=>'http://url.com/2'),
604
+ array('canonical_url'=>'http://url.com/3')
605
+ );
606
+
607
+ $serverResponseMock =
608
+ $this->getMockBuilder('Facebook\FacebookResponse')
609
+ ->disableOriginalConstructor()
610
+ ->getMock();
611
+
612
+ $serverResponseMock
613
+ ->expects($this->once())
614
+ ->method('getGraphEdge')
615
+ ->willReturn($mockedMap);
616
+
617
+ $this->facebook
618
+ ->expects($this->once())
619
+ ->method('get')
620
+ ->with('me/instant_articles?fields=canonical_url&development_mode=false&limit=10')
621
+ ->willReturn($serverResponseMock);
622
+
623
+
624
+ $expected = array(
625
+ 'http://url.com/1',
626
+ 'http://url.com/2',
627
+ 'http://url.com/3'
628
+ );
629
+
630
+ $result = $this->client->getArticlesURLs();
631
+ $this->assertEquals($expected, $result);
632
+ }
633
  }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/AdTest.php CHANGED
@@ -80,13 +80,11 @@ class AdTest extends \PHPUnit_Framework_TestCase
80
  {
81
  $inline =
82
  '<h1>Some custom code</h1>'.
83
- '<script>alert("test");</script>';
84
- $document = new \DOMDocument();
85
- $fragment = $document->createDocumentFragment();
86
- $fragment->appendXML($inline);
87
  $ad =
88
  Ad::create()
89
- ->withHTML($fragment)
90
  ->withHeight(640)
91
  ->withWidth(480);
92
 
@@ -94,7 +92,7 @@ class AdTest extends \PHPUnit_Framework_TestCase
94
  '<figure class="op-ad">'.
95
  '<iframe width="480" height="640">'.
96
  '<h1>Some custom code</h1>'.
97
- '<script>alert("test");</script>'.
98
  '</iframe>'.
99
  '</figure>';
100
 
80
  {
81
  $inline =
82
  '<h1>Some custom code</h1>'.
83
+ '<script>alert("test & more test");</script>';
84
+
 
 
85
  $ad =
86
  Ad::create()
87
+ ->withHTML($inline)
88
  ->withHeight(640)
89
  ->withWidth(480);
90
 
92
  '<figure class="op-ad">'.
93
  '<iframe width="480" height="640">'.
94
  '<h1>Some custom code</h1>'.
95
+ '<script>alert("test & more test");</script>'.
96
  '</iframe>'.
97
  '</figure>';
98
 
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/AnalyticsTest.php CHANGED
@@ -40,20 +40,17 @@ class AnalyticsTest extends \PHPUnit_Framework_TestCase
40
  {
41
  $inline =
42
  '<h1>Some custom code</h1>'.
43
- '<script>alert("test");</script>';
44
- $document = new \DOMDocument();
45
- $fragment = $document->createDocumentFragment();
46
- $fragment->appendXML($inline);
47
 
48
  $analytics =
49
  Analytics::create()
50
- ->withHTML($fragment);
51
 
52
  $expected =
53
  '<figure class="op-tracker">'.
54
  '<iframe>'.
55
  '<h1>Some custom code</h1>'.
56
- '<script>alert("test");</script>'.
57
  '</iframe>'.
58
  '</figure>';
59
 
@@ -74,13 +71,10 @@ class AnalyticsTest extends \PHPUnit_Framework_TestCase
74
  'ga("send", "pageview");'.
75
  '</script>'.
76
  '<!-- End Google Analytics -->';
77
- $document = new \DOMDocument();
78
- $fragment = $document->createDocumentFragment();
79
- $fragment->appendXML($google_analytics);
80
 
81
  $analytics =
82
  Analytics::create()
83
- ->withHTML($fragment);
84
 
85
  $expected =
86
  '<figure class="op-tracker">'.
40
  {
41
  $inline =
42
  '<h1>Some custom code</h1>'.
43
+ '<script>alert("test & more test");</script>';
 
 
 
44
 
45
  $analytics =
46
  Analytics::create()
47
+ ->withHTML($inline);
48
 
49
  $expected =
50
  '<figure class="op-tracker">'.
51
  '<iframe>'.
52
  '<h1>Some custom code</h1>'.
53
+ '<script>alert("test & more test");</script>'.
54
  '</iframe>'.
55
  '</figure>';
56
 
71
  'ga("send", "pageview");'.
72
  '</script>'.
73
  '<!-- End Google Analytics -->';
 
 
 
74
 
75
  $analytics =
76
  Analytics::create()
77
+ ->withHTML($google_analytics);
78
 
79
  $expected =
80
  '<figure class="op-tracker">'.
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/CaptionTest.php CHANGED
@@ -117,6 +117,22 @@ class CaptionTest extends \PHPUnit_Framework_TestCase
117
  $this->assertEquals($expected, $rendered);
118
  }
119
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  public function testRenderWithAllFormating()
121
  {
122
  $caption =
@@ -124,10 +140,11 @@ class CaptionTest extends \PHPUnit_Framework_TestCase
124
  ->appendText('Caption Title')
125
  ->withFontsize(Caption::SIZE_LARGE)
126
  ->withPosition(Caption::POSITION_BELOW)
127
- ->withTextAlignment(Caption::ALIGN_LEFT);
 
128
 
129
  $expected =
130
- '<figcaption class="op-left op-large op-vertical-below">'.
131
  'Caption Title'.
132
  '</figcaption>';
133
 
117
  $this->assertEquals($expected, $rendered);
118
  }
119
 
120
+ public function testRenderWithVerticalAlignment()
121
+ {
122
+ $caption =
123
+ Caption::create()
124
+ ->appendText('Caption Title')
125
+ ->withVerticalAlignment(Caption::VERTICAL_BOTTOM);
126
+
127
+ $expected =
128
+ '<figcaption class="op-vertical-bottom">' .
129
+ 'Caption Title' .
130
+ '</figcaption>';
131
+
132
+ $rendered = $caption->render();
133
+ $this->assertEquals($expected, $rendered);
134
+ }
135
+
136
  public function testRenderWithAllFormating()
137
  {
138
  $caption =
140
  ->appendText('Caption Title')
141
  ->withFontsize(Caption::SIZE_LARGE)
142
  ->withPosition(Caption::POSITION_BELOW)
143
+ ->withTextAlignment(Caption::ALIGN_LEFT)
144
+ ->withVerticalAlignment(Caption::VERTICAL_BOTTOM);
145
 
146
  $expected =
147
+ '<figcaption class="op-left op-vertical-bottom op-large op-vertical-below">'.
148
  'Caption Title'.
149
  '</figcaption>';
150
 
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/CiteTest.php CHANGED
@@ -67,16 +67,33 @@ class CiteTest extends \PHPUnit_Framework_TestCase
67
  $this->assertEquals($expected, $rendered);
68
  }
69
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  public function testRenderWithPositionAndAlignment()
71
  {
72
  $cite =
73
  Cite::create()
74
  ->appendText('Citation simple text.')
75
  ->withPosition(Caption::POSITION_ABOVE)
76
- ->withTextAlignment(Caption::ALIGN_LEFT);
 
77
 
78
  $expected =
79
- '<cite class="op-vertical-above op-left">'.
80
  'Citation simple text.'.
81
  '</cite>';
82
 
67
  $this->assertEquals($expected, $rendered);
68
  }
69
 
70
+ public function testRenderWithVerticalAlign()
71
+ {
72
+ $cite =
73
+ Cite::create()
74
+ ->appendText('Citation simple text.')
75
+ ->withVerticalAlignment(Caption::VERTICAL_TOP);
76
+
77
+ $expected =
78
+ '<cite class="op-vertical-top">' .
79
+ 'Citation simple text.' .
80
+ '</cite>';
81
+
82
+ $rendered = $cite->render();
83
+ $this->assertEquals($expected, $rendered);
84
+ }
85
+
86
  public function testRenderWithPositionAndAlignment()
87
  {
88
  $cite =
89
  Cite::create()
90
  ->appendText('Citation simple text.')
91
  ->withPosition(Caption::POSITION_ABOVE)
92
+ ->withTextAlignment(Caption::ALIGN_LEFT)
93
+ ->withVerticalAlignment(Caption::VERTICAL_TOP);
94
 
95
  $expected =
96
+ '<cite class="op-vertical-above op-left op-vertical-top">'.
97
  'Citation simple text.'.
98
  '</cite>';
99
 
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/HeaderTest.php CHANGED
@@ -24,10 +24,7 @@ class HeaderTest extends \PHPUnit_Framework_TestCase
24
  date_default_timezone_set('UTC');
25
 
26
  $inline =
27
- '<script>alert("test");</script>';
28
- $document = new \DOMDocument();
29
- $fragment = $document->createDocumentFragment();
30
- $fragment->appendXML($inline);
31
 
32
  $header =
33
  Header::create()
@@ -87,7 +84,7 @@ class HeaderTest extends \PHPUnit_Framework_TestCase
87
  ->withWidth(300)
88
  ->withHeight(250)
89
  ->enableDefaultForReuse()
90
- ->withHTML($fragment)
91
  );
92
 
93
  $expected =
@@ -118,7 +115,7 @@ class HeaderTest extends \PHPUnit_Framework_TestCase
118
  '</figure>'.
119
  '<figure class="op-ad">'.
120
  '<iframe width="300" height="250">'.
121
- '<script>alert("test");</script>'.
122
  '</iframe>'.
123
  '</figure>'.
124
  '</section>'.
@@ -214,4 +211,94 @@ class HeaderTest extends \PHPUnit_Framework_TestCase
214
 
215
  $this->assertEquals($expected, $rendered);
216
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
217
  }
24
  date_default_timezone_set('UTC');
25
 
26
  $inline =
27
+ '<script>alert("test & more test");</script>';
 
 
 
28
 
29
  $header =
30
  Header::create()
84
  ->withWidth(300)
85
  ->withHeight(250)
86
  ->enableDefaultForReuse()
87
+ ->withHTML($inline)
88
  );
89
 
90
  $expected =
115
  '</figure>'.
116
  '<figure class="op-ad">'.
117
  '<iframe width="300" height="250">'.
118
+ '<script>alert("test & more test");</script>'.
119
  '</iframe>'.
120
  '</figure>'.
121
  '</section>'.
211
 
212
  $this->assertEquals($expected, $rendered);
213
  }
214
+
215
+ public function testHeaderWithSlideshow()
216
+ {
217
+ $header =
218
+ Header::create()
219
+ ->withTitle(
220
+ H1::create()
221
+ ->appendText('Big Top Title ')
222
+ ->appendText(Bold::create()->appendText('in Bold'))
223
+ )
224
+ ->withSubTitle(
225
+ H2::create()
226
+ ->appendText('Smaller SubTitle ')
227
+ ->appendText(Bold::create()->appendText('in Bold'))
228
+ )
229
+ ->withKicker(
230
+ H3::create()
231
+ ->appendText('Kicker ')
232
+ ->appendText(Bold::create()->appendText('in Bold'))
233
+ )
234
+ ->withCover(
235
+ SlideShow::create()
236
+ ->addImage(Image::create()->withURL('https://jpeg.org/images/jpegls-home.jpg'))
237
+ ->addImage(Image::create()->withURL('https://jpeg.org/images/jpegls-home2.jpg'))
238
+ ->addImage(Image::create()->withURL('https://jpeg.org/images/jpegls-home3.jpg'))
239
+ );
240
+
241
+ $expected =
242
+ '<header>'.
243
+ '<figure class="op-slideshow">'.
244
+ '<figure>'.
245
+ '<img src="https://jpeg.org/images/jpegls-home.jpg"/>'.
246
+ '</figure>'.
247
+ '<figure>'.
248
+ '<img src="https://jpeg.org/images/jpegls-home2.jpg"/>'.
249
+ '</figure>'.
250
+ '<figure>'.
251
+ '<img src="https://jpeg.org/images/jpegls-home3.jpg"/>'.
252
+ '</figure>'.
253
+ '</figure>'.
254
+ '<h1>Big Top Title <b>in Bold</b></h1>'.
255
+ '<h2>Smaller SubTitle <b>in Bold</b></h2>'.
256
+ '<h3 class="op-kicker">Kicker <b>in Bold</b></h3>'.
257
+ '</header>';
258
+
259
+ $rendered = $header->render();
260
+
261
+ $this->assertEquals($expected, $rendered);
262
+ }
263
+
264
+ public function testHeaderWithSponsor()
265
+ {
266
+ $header =
267
+ Header::create()
268
+ ->withTitle(
269
+ H1::create()
270
+ ->appendText('Big Top Title ')
271
+ ->appendText(Bold::create()->appendText('in Bold'))
272
+ )
273
+ ->withSubTitle(
274
+ H2::create()
275
+ ->appendText('Smaller SubTitle ')
276
+ ->appendText(Bold::create()->appendText('in Bold'))
277
+ )
278
+ ->withKicker(
279
+ H3::create()
280
+ ->appendText('Kicker ')
281
+ ->appendText(Bold::create()->appendText('in Bold'))
282
+ )
283
+ ->withSponsor(
284
+ Sponsor::create()
285
+ ->withPageUrl('http://facebook.com/my-sponsor')
286
+ );
287
+
288
+ $expected =
289
+ '<header>'.
290
+ '<h1>Big Top Title <b>in Bold</b></h1>'.
291
+ '<h2>Smaller SubTitle <b>in Bold</b></h2>'.
292
+ '<h3 class="op-kicker">Kicker <b>in Bold</b></h3>'.
293
+ '<ul class="op-sponsors">'.
294
+ '<li>'.
295
+ '<a href="http://facebook.com/my-sponsor" rel="facebook"></a>'.
296
+ '</li>'.
297
+ '</ul>'.
298
+ '</header>';
299
+
300
+ $rendered = $header->render();
301
+
302
+ $this->assertEquals($expected, $rendered);
303
+ }
304
  }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/InstantArticleTest.php CHANGED
@@ -20,10 +20,7 @@ class InstantArticleTest extends \PHPUnit_Framework_TestCase
20
 
21
  $inline =
22
  '<h1>Some custom code</h1>'.
23
- '<script>alert("test");</script>';
24
- $document = new \DOMDocument();
25
- $fragment = $document->createDocumentFragment();
26
- $fragment->appendXML($inline);
27
 
28
  $this->article =
29
  InstantArticle::create()
@@ -133,7 +130,7 @@ class InstantArticleTest extends \PHPUnit_Framework_TestCase
133
  // Analytics
134
  ->addChild(
135
  Analytics::create()
136
- ->withHTML($fragment)
137
  )
138
 
139
  // Footer
@@ -199,7 +196,7 @@ class InstantArticleTest extends \PHPUnit_Framework_TestCase
199
  '<figure class="op-tracker">'.
200
  '<iframe>'.
201
  '<h1>Some custom code</h1>'.
202
- '<script>alert("test");</script>'.
203
  '</iframe>'.
204
  '</figure>'.
205
  '<footer>'.
@@ -270,7 +267,7 @@ class InstantArticleTest extends \PHPUnit_Framework_TestCase
270
  '<figure class="op-tracker">'.
271
  '<iframe>'.
272
  '<h1>Some custom code</h1>'.
273
- '<script>alert("test");</script>'.
274
  '</iframe>'.
275
  '</figure>'.
276
  '<footer>'.
@@ -360,7 +357,7 @@ class InstantArticleTest extends \PHPUnit_Framework_TestCase
360
  '<link rel="canonical" href=""/>'.
361
  '<meta charset="utf-8"/>'.
362
  '<meta property="op:generator" content="facebook-instant-articles-sdk-php"/>'.
363
- '<meta property="op:generator:version" content="1.0.6"/>'.
364
  '<meta property="op:markup_version" content="v1.0"/>'.
365
  '</head>'.
366
  '<body>'.
@@ -412,4 +409,9 @@ class InstantArticleTest extends \PHPUnit_Framework_TestCase
412
  );
413
  $this->assertTrue($ia->isValid());
414
  }
 
 
 
 
 
415
  }
20
 
21
  $inline =
22
  '<h1>Some custom code</h1>'.
23
+ '<script>alert("test & more test");</script>';
 
 
 
24
 
25
  $this->article =
26
  InstantArticle::create()
130
  // Analytics
131
  ->addChild(
132
  Analytics::create()
133
+ ->withHTML($inline)
134
  )
135
 
136
  // Footer
196
  '<figure class="op-tracker">'.
197
  '<iframe>'.
198
  '<h1>Some custom code</h1>'.
199
+ '<script>alert("test & more test");</script>'.
200
  '</iframe>'.
201
  '</figure>'.
202
  '<footer>'.
267
  '<figure class="op-tracker">'.
268
  '<iframe>'.
269
  '<h1>Some custom code</h1>'.
270
+ '<script>alert("test & more test");</script>'.
271
  '</iframe>'.
272
  '</figure>'.
273
  '<footer>'.
357
  '<link rel="canonical" href=""/>'.
358
  '<meta charset="utf-8"/>'.
359
  '<meta property="op:generator" content="facebook-instant-articles-sdk-php"/>'.
360
+ '<meta property="op:generator:version" content="'.InstantArticle::CURRENT_VERSION.'"/>'.
361
  '<meta property="op:markup_version" content="v1.0"/>'.
362
  '</head>'.
363
  '<body>'.
409
  );
410
  $this->assertTrue($ia->isValid());
411
  }
412
+
413
+ public function testImplementsInterface()
414
+ {
415
+ $this->assertInstanceOf('Facebook\InstantArticles\Elements\InstantArticleInterface', $this->article);
416
+ }
417
  }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/InteractiveTest.php CHANGED
@@ -74,12 +74,45 @@ class InteractiveTest extends \PHPUnit_Framework_TestCase
74
  $this->assertEquals($expected, $rendered);
75
  }
76
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  public function testRenderBasicWithColumnWidth()
78
  {
79
  $interactive =
80
  Interactive::create()
81
  ->withSource('http://foo.com/interactive-graphic')
82
- ->withWidth(Interactive::COLUMN_WIDTH);
83
 
84
  $expected =
85
  '<figure class="op-interactive">'.
@@ -95,7 +128,7 @@ class InteractiveTest extends \PHPUnit_Framework_TestCase
95
  $interactive =
96
  Interactive::create()
97
  ->withSource('http://foo.com/interactive-graphic')
98
- ->withWidth(Interactive::NO_MARGIN);
99
 
100
  $expected =
101
  '<figure class="op-interactive">'.
@@ -110,22 +143,19 @@ class InteractiveTest extends \PHPUnit_Framework_TestCase
110
  {
111
  $inline =
112
  '<h1>Some custom code</h1>'.
113
- '<script>alert("test");</script>';
114
- $document = new \DOMDocument();
115
- $fragment = $document->createDocumentFragment();
116
- $fragment->appendXML($inline);
117
 
118
  $interactive =
119
  Interactive::create()
120
- ->withHTML($fragment)
121
  ->withHeight(640)
122
- ->withWidth(Interactive::NO_MARGIN);
123
 
124
  $expected =
125
  '<figure class="op-interactive">'.
126
  '<iframe class="no-margin" height="640">'.
127
  '<h1>Some custom code</h1>'.
128
- '<script>alert("test");</script>'.
129
  '</iframe>'.
130
  '</figure>';
131
 
74
  $this->assertEquals($expected, $rendered);
75
  }
76
 
77
+ public function testRenderBasicWithWidth()
78
+ {
79
+ $interactive =
80
+ Interactive::create()
81
+ ->withSource('http://foo.com/interactive-graphic')
82
+ ->withWidth(640);
83
+
84
+ $expected =
85
+ '<figure class="op-interactive">' .
86
+ '<iframe src="http://foo.com/interactive-graphic" width="640"></iframe>' .
87
+ '</figure>';
88
+
89
+ $rendered = $interactive->render();
90
+ $this->assertEquals($expected, $rendered);
91
+ }
92
+
93
+ public function testRenderBasicWithWidthHeight()
94
+ {
95
+ $interactive =
96
+ Interactive::create()
97
+ ->withSource('http://foo.com/interactive-graphic')
98
+ ->withWidth(1600)
99
+ ->withHeight(900);
100
+
101
+ $expected =
102
+ '<figure class="op-interactive">' .
103
+ '<iframe src="http://foo.com/interactive-graphic" width="1600" height="900"></iframe>' .
104
+ '</figure>';
105
+
106
+ $rendered = $interactive->render();
107
+ $this->assertEquals($expected, $rendered);
108
+ }
109
+
110
  public function testRenderBasicWithColumnWidth()
111
  {
112
  $interactive =
113
  Interactive::create()
114
  ->withSource('http://foo.com/interactive-graphic')
115
+ ->withMargin(Interactive::COLUMN_WIDTH);
116
 
117
  $expected =
118
  '<figure class="op-interactive">'.
128
  $interactive =
129
  Interactive::create()
130
  ->withSource('http://foo.com/interactive-graphic')
131
+ ->withMargin(Interactive::NO_MARGIN);
132
 
133
  $expected =
134
  '<figure class="op-interactive">'.
143
  {
144
  $inline =
145
  '<h1>Some custom code</h1>'.
146
+ '<script>alert("test & more test");</script>';
 
 
 
147
 
148
  $interactive =
149
  Interactive::create()
150
+ ->withHTML($inline)
151
  ->withHeight(640)
152
+ ->withMargin(Interactive::NO_MARGIN);
153
 
154
  $expected =
155
  '<figure class="op-interactive">'.
156
  '<iframe class="no-margin" height="640">'.
157
  '<h1>Some custom code</h1>'.
158
+ '<script>alert("test & more test");</script>'.
159
  '</iframe>'.
160
  '</figure>';
161
 
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/SocialEmbedTest.php CHANGED
@@ -27,7 +27,7 @@ class SocialEmbedTest extends \PHPUnit_Framework_TestCase
27
  ->withSource('http://foo.com');
28
 
29
  $expected =
30
- '<figure class="op-social">'.
31
  '<iframe src="http://foo.com"></iframe>'.
32
  '</figure>';
33
 
@@ -46,7 +46,7 @@ class SocialEmbedTest extends \PHPUnit_Framework_TestCase
46
  );
47
 
48
  $expected =
49
- '<figure class="op-social">'.
50
  '<iframe src="http://foo.com"></iframe>'.
51
  '<figcaption>Some caption to the embed</figcaption>'.
52
  '</figure>';
@@ -59,20 +59,17 @@ class SocialEmbedTest extends \PHPUnit_Framework_TestCase
59
  {
60
  $inline =
61
  '<h1>Some custom code</h1>'.
62
- '<script>alert("test");</script>';
63
- $document = new \DOMDocument();
64
- $fragment = $document->createDocumentFragment();
65
- $fragment->appendXML($inline);
66
 
67
  $social_embed =
68
  SocialEmbed::create()
69
- ->withHTML($fragment);
70
 
71
  $expected =
72
- '<figure class="op-social">'.
73
  '<iframe>'.
74
  '<h1>Some custom code</h1>'.
75
- '<script>alert("test");</script>'.
76
  '</iframe>'.
77
  '</figure>';
78
 
@@ -89,7 +86,7 @@ class SocialEmbedTest extends \PHPUnit_Framework_TestCase
89
  ->withHeight(480);
90
 
91
  $expected =
92
- '<figure class="op-social">'.
93
  '<iframe src="http://foo.com" width="640" height="480"></iframe>'.
94
  '</figure>';
95
 
27
  ->withSource('http://foo.com');
28
 
29
  $expected =
30
+ '<figure class="op-interactive">'.
31
  '<iframe src="http://foo.com"></iframe>'.
32
  '</figure>';
33
 
46
  );
47
 
48
  $expected =
49
+ '<figure class="op-interactive">'.
50
  '<iframe src="http://foo.com"></iframe>'.
51
  '<figcaption>Some caption to the embed</figcaption>'.
52
  '</figure>';
59
  {
60
  $inline =
61
  '<h1>Some custom code</h1>'.
62
+ '<script>alert("test & more test");</script>';
 
 
 
63
 
64
  $social_embed =
65
  SocialEmbed::create()
66
+ ->withHTML($inline);
67
 
68
  $expected =
69
+ '<figure class="op-interactive">'.
70
  '<iframe>'.
71
  '<h1>Some custom code</h1>'.
72
+ '<script>alert("test & more test");</script>'.
73
  '</iframe>'.
74
  '</figure>';
75
 
86
  ->withHeight(480);
87
 
88
  $expected =
89
+ '<figure class="op-interactive">'.
90
  '<iframe src="http://foo.com" width="640" height="480"></iframe>'.
91
  '</figure>';
92
 
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/SponsorTest.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2016-present, Facebook, Inc.
4
+ * All rights reserved.
5
+ *
6
+ * This source code is licensed under the license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+ namespace Facebook\InstantArticles\Elements;
10
+
11
+ class SponsorTest extends \PHPUnit_Framework_TestCase
12
+ {
13
+ public function testRenderEmpty()
14
+ {
15
+ $list =
16
+ Sponsor::create();
17
+
18
+ $expected = '';
19
+
20
+ $rendered = $list->render();
21
+ $this->assertEquals($expected, $rendered);
22
+ }
23
+
24
+ public function testRenderWithSponsor()
25
+ {
26
+ $list =
27
+ Sponsor::create()
28
+ ->withPageUrl('http://facebook.com/my-sponsor');
29
+
30
+ $expected =
31
+ '<ul class="op-sponsors">'.
32
+ '<li>'.
33
+ '<a href="http://facebook.com/my-sponsor" rel="facebook"></a>'.
34
+ '</li>'.
35
+ '</ul>';
36
+
37
+ $rendered = $list->render();
38
+ $this->assertEquals($expected, $rendered);
39
+ }
40
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/Validators/InstantArticleValidatorTest.php CHANGED
@@ -90,7 +90,7 @@ class InstantArticleValidatorTest extends \PHPUnit_Framework_TestCase
90
  '<link rel="canonical" href=""/>'.
91
  '<meta charset="utf-8"/>'.
92
  '<meta property="op:generator" content="facebook-instant-articles-sdk-php"/>'.
93
- '<meta property="op:generator:version" content="1.0.6"/>'.
94
  '<meta property="op:markup_version" content="v1.0"/>'.
95
  '</head>'.
96
  '<body>'.
90
  '<link rel="canonical" href=""/>'.
91
  '<meta charset="utf-8"/>'.
92
  '<meta property="op:generator" content="facebook-instant-articles-sdk-php"/>'.
93
+ '<meta property="op:generator:version" content="'.InstantArticle::CURRENT_VERSION.'"/>'.
94
  '<meta property="op:markup_version" content="v1.0"/>'.
95
  '</head>'.
96
  '<body>'.
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Parser/ParserTest.php ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2016-present, Facebook, Inc.
4
+ * All rights reserved.
5
+ *
6
+ * This source code is licensed under the license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+ namespace Facebook\InstantArticles\Parser;
10
+
11
+ class ParserTest extends \PHPUnit_Framework_TestCase
12
+ {
13
+ protected function setUp()
14
+ {
15
+ \Logger::configure(
16
+ [
17
+ 'rootLogger' => [
18
+ 'appenders' => ['facebook-instantarticles-transformer']
19
+ ],
20
+ 'appenders' => [
21
+ 'facebook-instantarticles-transformer' => [
22
+ 'class' => 'LoggerAppenderConsole',
23
+ 'threshold' => 'INFO',
24
+ 'layout' => [
25
+ 'class' => 'LoggerLayoutSimple'
26
+ ]
27
+ ]
28
+ ]
29
+ ]
30
+ );
31
+ }
32
+
33
+ public function testSelfParse()
34
+ {
35
+ $html_file = file_get_contents(__DIR__ . '/instant-article-example.html');
36
+
37
+ libxml_use_internal_errors(true);
38
+ $document = new \DOMDocument();
39
+ $document->loadHTML($html_file);
40
+ libxml_use_internal_errors(false);
41
+
42
+ $parser = new Parser();
43
+ $instant_article = $parser->parse($document);
44
+ $instant_article->addMetaProperty('op:generator:version', '1.0.0');
45
+ $instant_article->addMetaProperty('op:generator:transformer:version', '1.0.0');
46
+ $result = $instant_article->render('', true)."\n";
47
+
48
+ $this->assertEquals($html_file, $result);
49
+ }
50
+
51
+ public function testSelfParseString()
52
+ {
53
+ $html_file = file_get_contents(__DIR__ . '/instant-article-example.html');
54
+
55
+ $parser = new Parser();
56
+ $instant_article = $parser->parse($html_file);
57
+ $instant_article->addMetaProperty('op:generator:version', '1.0.0');
58
+ $instant_article->addMetaProperty('op:generator:transformer:version', '1.0.0');
59
+ $result = $instant_article->render('', true)."\n";
60
+
61
+ $this->assertEquals($html_file, $result);
62
+ }
63
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Parser/instant-article-example.html ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <html>
2
+ <head>
3
+ <link rel="canonical" href="http://foo.com/article.html"/>
4
+ <meta charset="utf-8"/>
5
+ <meta property="op:generator" content="facebook-instant-articles-sdk-php"/>
6
+ <meta property="op:generator:version" content="1.0.0"/>
7
+ <meta property="op:generator:transformer" content="facebook-instant-articles-sdk-php"/>
8
+ <meta property="op:generator:transformer:version" content="1.0.0"/>
9
+ <meta property="op:markup_version" content="v1.0"/>
10
+ </head>
11
+ <body>
12
+ <article>
13
+ <header>
14
+ <figure>
15
+ <img src="https://jpeg.org/images/jpegls-home.jpg"/>
16
+ <figcaption><h1>Image Name</h1>Some text on text node<cite>Some caption to the image</cite></figcaption>
17
+ </figure>
18
+ <h1>Big Top <b>Title</b></h1>
19
+ <h2>Smaller <b>SubTitle</b></h2>
20
+ <time class="op-published" datetime="1984-08-14T19:30:00+00:00">August 14th, 7:30pm</time>
21
+ <time class="op-modified" datetime="2016-02-10T10:00:00+00:00">February 10th, 10:00am</time>
22
+ <address><a href="#" title="Title of author">Author Name</a>
23
+ Author more detailed description
24
+ Even more
25
+ </address>
26
+ <address><a href="http://facebook.com/author" rel="facebook">Author in FB</a>
27
+ Author user in facebook
28
+ </address>
29
+ <address><a title="PHP Programmer">Developer</a>
30
+ </address>
31
+ <h3 class="op-kicker">Some kicker of this article</h3>
32
+ </header>
33
+ <p>Some text to be within a paragraph for testing.</p>
34
+ <figure data-feedback="fb:likes">
35
+ <img src="http://mydomain.com/path/to/img.jpg"/>
36
+ <audio title="audio title" autoplay="autoplay" muted="muted">
37
+ <source src="http://foo.com/mp3"/>
38
+ </audio>
39
+ </figure>
40
+ <figure data-feedback="fb:comments">
41
+ <img src="http://mydomain.com/path/to/img.jpg"/>
42
+ <script type="application/json" class="op-geotag">
43
+ {
44
+ "type": "Feature",
45
+ "geometry": {
46
+ "type": "Point",
47
+ "coordinates": [23.166667, 89.216667]
48
+ },
49
+ "properties": {
50
+ "title": "Jessore, Bangladesh",
51
+ "radius": 750000,
52
+ "pivot": true,
53
+ "style": "satellite",
54
+ }
55
+ }
56
+ </script>
57
+ <audio title="audio title" autoplay="autoplay" muted="muted">
58
+ <source src="http://foo.com/mp3"/>
59
+ </audio>
60
+ </figure>
61
+ <figure data-feedback="fb:likes,fb:comments">
62
+ <img src="https://jpeg.org/images/jpegls-home.jpg"/>
63
+ <figcaption><h1>Image Name</h1>Some text on text node<cite>Some caption to the image</cite></figcaption>
64
+ </figure>
65
+ <p>Other text to be within a second paragraph for testing.</p>
66
+ <figure class="op-slideshow">
67
+ <figure>
68
+ <img src="https://jpeg.org/images/jpegls-home.jpg"/>
69
+ </figure>
70
+ <figure>
71
+ <img src="https://jpeg.org/images/jpegls-home2.jpg"/>
72
+ </figure>
73
+ <figure>
74
+ <img src="https://jpeg.org/images/jpegls-home3.jpg"/>
75
+ </figure>
76
+ <figcaption><h1>Image Name</h1>Some text on text node<cite>Some caption to the image</cite></figcaption>
77
+ <audio title="audio title" autoplay="autoplay" muted="muted">
78
+ <source src="http://foo.com/mp3"/>
79
+ </audio>
80
+ </figure>
81
+ <ol>
82
+ <li>First list item</li>
83
+ <li>One paragraph on the list</li>
84
+ <li>On the span</li>
85
+ <li>Text inside div?</li>
86
+ <li>Other <a href="#">paragraph</a> on the li</li>
87
+ <li>Last list item</li>
88
+ </ol>
89
+ <p>Some text to be within a paragraph for testing.</p>
90
+ <figure class="op-interactive">
91
+ <iframe src="http://example.com/custom-interactive" class="column-width" height="60">
92
+ <h1>Some custom code</h1>
93
+ <script>alert("test & more test");</script></iframe>
94
+ <figcaption>This graphic is awesome.</figcaption>
95
+ </figure>
96
+ <figure class="op-ad">
97
+ <iframe src="http://foo.com"></iframe>
98
+ </figure>
99
+ <blockquote>Some blockquotes creates <b>magic</b> in an article</blockquote>
100
+ <figure class="op-map">
101
+ <script type="application/json" class="op-geotag">
102
+ {
103
+ "type": "Feature",
104
+ "geometry":
105
+ {
106
+ "type": "Point",
107
+ "coordinates": [23.166667, 89.216667]
108
+ },
109
+ "properties":
110
+ {
111
+ "title": "Jessore, Bangladesh",
112
+ "radius": 750000,
113
+ "pivot": true,
114
+ "style": "satellite",
115
+ }
116
+ }
117
+ </script>
118
+ <figcaption class="op-vertical-above"><h1 class="op-vertical-above op-center">title for caption</h1><h2 class="op-vertical-below op-right">sub title for caption</h2>
119
+
120
+
121
+ <cite class="op-vertical-center op-left">credit within caption</cite></figcaption>
122
+ <audio title="audio title" autoplay="autoplay" muted="muted">
123
+ <source src="http://foo.com/mp3"/>
124
+ </audio>
125
+ </figure>
126
+ <aside>
127
+ We can be more efficient about where we grow, what we grow, and how we grow.
128
+ <cite>Fruit Store Company</cite></aside>
129
+ <p>Other text to be within a second paragraph for testing.</p>
130
+ <figure class="op-tracker">
131
+ <iframe>
132
+ <h1>Some custom code</h1>
133
+ <script>alert("test & more test");</script></iframe>
134
+ </figure>
135
+ <figure class="op-tracker">
136
+ <iframe>
137
+ <h1>Tracker with enclosing on the script</h1>
138
+ <div><script>alert("test & more test");</script></div>
139
+ </iframe>
140
+ </figure>
141
+ <figure class="op-interactive">
142
+ <iframe class="no-margin">
143
+ <h1>Custom code for your social embed</h1>
144
+ <script>alert("test & more test");</script></iframe>
145
+ </figure>
146
+ <figure data-mode="fullscreen" data-feedback="fb:likes,fb:comments">
147
+ <video data-fb-disable-autoplay="data-fb-disable-autoplay" controls="controls">
148
+ <source src="http://mydomain.com/path/to/video.mp4" type="video/mp4"/>
149
+ </video>
150
+ <figcaption class="op-vertical-below"><h1>Video 1 Title</h1>
151
+
152
+ <cite>Attribution Source</cite></figcaption>
153
+ <script type="application/json" class="op-geotag">
154
+ {
155
+ "type": "Feature",
156
+ "geometry": {
157
+ "type": "Point",
158
+ "coordinates": [ [23.166667, 89.216667], [23.166667, 89.216667] ]
159
+ },
160
+ "properties": {
161
+ "title": "Jessore, Bangladesh",
162
+ "radius": 750000,
163
+ "pivot": true,
164
+ "style": "satellite",
165
+ }
166
+ }
167
+ </script>
168
+ </figure>
169
+ <ul class="op-related-articles" title="The related ones in the middle">
170
+ <li>
171
+ <a href="http://example.com/article.html"></a>
172
+ </li>
173
+ <li data-sponsored="true">
174
+ <a href="http://example.com/sponsored-article.html"></a>
175
+ </li>
176
+ <li>
177
+ <a href="http://example.com/another-article.html"></a>
178
+ </li>
179
+ </ul>
180
+ <footer>
181
+ <aside>
182
+ <p>Some plaintext credits to<a href="http://facebook.com/author" rel="facebook">Author</a></p>
183
+ <p>Paragraph text as credits</p>
184
+ </aside>
185
+ <ul class="op-related-articles" title="The related ones in the footer">
186
+ <li>
187
+ <a href="http://example.com/article.html"></a>
188
+ </li>
189
+ <li data-sponsored="true">
190
+ <a href="http://example.com/sponsored-article.html"></a>
191
+ </li>
192
+ <li>
193
+ <a href="http://example.com/another-article.html"></a>
194
+ </li>
195
+ </ul>
196
+ </footer>
197
+ </article>
198
+ </body>
199
+ </html>
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/CMS/WPTransformerTest.php CHANGED
@@ -71,6 +71,7 @@ class WPTest extends \PHPUnit_Framework_TestCase
71
  $expected = file_get_contents(__DIR__ . '/wp-ia.xml');
72
 
73
  $this->assertEquals($expected, $result);
74
- $this->assertEquals(0, count($transformer->getWarnings()));
 
75
  }
76
  }
71
  $expected = file_get_contents(__DIR__ . '/wp-ia.xml');
72
 
73
  $this->assertEquals($expected, $result);
74
+ // there must be 3 warnings related to <img> inside <li> that is not supported by IA
75
+ $this->assertEquals(3, count($transformer->getWarnings()));
76
  }
77
  }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/CMS/wp-ia.xml CHANGED
@@ -17,6 +17,24 @@
17
  </header>
18
  <p>Yes, peace is good for everybody!<br/>
19
  Man kind.</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  </article>
21
  </body>
22
  </html>
17
  </header>
18
  <p>Yes, peace is good for everybody!<br/>
19
  Man kind.</p>
20
+ <figure>
21
+ <img src="http://example.com/image0.jpg"/>
22
+ </figure>
23
+ <p>Some text after img.</p>
24
+ <p>Some text before img</p>
25
+ <figure>
26
+ <img src="http://example.com/image1.jpg"/>
27
+ </figure>
28
+ <p>Some text before img</p>
29
+ <figure>
30
+ <img src="http://example.com/image2.jpg"/>
31
+ </figure>
32
+ <p> and some after img.</p>
33
+ <ul>
34
+ <li>Some text on li before img</li>
35
+ <li>Some text on li before imgand after img</li>
36
+ <li>Some text after img</li>
37
+ </ul>
38
  </article>
39
  </body>
40
  </html>
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/CMS/wp-rules.json CHANGED
@@ -59,9 +59,9 @@
59
  }, {
60
  "class": "PassThroughRule",
61
  "selector": "blockquote p"
62
- }, {
63
  "class": "ImageRule",
64
- "selector": "//p[img]",
65
  "properties": {
66
  "image.url": {
67
  "type": "string",
@@ -69,8 +69,8 @@
69
  "attribute": "src"
70
  }
71
  }
72
- },{
73
- "class": "ImageRule",
74
  "selector": "img",
75
  "properties": {
76
  "image.url": {
@@ -117,51 +117,6 @@
117
  }, {
118
  "class": "H2Rule",
119
  "selector" : "h3,h4,h5,h6"
120
- }, {
121
- "class": "SocialEmbedRule",
122
- "selector" : "iframe",
123
- "properties" : {
124
- "socialembed.url" : {
125
- "type" : "string",
126
- "selector" : "iframe",
127
- "attribute": "src"
128
- },
129
- "socialembed.iframe" : {
130
- "type" : "children",
131
- "selector" : "iframe"
132
- },
133
- "socialembed.caption" : {
134
- "type" : "element",
135
- "selector" : "figcaption"
136
- }
137
- }
138
- }, {
139
- "class": "SocialEmbedRule",
140
- "selector" : "//p[iframe]",
141
- "properties" : {
142
- "socialembed.url" : {
143
- "type" : "string",
144
- "selector" : "iframe",
145
- "attribute": "src"
146
- },
147
- "socialembed.iframe" : {
148
- "type" : "children",
149
- "selector" : "iframe"
150
- },
151
- "socialembed.caption" : {
152
- "type" : "element",
153
- "selector" : "figcaption"
154
- }
155
- }
156
- }, {
157
- "class": "SocialEmbedRule",
158
- "selector" : "div.embed",
159
- "properties" : {
160
- "socialembed.iframe" : {
161
- "type" : "children",
162
- "selector" : "div.embed"
163
- }
164
- }
165
  }, {
166
  "class": "InteractiveRule",
167
  "selector" : "div.interactive",
@@ -180,16 +135,6 @@
180
  "selector" : "iframe"
181
  }
182
  }
183
- }, {
184
- "class": "SocialEmbedRule",
185
- "selector" : "//div[@class='embed' and iframe]",
186
- "properties" : {
187
- "socialembed.url" : {
188
- "type" : "string",
189
- "selector" : "iframe",
190
- "attribute": "src"
191
- }
192
- }
193
  }, {
194
  "class": "InteractiveRule",
195
  "selector" : "//div[@class='interactive' and iframe]",
@@ -200,16 +145,6 @@
200
  "attribute": "src"
201
  }
202
  }
203
- }, {
204
- "class": "ImageRule",
205
- "selector": "//p[a[img]]|//a[img]",
206
- "properties": {
207
- "image.url": {
208
- "type": "string",
209
- "selector": "img",
210
- "attribute": "src"
211
- }
212
- }
213
  }, {
214
  "class": "SlideshowImageRule",
215
  "selector" : "figure",
@@ -258,13 +193,13 @@
258
  }
259
  }
260
  }, {
261
- "class": "InteractiveRule",
262
- "selector" : "table",
263
- "properties" : {
264
- "interactive.iframe" : {
265
- "type" : "element",
266
- "selector" : "table"
267
- }
268
- }
269
- }]
270
  }
59
  }, {
60
  "class": "PassThroughRule",
61
  "selector": "blockquote p"
62
+ },{
63
  "class": "ImageRule",
64
+ "selector": "img",
65
  "properties": {
66
  "image.url": {
67
  "type": "string",
69
  "attribute": "src"
70
  }
71
  }
72
+ }, {
73
+ "class": "ImageInsideParagraphRule",
74
  "selector": "img",
75
  "properties": {
76
  "image.url": {
117
  }, {
118
  "class": "H2Rule",
119
  "selector" : "h3,h4,h5,h6"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  }, {
121
  "class": "InteractiveRule",
122
  "selector" : "div.interactive",
135
  "selector" : "iframe"
136
  }
137
  }
 
 
 
 
 
 
 
 
 
 
138
  }, {
139
  "class": "InteractiveRule",
140
  "selector" : "//div[@class='interactive' and iframe]",
145
  "attribute": "src"
146
  }
147
  }
 
 
 
 
 
 
 
 
 
 
148
  }, {
149
  "class": "SlideshowImageRule",
150
  "selector" : "figure",
193
  }
194
  }
195
  }, {
196
+ "class": "InteractiveRule",
197
+ "selector" : "table",
198
+ "properties" : {
199
+ "interactive.iframe" : {
200
+ "type" : "element",
201
+ "selector" : "table"
202
+ }
203
+ }
204
+ }]
205
  }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/CMS/wp.html CHANGED
@@ -1,4 +1,12 @@
1
  <!DOCTYPE html>
2
  <html><body><p>Yes, peace is good for everybody!<br>
3
  Man kind.</p>
 
 
 
 
 
 
 
 
4
  </body></html>
1
  <!DOCTYPE html>
2
  <html><body><p>Yes, peace is good for everybody!<br>
3
  Man kind.</p>
4
+ <p><img src="http://example.com/image0.jpg" />Some text after img.</p>
5
+ <p>Some text before img<img src="http://example.com/image1.jpg" /></p>
6
+ <p>Some text before img<img src="http://example.com/image2.jpg" /> and some after img.</p>
7
+ <ul>
8
+ <li>Some text on li before img<img src="http://example.com/image.jpg" width="600" height="360"/></li>
9
+ <li>Some text on li before img<img src="http://example.com/image.jpg" width="600" height="360"/>and after img</li>
10
+ <li><img src="http://example.com/image.jpg" width="600" height="360"/>Some text after img</li>
11
+ </ul>
12
  </body></html>
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/Example/SimpleTransformerTest.php CHANGED
@@ -51,7 +51,7 @@ class SimpleTransformerTest extends \PHPUnit_Framework_TestCase
51
  $instant_article->addMetaProperty('op:generator:version', '1.0.0');
52
  $instant_article->addMetaProperty('op:generator:transformer:version', '1.0.0');
53
  $result = $instant_article->render('', true)."\n";
54
- $expected = file_get_contents(__DIR__ . '/simple-ia.xml');
55
 
56
  //var_dump($result);
57
  // print_r($warnings);
51
  $instant_article->addMetaProperty('op:generator:version', '1.0.0');
52
  $instant_article->addMetaProperty('op:generator:transformer:version', '1.0.0');
53
  $result = $instant_article->render('', true)."\n";
54
+ $expected = file_get_contents(__DIR__ . '/simple-ia.html');
55
 
56
  //var_dump($result);
57
  // print_r($warnings);
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/Example/{simple-ia.xml → simple-ia.html} RENAMED
@@ -26,6 +26,11 @@
26
  <figcaption>Photographer</figcaption>
27
  </figure>
28
  <p>Curabitur vulputate odio eu justo <i>venenatis</i>, a pretium orci placerat. Nam sed neque quis eros vestibulum mattis. Donec vitae mi egestas, laoreet massa et, fringilla libero.</p>
 
 
 
 
 
29
  </article>
30
  </body>
31
  </html>
26
  <figcaption>Photographer</figcaption>
27
  </figure>
28
  <p>Curabitur vulputate odio eu justo <i>venenatis</i>, a pretium orci placerat. Nam sed neque quis eros vestibulum mattis. Donec vitae mi egestas, laoreet massa et, fringilla libero.</p>
29
+ <figure class="op-interactive">
30
+ <iframe>
31
+ <h1>Custom code for your social embed</h1>
32
+ <script>alert("test & more test");</script></iframe>
33
+ </figure>
34
  </article>
35
  </body>
36
  </html>
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/Example/simple-rules.json CHANGED
@@ -98,6 +98,16 @@
98
  "selector" : "div.image-caption"
99
  }
100
  }
 
 
 
 
 
 
 
 
 
 
101
  }
102
  ]
103
  }
98
  "selector" : "div.image-caption"
99
  }
100
  }
101
+ },
102
+ {
103
+ "class": "SocialEmbedRule",
104
+ "selector" : "div.embed",
105
+ "properties" : {
106
+ "socialembed.iframe" : {
107
+ "type" : "children",
108
+ "selector" : "*"
109
+ }
110
+ }
111
  }
112
  ]
113
  }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/Example/simple.html CHANGED
@@ -18,5 +18,9 @@
18
  <img src="http://domain.com/image-body.png" alt="Photographer"/>
19
  </div>
20
  <p>Curabitur vulputate odio eu justo <i>venenatis</i>, a pretium orci placerat. Nam sed neque quis eros vestibulum mattis. Donec vitae mi egestas, laoreet massa et, fringilla libero.</p>
 
 
 
 
21
  </body>
22
  </html>
18
  <img src="http://domain.com/image-body.png" alt="Photographer"/>
19
  </div>
20
  <p>Curabitur vulputate odio eu justo <i>venenatis</i>, a pretium orci placerat. Nam sed neque quis eros vestibulum mattis. Donec vitae mi egestas, laoreet massa et, fringilla libero.</p>
21
+ <div class="embed">
22
+ <h1>Custom code for your social embed</h1>
23
+ <script>alert("test & more test");</script>
24
+ </div>
25
  </body>
26
  </html>
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/TransformerTest.php CHANGED
@@ -10,8 +10,12 @@ namespace Facebook\InstantArticles\Transformer;
10
 
11
  use Facebook\InstantArticles\Elements\InstantArticle;
12
 
13
- use Facebook\InstantArticles\Transformer\Rules\ParagraphRule;
 
 
14
  use Facebook\InstantArticles\Transformer\Rules\ItalicRule;
 
 
15
 
16
  class TransformerTest extends \PHPUnit_Framework_TestCase
17
  {
@@ -37,7 +41,7 @@ class TransformerTest extends \PHPUnit_Framework_TestCase
37
 
38
  public function testSelfTransformerContent()
39
  {
40
- $json_file = file_get_contents(__DIR__ . '/instant-article-example-rules.json');
41
 
42
  $instant_article = InstantArticle::create();
43
  $transformer = new Transformer();
@@ -47,7 +51,7 @@ class TransformerTest extends \PHPUnit_Framework_TestCase
47
 
48
  libxml_use_internal_errors(true);
49
  $document = new \DOMDocument();
50
- $document->loadXML($html_file);
51
  libxml_use_internal_errors(false);
52
 
53
  $transformer->transform($instant_article, $document);
@@ -89,4 +93,23 @@ class TransformerTest extends \PHPUnit_Framework_TestCase
89
  $transformer->resetRules();
90
  $this->assertEquals([], $transformer->getRules());
91
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  }
10
 
11
  use Facebook\InstantArticles\Elements\InstantArticle;
12
 
13
+ use Facebook\InstantArticles\Elements\Header;
14
+ use Facebook\InstantArticles\Transformer\Rules\BoldRule;
15
+ use Facebook\InstantArticles\Transformer\Rules\H1Rule;
16
  use Facebook\InstantArticles\Transformer\Rules\ItalicRule;
17
+ use Facebook\InstantArticles\Transformer\Rules\ParagraphRule;
18
+ use Facebook\InstantArticles\Transformer\Rules\TextNodeRule;
19
 
20
  class TransformerTest extends \PHPUnit_Framework_TestCase
21
  {
41
 
42
  public function testSelfTransformerContent()
43
  {
44
+ $json_file = file_get_contents('src/Facebook/InstantArticles/Parser/instant-articles-rules.json');
45
 
46
  $instant_article = InstantArticle::create();
47
  $transformer = new Transformer();
51
 
52
  libxml_use_internal_errors(true);
53
  $document = new \DOMDocument();
54
+ $document->loadHTML($html_file);
55
  libxml_use_internal_errors(false);
56
 
57
  $transformer->transform($instant_article, $document);
93
  $transformer->resetRules();
94
  $this->assertEquals([], $transformer->getRules());
95
  }
96
+
97
+ public function testTitleTransformedWithBold()
98
+ {
99
+ $transformer = new Transformer();
100
+ $json_file = file_get_contents(__DIR__ . '/wp-rules.json');
101
+ $transformer->loadRules($json_file);
102
+
103
+ $title_html_string = '<?xml encoding="utf-8" ?><h1>Title <b>in bold</b></h1>';
104
+
105
+ libxml_use_internal_errors(true);
106
+ $document = new \DOMDocument();
107
+ $document->loadHtml($title_html_string);
108
+ libxml_use_internal_errors(false);
109
+
110
+ $header = Header::create();
111
+ $transformer->transform($header, $document);
112
+
113
+ $this->assertEquals('<h1>Title <b>in bold</b></h1>', $header->getTitle()->render());
114
+ }
115
  }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/instant-article-example.html CHANGED
@@ -29,6 +29,11 @@
29
  <address><a title="PHP Programmer">Developer</a>
30
  </address>
31
  <h3 class="op-kicker">Some kicker of this article</h3>
 
 
 
 
 
32
  </header>
33
  <p>Some text to be within a paragraph for testing.</p>
34
  <figure data-feedback="fb:likes">
@@ -90,7 +95,7 @@
90
  <figure class="op-interactive">
91
  <iframe src="http://example.com/custom-interactive" class="column-width" height="60">
92
  <h1>Some custom code</h1>
93
- <script>alert("test");</script></iframe>
94
  <figcaption>This graphic is awesome.</figcaption>
95
  </figure>
96
  <figure class="op-ad">
@@ -130,18 +135,18 @@
130
  <figure class="op-tracker">
131
  <iframe>
132
  <h1>Some custom code</h1>
133
- <script>alert("test");</script></iframe>
134
  </figure>
135
  <figure class="op-tracker">
136
  <iframe>
137
  <h1>Tracker with enclosing on the script</h1>
138
- <div><script>alert("test");</script></div>
139
  </iframe>
140
  </figure>
141
- <figure class="op-social">
142
- <iframe>
143
  <h1>Custom code for your social embed</h1>
144
- <script>alert("test");</script></iframe>
145
  </figure>
146
  <figure data-mode="fullscreen" data-feedback="fb:likes,fb:comments">
147
  <video data-fb-disable-autoplay="data-fb-disable-autoplay" controls="controls">
29
  <address><a title="PHP Programmer">Developer</a>
30
  </address>
31
  <h3 class="op-kicker">Some kicker of this article</h3>
32
+ <ul class="op-sponsors">
33
+ <li>
34
+ <a href="http://facebook.com/my-sponsor" rel="facebook"></a>
35
+ </li>
36
+ </ul>
37
  </header>
38
  <p>Some text to be within a paragraph for testing.</p>
39
  <figure data-feedback="fb:likes">
95
  <figure class="op-interactive">
96
  <iframe src="http://example.com/custom-interactive" class="column-width" height="60">
97
  <h1>Some custom code</h1>
98
+ <script>alert("test & more test");</script></iframe>
99
  <figcaption>This graphic is awesome.</figcaption>
100
  </figure>
101
  <figure class="op-ad">
135
  <figure class="op-tracker">
136
  <iframe>
137
  <h1>Some custom code</h1>
138
+ <script>alert("test & more test");</script></iframe>
139
  </figure>
140
  <figure class="op-tracker">
141
  <iframe>
142
  <h1>Tracker with enclosing on the script</h1>
143
+ <div><script>alert("test & more test");</script></div>
144
  </iframe>
145
  </figure>
146
+ <figure class="op-interactive">
147
+ <iframe class="no-margin">
148
  <h1>Custom code for your social embed</h1>
149
+ <script>alert("test & more test");</script></iframe>
150
  </figure>
151
  <figure data-mode="fullscreen" data-feedback="fb:likes,fb:comments">
152
  <video data-fb-disable-autoplay="data-fb-disable-autoplay" controls="controls">
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/wp-rules.json ADDED
@@ -0,0 +1,270 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "rules":
3
+ [{
4
+ "class": "TextNodeRule"
5
+ }, {
6
+ "class": "PassThroughRule",
7
+ "selector": "html"
8
+ }, {
9
+ "class": "PassThroughRule",
10
+ "selector": "head"
11
+ }, {
12
+ "class": "PassThroughRule",
13
+ "selector": "body"
14
+ }, {
15
+ "class": "PassThroughRule",
16
+ "selector" : "code"
17
+ },{
18
+ "class": "PassThroughRule",
19
+ "selector" : "del"
20
+ }, {
21
+ "class": "PassThroughRule",
22
+ "selector" : "span"
23
+ }, {
24
+ "class": "ParagraphRule",
25
+ "selector": "p"
26
+ }, {
27
+ "class": "LineBreakRule",
28
+ "selector": "br"
29
+ }, {
30
+ "class": "AnchorRule",
31
+ "selector": "a",
32
+ "properties": {
33
+ "anchor.href": {
34
+ "type": "string",
35
+ "selector": "a",
36
+ "attribute": "href"
37
+ },
38
+ "anchor.rel": {
39
+ "type": "string",
40
+ "selector": "a",
41
+ "attribute": "rel"
42
+ }
43
+ }
44
+ }, {
45
+ "class": "BoldRule",
46
+ "selector": "b"
47
+ }, {
48
+ "class": "BoldRule",
49
+ "selector": "strong"
50
+ }, {
51
+ "class": "ItalicRule",
52
+ "selector": "i"
53
+ }, {
54
+ "class": "ItalicRule",
55
+ "selector": "em"
56
+ }, {
57
+ "class": "BlockquoteRule",
58
+ "selector": "blockquote"
59
+ }, {
60
+ "class": "PassThroughRule",
61
+ "selector": "blockquote p"
62
+ }, {
63
+ "class": "ImageRule",
64
+ "selector": "//p[img]",
65
+ "properties": {
66
+ "image.url": {
67
+ "type": "string",
68
+ "selector": "img",
69
+ "attribute": "src"
70
+ }
71
+ }
72
+ },{
73
+ "class": "ImageRule",
74
+ "selector": "img",
75
+ "properties": {
76
+ "image.url": {
77
+ "type": "string",
78
+ "selector": "img",
79
+ "attribute": "src"
80
+ }
81
+ }
82
+ }, {
83
+ "class": "ListItemRule",
84
+ "selector" : "li"
85
+ }, {
86
+ "class": "ListElementRule",
87
+ "selector" : "ul"
88
+ }, {
89
+ "class": "ListElementRule",
90
+ "selector" : "ol"
91
+ }, {
92
+ "class": "BlockquoteRule",
93
+ "selector" : "blockquote"
94
+ }, {
95
+ "class": "H1Rule",
96
+ "selector" : "h1",
97
+ "properties" : {
98
+ "h1.class" : {
99
+ "type" : "string",
100
+ "selector" : "link",
101
+ "attribute": "class"
102
+ }
103
+ }
104
+ }, {
105
+ "class": "H1Rule",
106
+ "selector" : "title"
107
+ }, {
108
+ "class": "H2Rule",
109
+ "selector" : "h2",
110
+ "properties" : {
111
+ "h2.class" : {
112
+ "type" : "string",
113
+ "selector" : "link",
114
+ "attribute": "class"
115
+ }
116
+ }
117
+ }, {
118
+ "class": "H2Rule",
119
+ "selector" : "h3,h4,h5,h6"
120
+ }, {
121
+ "class": "SocialEmbedRule",
122
+ "selector" : "iframe",
123
+ "properties" : {
124
+ "socialembed.url" : {
125
+ "type" : "string",
126
+ "selector" : "iframe",
127
+ "attribute": "src"
128
+ },
129
+ "socialembed.iframe" : {
130
+ "type" : "children",
131
+ "selector" : "iframe"
132
+ },
133
+ "socialembed.caption" : {
134
+ "type" : "element",
135
+ "selector" : "figcaption"
136
+ }
137
+ }
138
+ }, {
139
+ "class": "SocialEmbedRule",
140
+ "selector" : "//p[iframe]",
141
+ "properties" : {
142
+ "socialembed.url" : {
143
+ "type" : "string",
144
+ "selector" : "iframe",
145
+ "attribute": "src"
146
+ },
147
+ "socialembed.iframe" : {
148
+ "type" : "children",
149
+ "selector" : "iframe"
150
+ },
151
+ "socialembed.caption" : {
152
+ "type" : "element",
153
+ "selector" : "figcaption"
154
+ }
155
+ }
156
+ }, {
157
+ "class": "SocialEmbedRule",
158
+ "selector" : "div.embed",
159
+ "properties" : {
160
+ "socialembed.iframe" : {
161
+ "type" : "children",
162
+ "selector" : "div.embed"
163
+ }
164
+ }
165
+ }, {
166
+ "class": "InteractiveRule",
167
+ "selector" : "div.interactive",
168
+ "properties" : {
169
+ "interactive.iframe" : {
170
+ "type" : "children",
171
+ "selector" : "div.interactive"
172
+ },
173
+ "interactive.height" : {
174
+ "type" : "int",
175
+ "selector" : "iframe",
176
+ "attribute": "height"
177
+ },
178
+ "interactive.iframe" : {
179
+ "type" : "children",
180
+ "selector" : "iframe"
181
+ }
182
+ }
183
+ }, {
184
+ "class": "SocialEmbedRule",
185
+ "selector" : "//div[@class='embed' and iframe]",
186
+ "properties" : {
187
+ "socialembed.url" : {
188
+ "type" : "string",
189
+ "selector" : "iframe",
190
+ "attribute": "src"
191
+ }
192
+ }
193
+ }, {
194
+ "class": "InteractiveRule",
195
+ "selector" : "//div[@class='interactive' and iframe]",
196
+ "properties" : {
197
+ "interactive.url" : {
198
+ "type" : "string",
199
+ "selector" : "iframe",
200
+ "attribute": "src"
201
+ }
202
+ }
203
+ }, {
204
+ "class": "ImageRule",
205
+ "selector": "//p[a[img]]|//a[img]",
206
+ "properties": {
207
+ "image.url": {
208
+ "type": "string",
209
+ "selector": "img",
210
+ "attribute": "src"
211
+ }
212
+ }
213
+ }, {
214
+ "class": "SlideshowImageRule",
215
+ "selector" : "figure",
216
+ "properties" : {
217
+ "image.url" : {
218
+ "type" : "string",
219
+ "selector" : "img",
220
+ "attribute": "src"
221
+ },
222
+ "caption.title" : {
223
+ "type" : "string",
224
+ "selector" : "figcaption"
225
+ }
226
+ }
227
+ }, {
228
+ "class": "SlideshowRule",
229
+ "selector" : "div.gallery"
230
+ }, {
231
+ "class": "CaptionRule",
232
+ "selector" : "figcaption"
233
+ },
234
+ {
235
+ "class": "ImageRule",
236
+ "selector" : "figure",
237
+ "properties" : {
238
+ "image.url" : {
239
+ "type" : "string",
240
+ "selector" : "img",
241
+ "attribute": "src"
242
+ }
243
+ }
244
+ }, {
245
+ "class": "VideoRule",
246
+ "selector" : "div.wp-video",
247
+ "containsChild": "video",
248
+ "properties" : {
249
+ "video.url" : {
250
+ "type" : "string",
251
+ "selector" : "source",
252
+ "attribute": "src"
253
+ },
254
+ "video.type" : {
255
+ "type" : "string",
256
+ "selector" : "source",
257
+ "attribute": "type"
258
+ }
259
+ }
260
+ }, {
261
+ "class": "InteractiveRule",
262
+ "selector" : "table",
263
+ "properties" : {
264
+ "interactive.iframe" : {
265
+ "type" : "element",
266
+ "selector" : "table"
267
+ }
268
+ }
269
+ }]
270
+ }
vendor/facebook/php-sdk-v4/composer.json CHANGED
@@ -12,8 +12,7 @@
12
  }
13
  ],
14
  "require": {
15
- "php": ">=5.4.0",
16
- "ext-mbstring": "*"
17
  },
18
  "require-dev": {
19
  "phpunit/phpunit": "~4.0",
@@ -26,7 +25,8 @@
26
  "autoload": {
27
  "psr-4": {
28
  "Facebook\\": "src/Facebook/"
29
- }
 
30
  },
31
  "autoload-dev": {
32
  "psr-4": {
12
  }
13
  ],
14
  "require": {
15
+ "php": "^5.4|^7.0"
 
16
  },
17
  "require-dev": {
18
  "phpunit/phpunit": "~4.0",
25
  "autoload": {
26
  "psr-4": {
27
  "Facebook\\": "src/Facebook/"
28
+ },
29
+ "files": ["src/Facebook/polyfills.php"]
30
  },
31
  "autoload-dev": {
32
  "psr-4": {
vendor/facebook/php-sdk-v4/src/Facebook/Facebook.php CHANGED
@@ -53,12 +53,12 @@ class Facebook
53
  /**
54
  * @const string Version number of the Facebook PHP SDK.
55
  */
56
- const VERSION = '5.1.4';
57
 
58
  /**
59
  * @const string Default Graph API version for requests.
60
  */
61
- const DEFAULT_GRAPH_VERSION = 'v2.5';
62
 
63
  /**
64
  * @const string The name of the environment variable that contains the app ID.
53
  /**
54
  * @const string Version number of the Facebook PHP SDK.
55
  */
56
+ const VERSION = '5.2.0';
57
 
58
  /**
59
  * @const string Default Graph API version for requests.
60
  */
61
+ const DEFAULT_GRAPH_VERSION = 'v2.6';
62
 
63
  /**
64
  * @const string The name of the environment variable that contains the app ID.
vendor/facebook/php-sdk-v4/src/Facebook/FacebookApp.php CHANGED
@@ -24,6 +24,7 @@
24
  namespace Facebook;
25
 
26
  use Facebook\Authentication\AccessToken;
 
27
 
28
  class FacebookApp implements \Serializable
29
  {
@@ -40,10 +41,18 @@ class FacebookApp implements \Serializable
40
  /**
41
  * @param string $id
42
  * @param string $secret
 
 
43
  */
44
  public function __construct($id, $secret)
45
  {
46
- $this->id = $id;
 
 
 
 
 
 
47
  $this->secret = $secret;
48
  }
49
 
24
  namespace Facebook;
25
 
26
  use Facebook\Authentication\AccessToken;
27
+ use Facebook\Exceptions\FacebookSDKException;
28
 
29
  class FacebookApp implements \Serializable
30
  {
41
  /**
42
  * @param string $id
43
  * @param string $secret
44
+ *
45
+ * @throws FacebookSDKException
46
  */
47
  public function __construct($id, $secret)
48
  {
49
+ if (!is_string($id)
50
+ // Keeping this for BC. Integers greater than PHP_INT_MAX will make is_int() return false
51
+ && !is_int($id)) {
52
+ throw new FacebookSDKException('The "app_id" must be formatted as a string since many app ID\'s are greater than PHP_INT_MAX on some systems.');
53
+ }
54
+ // We cast as a string in case a valid int was set on a 64-bit system and this is unserialised on a 32-bit system
55
+ $this->id = (string) $id;
56
  $this->secret = $secret;
57
  }
58
 
vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/Birthday.php ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2016 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\GraphNodes;
25
+
26
+ use DateTime;
27
+
28
+ /**
29
+ * Birthday object to handle various Graph return formats
30
+ *
31
+ * @package Facebook
32
+ */
33
+ class Birthday extends DateTime
34
+ {
35
+ /**
36
+ * @var bool
37
+ */
38
+ private $hasDate = false;
39
+
40
+ /**
41
+ * @var bool
42
+ */
43
+ private $hasYear = false;
44
+
45
+ /**
46
+ * Parses Graph birthday format to set indication flags, possible values:
47
+ *
48
+ * MM/DD/YYYY
49
+ * MM/DD
50
+ * YYYY
51
+ *
52
+ * @link https://developers.facebook.com/docs/graph-api/reference/user
53
+ *
54
+ * @param string $date
55
+ */
56
+ public function __construct($date)
57
+ {
58
+ $parts = explode('/', $date);
59
+
60
+ $this->hasYear = count($parts) === 3 || count($parts) === 1;
61
+ $this->hasDate = count($parts) === 3 || count($parts) === 2;
62
+
63
+ parent::__construct($date);
64
+ }
65
+
66
+ /**
67
+ * Returns whether date object contains birth day and month
68
+ *
69
+ * @return bool
70
+ */
71
+ public function hasDate()
72
+ {
73
+ return $this->hasDate;
74
+ }
75
+
76
+ /**
77
+ * Returns whether date object contains birth year
78
+ *
79
+ * @return bool
80
+ */
81
+ public function hasYear()
82
+ {
83
+ return $this->hasYear;
84
+ }
85
+ }
vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphNode.php CHANGED
@@ -62,10 +62,11 @@ class GraphNode extends Collection
62
  foreach ($data as $k => $v) {
63
  if ($this->shouldCastAsDateTime($k)
64
  && (is_numeric($v)
65
- || $k === 'birthday'
66
  || $this->isIso8601DateString($v))
67
  ) {
68
  $items[$k] = $this->castToDateTime($v);
 
 
69
  } else {
70
  $items[$k] = $v;
71
  }
@@ -149,7 +150,6 @@ class GraphNode extends Collection
149
  'backdated_time',
150
  'issued_at',
151
  'expires_at',
152
- 'birthday',
153
  'publish_time'
154
  ], true);
155
  }
@@ -173,6 +173,18 @@ class GraphNode extends Collection
173
  return $dt;
174
  }
175
 
 
 
 
 
 
 
 
 
 
 
 
 
176
  /**
177
  * Getter for $graphObjectMap.
178
  *
62
  foreach ($data as $k => $v) {
63
  if ($this->shouldCastAsDateTime($k)
64
  && (is_numeric($v)
 
65
  || $this->isIso8601DateString($v))
66
  ) {
67
  $items[$k] = $this->castToDateTime($v);
68
+ } elseif ($k === 'birthday') {
69
+ $items[$k] = $this->castToBirthday($v);
70
  } else {
71
  $items[$k] = $v;
72
  }
150
  'backdated_time',
151
  'issued_at',
152
  'expires_at',
 
153
  'publish_time'
154
  ], true);
155
  }
173
  return $dt;
174
  }
175
 
176
+ /**
177
+ * Casts a birthday value from Graph to Birthday
178
+ *
179
+ * @param string $value
180
+ *
181
+ * @return Birthday
182
+ */
183
+ public function castToBirthday($value)
184
+ {
185
+ return new Birthday($value);
186
+ }
187
+
188
  /**
189
  * Getter for $graphObjectMap.
190
  *
vendor/facebook/php-sdk-v4/src/Facebook/Helpers/FacebookRedirectLoginHelper.php CHANGED
@@ -235,27 +235,19 @@ class FacebookRedirectLoginHelper
235
  protected function validateCsrf()
236
  {
237
  $state = $this->getState();
238
- $savedState = $this->persistentDataHandler->get('state');
239
-
240
- if (!$state || !$savedState) {
241
- throw new FacebookSDKException('Cross-site request forgery validation failed. Required param "state" missing.');
242
  }
243
-
244
- $savedLen = strlen($savedState);
245
- $givenLen = strlen($state);
246
-
247
- if ($savedLen !== $givenLen) {
248
- throw new FacebookSDKException('Cross-site request forgery validation failed. The "state" param from the URL and session do not match.');
249
  }
250
 
251
- $result = 0;
252
- for ($i = 0; $i < $savedLen; $i++) {
253
- $result |= ord($state[$i]) ^ ord($savedState[$i]);
254
  }
255
 
256
- if ($result !== 0) {
257
- throw new FacebookSDKException('Cross-site request forgery validation failed. The "state" param from the URL and session do not match.');
258
- }
259
  }
260
 
261
  /**
235
  protected function validateCsrf()
236
  {
237
  $state = $this->getState();
238
+ if (!$state) {
239
+ throw new FacebookSDKException('Cross-site request forgery validation failed. Required GET param "state" missing.');
 
 
240
  }
241
+ $savedState = $this->persistentDataHandler->get('state');
242
+ if (!$savedState) {
243
+ throw new FacebookSDKException('Cross-site request forgery validation failed. Required param "state" missing from persistent data.');
 
 
 
244
  }
245
 
246
+ if (\hash_equals($savedState, $state)) {
247
+ return;
 
248
  }
249
 
250
+ throw new FacebookSDKException('Cross-site request forgery validation failed. The "state" param from the URL and session do not match.');
 
 
251
  }
252
 
253
  /**
vendor/facebook/php-sdk-v4/src/Facebook/HttpClients/FacebookCurlHttpClient.php CHANGED
@@ -53,16 +53,6 @@ class FacebookCurlHttpClient implements FacebookHttpClientInterface
53
  */
54
  protected $facebookCurl;
55
 
56
- /**
57
- * @const Curl Version which is unaffected by the proxy header length error.
58
- */
59
- const CURL_PROXY_QUIRK_VER = 0x071E00;
60
-
61
- /**
62
- * @const "Connection Established" header text
63
- */
64
- const CONNECTION_ESTABLISHED = "HTTP/1.0 200 Connection established\r\n\r\n";
65
-
66
  /**
67
  * @param FacebookCurl|null Procedural curl as object
68
  */
@@ -164,47 +154,10 @@ class FacebookCurlHttpClient implements FacebookHttpClientInterface
164
  */
165
  public function extractResponseHeadersAndBody()
166
  {
167
- $headerSize = $this->getHeaderSize();
168
-
169
- $rawHeaders = mb_substr($this->rawResponse, 0, $headerSize);
170
- $rawBody = mb_substr($this->rawResponse, $headerSize);
171
 
172
  return [trim($rawHeaders), trim($rawBody)];
173
  }
174
-
175
- /**
176
- * Return proper header size
177
- *
178
- * @return integer
179
- */
180
- private function getHeaderSize()
181
- {
182
- $headerSize = $this->facebookCurl->getinfo(CURLINFO_HEADER_SIZE);
183
- // This corrects a Curl bug where header size does not account
184
- // for additional Proxy headers.
185
- if ($this->needsCurlProxyFix()) {
186
- // Additional way to calculate the request body size.
187
- if (preg_match('/Content-Length: (\d+)/', $this->rawResponse, $m)) {
188
- $headerSize = mb_strlen($this->rawResponse) - $m[1];
189
- } elseif (stripos($this->rawResponse, self::CONNECTION_ESTABLISHED) !== false) {
190
- $headerSize += mb_strlen(self::CONNECTION_ESTABLISHED);
191
- }
192
- }
193
-
194
- return $headerSize;
195
- }
196
-
197
- /**
198
- * Detect versions of Curl which report incorrect header lengths when
199
- * using Proxies.
200
- *
201
- * @return boolean
202
- */
203
- private function needsCurlProxyFix()
204
- {
205
- $ver = $this->facebookCurl->version();
206
- $version = $ver['version_number'];
207
-
208
- return $version < self::CURL_PROXY_QUIRK_VER;
209
- }
210
  }
53
  */
54
  protected $facebookCurl;
55
 
 
 
 
 
 
 
 
 
 
 
56
  /**
57
  * @param FacebookCurl|null Procedural curl as object
58
  */
154
  */
155
  public function extractResponseHeadersAndBody()
156
  {
157
+ $parts = explode("\r\n\r\n", $this->rawResponse);
158
+ $rawBody = array_pop($parts);
159
+ $rawHeaders = implode("\r\n\r\n", $parts);
 
160
 
161
  return [trim($rawHeaders), trim($rawBody)];
162
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
  }
vendor/facebook/php-sdk-v4/src/Facebook/PseudoRandomString/PseudoRandomStringGeneratorTrait.php CHANGED
@@ -54,9 +54,6 @@ trait PseudoRandomStringGeneratorTrait
54
  */
55
  public function binToHex($binaryData, $length)
56
  {
57
- if (true !== extension_loaded('mbstring')) {
58
- throw new \RuntimeException('Multibyte support required');
59
- }
60
- return \mb_substr(\bin2hex($binaryData), 0, $length);
61
  }
62
  }
54
  */
55
  public function binToHex($binaryData, $length)
56
  {
57
+ return \substr(\bin2hex($binaryData), 0, $length);
 
 
 
58
  }
59
  }
vendor/facebook/php-sdk-v4/src/Facebook/SignedRequest.php CHANGED
@@ -268,14 +268,8 @@ class SignedRequest
268
  */
269
  protected function validateSignature($hashedSig, $sig)
270
  {
271
- if (mb_strlen($hashedSig) === mb_strlen($sig)) {
272
- $validate = 0;
273
- for ($i = 0; $i < mb_strlen($sig); $i++) {
274
- $validate |= ord($hashedSig[$i]) ^ ord($sig[$i]);
275
- }
276
- if ($validate === 0) {
277
- return;
278
- }
279
  }
280
 
281
  throw new FacebookSDKException('Signed request has an invalid signature.', 602);
268
  */
269
  protected function validateSignature($hashedSig, $sig)
270
  {
271
+ if (\hash_equals($hashedSig, $sig)) {
272
+ return;
 
 
 
 
 
 
273
  }
274
 
275
  throw new FacebookSDKException('Signed request has an invalid signature.', 602);
vendor/facebook/php-sdk-v4/src/Facebook/polyfills.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2016 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+
25
+ /**
26
+ * @see https://github.com/sarciszewski/php-future/blob/master/src/Security.php#L37-L51
27
+ */
28
+ if (!function_exists('hash_equals')) {
29
+ function hash_equals($knownString, $userString)
30
+ {
31
+ if (function_exists('mb_strlen')) {
32
+ $kLen = mb_strlen($knownString, '8bit');
33
+ $uLen = mb_strlen($userString, '8bit');
34
+ } else {
35
+ $kLen = strlen($knownString);
36
+ $uLen = strlen($userString);
37
+ }
38
+ if ($kLen !== $uLen) {
39
+ return false;
40
+ }
41
+ $result = 0;
42
+ for ($i = 0; $i < $kLen; $i++) {
43
+ $result |= (ord($knownString[$i]) ^ ord($userString[$i]));
44
+ }
45
+
46
+ // They are only identical strings if $result is exactly 0...
47
+ return 0 === $result;
48
+ }
49
+ }
vendor/symfony/css-selector/CssSelector.php CHANGED
@@ -68,8 +68,8 @@ class CssSelector
68
  * Optionally, a prefix can be added to the resulting XPath
69
  * expression with the $prefix parameter.
70
  *
71
- * @param mixed $cssExpr The CSS expression.
72
- * @param string $prefix An optional prefix for the XPath expression.
73
  *
74
  * @return string
75
  */
68
  * Optionally, a prefix can be added to the resulting XPath
69
  * expression with the $prefix parameter.
70
  *
71
+ * @param mixed $cssExpr The CSS expression
72
+ * @param string $prefix An optional prefix for the XPath expression
73
  *
74
  * @return string
75
  */
vendor/symfony/css-selector/CssSelectorConverter.php CHANGED
@@ -29,7 +29,7 @@ class CssSelectorConverter
29
  private $translator;
30
 
31
  /**
32
- * @param bool $html Whether HTML support should be enabled. Disable it for XML documents.
33
  */
34
  public function __construct($html = true)
35
  {
@@ -53,8 +53,8 @@ class CssSelectorConverter
53
  * Optionally, a prefix can be added to the resulting XPath
54
  * expression with the $prefix parameter.
55
  *
56
- * @param string $cssExpr The CSS expression.
57
- * @param string $prefix An optional prefix for the XPath expression.
58
  *
59
  * @return string
60
  */
29
  private $translator;
30
 
31
  /**
32
+ * @param bool $html Whether HTML support should be enabled. Disable it for XML documents
33
  */
34
  public function __construct($html = true)
35
  {
53
  * Optionally, a prefix can be added to the resulting XPath
54
  * expression with the $prefix parameter.
55
  *
56
+ * @param string $cssExpr The CSS expression
57
+ * @param string $prefix An optional prefix for the XPath expression
58
  *
59
  * @return string
60
  */
vendor/symfony/css-selector/Parser/Parser.php CHANGED
@@ -58,9 +58,9 @@ class Parser implements ParserInterface
58
  *
59
  * @param Token[] $tokens
60
  *
61
- * @throws SyntaxErrorException
62
- *
63
  * @return array
 
 
64
  */
65
  public static function parseSeries(array $tokens)
66
  {
@@ -133,9 +133,9 @@ class Parser implements ParserInterface
133
  *
134
  * @param TokenStream $stream
135
  *
136
- * @throws SyntaxErrorException
137
- *
138
  * @return Node\SelectorNode
 
 
139
  */
140
  private function parserSelectorNode(TokenStream $stream)
141
  {
@@ -173,9 +173,9 @@ class Parser implements ParserInterface
173
  * @param TokenStream $stream
174
  * @param bool $insideNegation
175
  *
176
- * @throws SyntaxErrorException
177
- *
178
  * @return array
 
 
179
  */
180
  private function parseSimpleSelector(TokenStream $stream, $insideNegation = false)
181
  {
@@ -330,9 +330,9 @@ class Parser implements ParserInterface
330
  * @param Node\NodeInterface $selector
331
  * @param TokenStream $stream
332
  *
333
- * @throws SyntaxErrorException
334
- *
335
  * @return Node\AttributeNode
 
 
336
  */
337
  private function parseAttributeNode(Node\NodeInterface $selector, TokenStream $stream)
338
  {
58
  *
59
  * @param Token[] $tokens
60
  *
 
 
61
  * @return array
62
+ *
63
+ * @throws SyntaxErrorException
64
  */
65
  public static function parseSeries(array $tokens)
66
  {
133
  *
134
  * @param TokenStream $stream
135
  *
 
 
136
  * @return Node\SelectorNode
137
+ *
138
+ * @throws SyntaxErrorException
139
  */
140
  private function parserSelectorNode(TokenStream $stream)
141
  {
173
  * @param TokenStream $stream
174
  * @param bool $insideNegation
175
  *
 
 
176
  * @return array
177
+ *
178
+ * @throws SyntaxErrorException
179
  */
180
  private function parseSimpleSelector(TokenStream $stream, $insideNegation = false)
181
  {
330
  * @param Node\NodeInterface $selector
331
  * @param TokenStream $stream
332
  *
 
 
333
  * @return Node\AttributeNode
334
+ *
335
+ * @throws SyntaxErrorException
336
  */
337
  private function parseAttributeNode(Node\NodeInterface $selector, TokenStream $stream)
338
  {
vendor/symfony/css-selector/Parser/TokenStream.php CHANGED
@@ -85,9 +85,9 @@ class TokenStream
85
  /**
86
  * Returns next token.
87
  *
88
- * @throws InternalErrorException If there is no more token
89
- *
90
  * @return Token
 
 
91
  */
92
  public function getNext()
93
  {
@@ -133,9 +133,9 @@ class TokenStream
133
  /**
134
  * Returns nex identifier token.
135
  *
136
- * @throws SyntaxErrorException If next token is not an identifier
137
- *
138
  * @return string The identifier token value
 
 
139
  */
140
  public function getNextIdentifier()
141
  {
@@ -151,9 +151,9 @@ class TokenStream
151
  /**
152
  * Returns nex identifier or star delimiter token.
153
  *
154
- * @throws SyntaxErrorException If next token is not an identifier or a star delimiter
155
- *
156
  * @return null|string The identifier token value or null if star found
 
 
157
  */
158
  public function getNextIdentifierOrStar()
159
  {
85
  /**
86
  * Returns next token.
87
  *
 
 
88
  * @return Token
89
+ *
90
+ * @throws InternalErrorException If there is no more token
91
  */
92
  public function getNext()
93
  {
133
  /**
134
  * Returns nex identifier token.
135
  *
 
 
136
  * @return string The identifier token value
137
+ *
138
+ * @throws SyntaxErrorException If next token is not an identifier
139
  */
140
  public function getNextIdentifier()
141
  {
151
  /**
152
  * Returns nex identifier or star delimiter token.
153
  *
 
 
154
  * @return null|string The identifier token value or null if star found
155
+ *
156
+ * @throws SyntaxErrorException If next token is not an identifier or a star delimiter
157
  */
158
  public function getNextIdentifierOrStar()
159
  {
vendor/symfony/css-selector/XPath/Translator.php CHANGED
@@ -268,9 +268,9 @@ class Translator implements TranslatorInterface
268
  * @param string $attribute
269
  * @param string $value
270
  *
271
- * @throws ExpressionErrorException
272
- *
273
  * @return XPathExpr
 
 
274
  */
275
  public function addAttributeMatching(XPathExpr $xpath, $operator, $attribute, $value)
276
  {
268
  * @param string $attribute
269
  * @param string $value
270
  *
 
 
271
  * @return XPathExpr
272
+ *
273
+ * @throws ExpressionErrorException
274
  */
275
  public function addAttributeMatching(XPathExpr $xpath, $operator, $attribute, $value)
276
  {
wpcom-helper.php DELETED
@@ -1,43 +0,0 @@
1
- <?php
2
-
3
- // Wrap the wpcom tracking pixel to comply with the FBIA spec
4
- // https://developers.facebook.com/docs/instant-articles/reference/analytics
5
- function wpcom_fbia_stats_pixel() {
6
- global $post;
7
-
8
- if ( ! defined( 'INSTANT_ARTICLES_SLUG' ) ) {
9
- return;
10
- }
11
-
12
- if ( ! is_feed( INSTANT_ARTICLES_SLUG ) ) {
13
- return;
14
- }
15
-
16
- // Stop wpcom adding the tracking pixel
17
- remove_filter( 'the_content', 'add_bug_to_feed', 100 );
18
-
19
- add_filter( 'the_content', '_wpcom_fbia_stats_pixel', 100 );
20
-
21
- }
22
- add_action( 'template_redirect', 'wpcom_fbia_stats_pixel' );
23
-
24
- function _wpcom_fbia_stats_pixel( $content ) {
25
- global $post, $current_blog;
26
-
27
- if( ! is_feed() )
28
- return $content;
29
-
30
- $url = 'https://pixel.wp.com/b.gif?host=' . $_SERVER[ 'HTTP_HOST' ] . '&blog=' . $current_blog->blog_id . '&post=' . $post->ID . '&subd=' . str_replace( '.wordpress.com', '', $current_blog->domain ) . '&ref=&feed=1';
31
-
32
- $fbia_pixel = '
33
- <figure class="op-tracker">
34
- <iframe>
35
- <script>
36
- var x = new Image(); x.src = "' . esc_js( $url ) . '&rand=" +Math.random();
37
- </script>
38
- </iframe>
39
- </figure>';
40
-
41
- return $content . $fbia_pixel;
42
-
43
- }