Instant Articles for WP - Version 2.1

Version Description

  • Fixes compatibility with PHP 5.4+
  • Bug fixes
Download this release

Release Info

Developer diegoquinteiro
Plugin Icon 128x128 Instant Articles for WP
Version 2.1
Comparing to
See all releases

Code changes from version 0.2 to 2.1

Files changed (242) hide show
  1. README.md +40 -0
  2. class-instant-articles-post.php +437 -287
  3. class-instant-articles-publisher.php +89 -0
  4. compat.php +12 -6
  5. compat/class-instant-articles-co-authors-plus.php +12 -8
  6. compat/class-instant-articles-google-analytics-for-wordpress.php +33 -17
  7. compat/class-instant-articles-yoast-seo.php +14 -17
  8. css/instant-articles-meta-box.css +92 -0
  9. css/instant-articles-settings-wizard.css +3 -0
  10. css/instant-articles-settings.css +16 -0
  11. embeds.php +39 -74
  12. facebook-instant-articles.php +275 -152
  13. feed-template.php +17 -7
  14. js/instant-articles-meta-box.js +15 -0
  15. js/instant-articles-option-ads.js +42 -0
  16. js/instant-articles-option-analytics.js +17 -0
  17. js/instant-articles-option-publishing.js +17 -0
  18. js/instant-articles-settings.js +25 -0
  19. meta-box/class-instant-articles-meta-box.php +97 -0
  20. meta-box/meta-box-loader-template.php +15 -0
  21. meta-box/meta-box-template.php +178 -0
  22. readme.txt +28 -20
  23. rules-configuration.json +259 -0
  24. settings/class-instant-articles-option-ads.php +254 -0
  25. settings/class-instant-articles-option-analytics.php +143 -0
  26. settings/class-instant-articles-option-fb-app.php +58 -0
  27. settings/class-instant-articles-option-fb-page.php +71 -0
  28. settings/class-instant-articles-option-publishing.php +113 -0
  29. settings/class-instant-articles-option-styles.php +45 -0
  30. settings/class-instant-articles-option.php +457 -0
  31. settings/class-instant-articles-settings-fb-page.php +194 -0
  32. settings/class-instant-articles-settings-wizard.php +50 -0
  33. settings/class-instant-articles-settings.php +158 -0
  34. settings/template-settings-advanced.php +25 -0
  35. settings/template-settings-info.php +53 -0
  36. settings/template-settings-wizard.php +216 -0
  37. settings/template-settings.php +33 -0
  38. vendor/apache/log4php +1 -0
  39. vendor/autoload.php +7 -0
  40. vendor/composer/ClassLoader.php +413 -0
  41. vendor/composer/LICENSE +21 -0
  42. vendor/composer/autoload_classmap.php +88 -0
  43. vendor/composer/autoload_namespaces.php +9 -0
  44. vendor/composer/autoload_psr4.php +12 -0
  45. vendor/composer/autoload_real.php +45 -0
  46. vendor/composer/installed.json +199 -0
  47. vendor/facebook/facebook-instant-articles-sdk-php/.gitignore +4 -0
  48. vendor/facebook/facebook-instant-articles-sdk-php/CONTRIBUTING.md +62 -0
  49. vendor/facebook/facebook-instant-articles-sdk-php/LICENSE +19 -0
  50. vendor/facebook/facebook-instant-articles-sdk-php/README.md +44 -0
  51. vendor/facebook/facebook-instant-articles-sdk-php/composer.json +26 -0
  52. vendor/facebook/facebook-instant-articles-sdk-php/composer.lock +1113 -0
  53. vendor/facebook/facebook-instant-articles-sdk-php/docs/QuickStart.md +498 -0
  54. vendor/facebook/facebook-instant-articles-sdk-php/phpunit.xml +8 -0
  55. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Client/Client.php +175 -0
  56. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Client/ClientException.php +14 -0
  57. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Client/Helper.php +97 -0
  58. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Client/InstantArticleStatus.php +126 -0
  59. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Client/ServerMessage.php +109 -0
  60. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Ad.php +222 -0
  61. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Analytics.php +129 -0
  62. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Anchor.php +101 -0
  63. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/AnimatedGIF.php +32 -0
  64. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Audible.php +36 -0
  65. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Audio.php +195 -0
  66. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Author.php +189 -0
  67. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Blockquote.php +85 -0
  68. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Bold.php +44 -0
  69. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Caption.php +323 -0
  70. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Cite.php +116 -0
  71. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Div.php +44 -0
  72. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Element.php +58 -0
  73. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Footer.php +179 -0
  74. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/FormattedText.php +25 -0
  75. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/GeoTag.php +103 -0
  76. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/H1.php +117 -0
  77. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/H2.php +118 -0
  78. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Header.php +368 -0
  79. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Image.php +330 -0
  80. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/InstantArticle.php +329 -0
  81. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Interactive.php +222 -0
  82. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Italic.php +44 -0
  83. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/LineBreak.php +47 -0
  84. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/ListElement.php +176 -0
  85. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/ListItem.php +89 -0
  86. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Map.php +171 -0
  87. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Paragraph.php +51 -0
  88. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Pullquote.php +91 -0
  89. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/RelatedArticles.php +125 -0
  90. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/RelatedItem.php +113 -0
  91. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Slideshow.php +224 -0
  92. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/SocialEmbed.php +151 -0
  93. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Span.php +44 -0
  94. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/TextContainer.php +78 -0
  95. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Time.php +156 -0
  96. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Video.php +473 -0
  97. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Getters/AbstractGetter.php +38 -0
  98. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Getters/ChildrenGetter.php +30 -0
  99. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Getters/ElementGetter.php +45 -0
  100. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Getters/ExistsGetter.php +38 -0
  101. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Getters/GetterFactory.php +66 -0
  102. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Getters/IntegerGetter.php +39 -0
  103. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Getters/NextSiblingGetter.php +42 -0
  104. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Getters/StringGetter.php +49 -0
  105. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Getters/XpathGetter.php +51 -0
  106. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/AdRule.php +100 -0
  107. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/AnalyticsRule.php +86 -0
  108. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/AnchorRule.php +76 -0
  109. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/AudioRule.php +92 -0
  110. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/AuthorRule.php +93 -0
  111. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/BlockquoteRule.php +50 -0
  112. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/BoldRule.php +45 -0
  113. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/CaptionCreditRule.php +83 -0
  114. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/CaptionRule.php +118 -0
  115. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/ConfigurationSelectorRule.php +102 -0
  116. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/FooterRelatedArticlesRule.php +63 -0
  117. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/FooterRule.php +51 -0
  118. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/GeoTagRule.php +68 -0
  119. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/H1Rule.php +93 -0
  120. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/H2Rule.php +89 -0
  121. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/HeaderAdRule.php +84 -0
  122. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/HeaderImageRule.php +79 -0
  123. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/HeaderKickerRule.php +38 -0
  124. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/HeaderRule.php +45 -0
  125. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/HeaderSubTitleRule.php +42 -0
  126. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/HeaderTitleRule.php +38 -0
  127. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/IgnoreRule.php +46 -0
  128. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/ImageRule.php +91 -0
  129. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/InstantArticleRule.php +93 -0
  130. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/InteractiveRule.php +97 -0
  131. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/ItalicRule.php +50 -0
  132. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/LineBreakRule.php +49 -0
  133. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/ListElementRule.php +53 -0
  134. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/ListItemRule.php +46 -0
  135. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/MapRule.php +42 -0
  136. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/ParagraphFooterRule.php +50 -0
  137. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/ParagraphRule.php +53 -0
  138. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/PassThroughRule.php +47 -0
  139. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/PullquoteCiteRule.php +50 -0
  140. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/PullquoteRule.php +50 -0
  141. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/RelatedArticlesRule.php +63 -0
  142. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/RelatedItemRule.php +78 -0
  143. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/Rule.php +81 -0
  144. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/SlideshowImageRule.php +91 -0
  145. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/SlideshowRule.php +47 -0
  146. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/SocialEmbedRule.php +80 -0
  147. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/TextNodeRule.php +63 -0
  148. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/TimeRule.php +78 -0
  149. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/VideoRule.php +164 -0
  150. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Transformer.php +139 -0
  151. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Warnings/InvalidSelector.php +65 -0
  152. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Warnings/UnrecognizedElement.php +55 -0
  153. vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Validators/Type.php +365 -0
  154. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Client/ClientTest.php +299 -0
  155. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Client/HelperTest.php +65 -0
  156. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/AdTest.php +94 -0
  157. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/AnalyticsTest.php +90 -0
  158. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/AudioTest.php +99 -0
  159. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/AuthorTest.php +54 -0
  160. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/BlockquoteTest.php +54 -0
  161. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/CaptionTest.php +133 -0
  162. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/CiteTest.php +165 -0
  163. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/FooterTest.php +134 -0
  164. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/GeoTagTest.php +47 -0
  165. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/H1Test.php +165 -0
  166. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/H2Test.php +165 -0
  167. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/HeaderTest.php +154 -0
  168. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/ImageTest.php +223 -0
  169. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/InstantArticleTest.php +217 -0
  170. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/InteractiveTest.php +130 -0
  171. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/ListElementTest.php +109 -0
  172. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/MapTest.php +94 -0
  173. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/ParagraphTest.php +136 -0
  174. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/PullquoteTest.php +77 -0
  175. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/RelatedArticlesTest.php +58 -0
  176. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/SlideshowTest.php +197 -0
  177. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/SocialEmbedTest.php +79 -0
  178. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/TimeTest.php +55 -0
  179. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/Validators/TypeTest.php +372 -0
  180. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/VideoTest.php +257 -0
  181. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/Example/SimpleTransformerTest.php +88 -0
  182. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/Example/simple-ia.xml +32 -0
  183. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/Example/simple-rules.json +103 -0
  184. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/Example/simple.html +22 -0
  185. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/Rules/AuthorRuleTest.php +62 -0
  186. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/TransformerTest.php +112 -0
  187. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/Warnings/InvalidSelectorTest.php +59 -0
  188. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/instant-article-example-rules.json +654 -0
  189. vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/instant-article-example.html +200 -0
  190. vendor/facebook/facebook-instant-articles-sdk-php/tests/bootstrap.php +3 -0
  191. vendor/facebook/php-sdk-v4/LICENSE +19 -0
  192. vendor/facebook/php-sdk-v4/composer.json +41 -0
  193. vendor/facebook/php-sdk-v4/src/Facebook/Authentication/AccessToken.php +160 -0
  194. vendor/facebook/php-sdk-v4/src/Facebook/Authentication/AccessTokenMetadata.php +390 -0
  195. vendor/facebook/php-sdk-v4/src/Facebook/Authentication/OAuth2Client.php +292 -0
  196. vendor/facebook/php-sdk-v4/src/Facebook/Exceptions/FacebookAuthenticationException.php +33 -0
  197. vendor/facebook/php-sdk-v4/src/Facebook/Exceptions/FacebookAuthorizationException.php +33 -0
  198. vendor/facebook/php-sdk-v4/src/Facebook/Exceptions/FacebookClientException.php +33 -0
  199. vendor/facebook/php-sdk-v4/src/Facebook/Exceptions/FacebookOtherException.php +33 -0
  200. vendor/facebook/php-sdk-v4/src/Facebook/Exceptions/FacebookResponseException.php +214 -0
  201. vendor/facebook/php-sdk-v4/src/Facebook/Exceptions/FacebookResumableUploadException.php +33 -0
  202. vendor/facebook/php-sdk-v4/src/Facebook/Exceptions/FacebookSDKException.php +33 -0
  203. vendor/facebook/php-sdk-v4/src/Facebook/Exceptions/FacebookServerException.php +33 -0
  204. vendor/facebook/php-sdk-v4/src/Facebook/Exceptions/FacebookThrottleException.php +33 -0
  205. vendor/facebook/php-sdk-v4/src/Facebook/Facebook.php +614 -0
  206. vendor/facebook/php-sdk-v4/src/Facebook/FacebookApp.php +101 -0
  207. vendor/facebook/php-sdk-v4/src/Facebook/FacebookBatchRequest.php +303 -0
  208. vendor/facebook/php-sdk-v4/src/Facebook/FacebookBatchResponse.php +174 -0
  209. vendor/facebook/php-sdk-v4/src/Facebook/FacebookClient.php +250 -0
  210. vendor/facebook/php-sdk-v4/src/Facebook/FacebookRequest.php +536 -0
  211. vendor/facebook/php-sdk-v4/src/Facebook/FacebookResponse.php +410 -0
  212. vendor/facebook/php-sdk-v4/src/Facebook/FileUpload/FacebookFile.php +169 -0
  213. vendor/facebook/php-sdk-v4/src/Facebook/FileUpload/FacebookResumableUploader.php +167 -0
  214. vendor/facebook/php-sdk-v4/src/Facebook/FileUpload/FacebookTransferChunk.php +133 -0
  215. vendor/facebook/php-sdk-v4/src/Facebook/FileUpload/FacebookVideo.php +33 -0
  216. vendor/facebook/php-sdk-v4/src/Facebook/FileUpload/Mimetypes.php +987 -0
  217. vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/Collection.php +242 -0
  218. vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphAchievement.php +113 -0
  219. vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphAlbum.php +183 -0
  220. vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphApplication.php +43 -0
  221. vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphCoverPhoto.php +72 -0
  222. vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphEdge.php +238 -0
  223. vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphEvent.php +242 -0
  224. vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphGroup.php +170 -0
  225. vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphList.php +36 -0
  226. vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphLocation.php +102 -0
  227. vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphNode.php +185 -0
  228. vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphNodeFactory.php +392 -0
  229. vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphObject.php +36 -0
  230. vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphObjectFactory.php +88 -0
  231. vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphPage.php +125 -0
  232. vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphPicture.php +72 -0
  233. vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphSessionInfo.php +102 -0
  234. vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphUser.php +172 -0
  235. vendor/facebook/php-sdk-v4/src/Facebook/Helpers/FacebookCanvasHelper.php +52 -0
  236. vendor/facebook/php-sdk-v4/src/Facebook/Helpers/FacebookJavaScriptHelper.php +42 -0
  237. vendor/facebook/php-sdk-v4/src/Facebook/Helpers/FacebookPageTabHelper.php +95 -0
  238. vendor/facebook/php-sdk-v4/src/Facebook/Helpers/FacebookRedirectLoginHelper.php +332 -0
  239. vendor/facebook/php-sdk-v4/src/Facebook/Helpers/FacebookSignedRequestFromInputHelper.php +166 -0
  240. vendor/facebook/php-sdk-v4/src/Facebook/Http/GraphRawResponse.php +137 -0
  241. vendor/facebook/php-sdk-v4/src/Facebook/Http/RequestBodyInterface.php +39 -0
  242. vendor/facebook/php-sdk-v4/src/Facebook/Http/RequestBodyMultipart.php +94 -0
README.md ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Instant Articles for WP
2
+
3
+ Enable [Instant Articles for Facebook](https://developers.facebook.com/docs/instant-articles) on your WordPress site.
4
+
5
+ ## Description
6
+
7
+ This plugin adds support for Instant Articles for Facebook, which is a new way for publishers to distribute fast, interactive stories on Facebook. Instant Articles are preloaded in the Facebook mobile app so they load instantly.
8
+
9
+ With the plugin active, a new menu will be available for you to connect to your Facebook Page and start publishing your Instant Articles. You'll also see the status of each Instant Articles submission on the edit page of your posts.
10
+
11
+ ## Feed submission to Facebook
12
+
13
+ Facebook has a review process where they verify that all Instant Articles are properly formatted, have content consistency with their mobile web counterparts, and adhere to their community standards and content policies. You will not be able to publish Instant Articles in Facebook until your feed has been approved.
14
+
15
+ It's important to note that if you use meta fields to add extra text, images or videos to your Posts, Facebook will expect you to add these to your Instant Articles output too. This plugin includes hooks to help you do that.
16
+
17
+ [See Facebook's documentation for full details of the submission process.](https://developers.facebook.com/docs/instant-articles)
18
+
19
+ Facebook requires a minimum number of articles in your feed before they will review it. Once your feed has been approved, new posts will automatically be taken live on Instant Articles, and existing posts will be taken live once you update them.
20
+
21
+ ## Installation
22
+
23
+ 1. Run `composer install` on the root of the plugin folder. Make sure you have [Composer](https://github.com/composer/composer) installed.
24
+ 2. Upload the folder to the `/wp-content/plugins/` directory
25
+ 3. Activate the plugin through the 'Plugins' menu in WordPress
26
+
27
+ ## Frequently Asked Questions
28
+
29
+ **How do I customize the output for my site?**
30
+
31
+ There are a number of filters available in the plugin for modifying the output.
32
+
33
+ **How do I change the feed slug/URL if I'm using the RSS integration?**
34
+
35
+ To change the feed slug, set the constant INSTANT_ARTICLES_SLUG to whatever you like. If you do, remember to flush the rewrite rules afterwards.
36
+ By default it is set to `instant-articles` which usually will give you a feed URL set to `/feed/instant-articles`
37
+
38
+ **How do I flush the rewrite rules after changing the feed slug?**
39
+
40
+ Usually simply visiting the permalinks settings page in the WordPress dashboard will do the trick (/wp-admin/options-permalink.php)
class-instant-articles-post.php CHANGED
@@ -1,5 +1,22 @@
1
  <?php
 
 
 
 
 
 
 
2
 
 
 
 
 
 
 
 
 
 
 
3
  /**
4
  * Class responsible for constructing our content and preparing it for rendering
5
  *
@@ -7,51 +24,73 @@
7
  */
8
  class Instant_Articles_Post {
9
 
10
- /** @var int ID of the post */
11
- protected $_ID = 0;
 
 
 
 
12
 
13
- /** @var string Cached version of the Instant Article body */
 
 
 
 
14
  protected $_content = null;
15
 
16
  /** @var string The post’s optional subtitle */
17
  protected $_subtitle = null;
18
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  /**
20
  * Setup data and build the content
21
  *
22
  * @since 0.1
23
- * @param int $post_id ID of the post
24
  */
25
- function __construct( $post_id ) {
26
- $this->_ID = $post_id;
27
  }
28
 
29
  /**
30
- * Get the ID for this post
31
  *
32
  * @since 0.1
33
- * @return int The post ID
34
  */
35
- public function get_the_ID() {
36
- return $this->_ID;
37
  }
38
 
39
  /**
40
- * Get the title for this post
41
  *
42
  * @since 0.1
43
- * @return string The title
44
  */
45
  public function get_the_title() {
46
- $title = get_the_title( $this->get_the_ID() );
47
 
48
  /**
49
- * Filter the post title for use in instant articles
50
  *
51
  * @since 0.1
52
  *
53
- * @param string $title The current post title.
54
- * @param Instant_Article_Post $instant_article_post The instant article post
55
  */
56
  $title = apply_filters( 'instant_articles_title', $title, $this );
57
 
@@ -59,10 +98,10 @@ class Instant_Articles_Post {
59
  }
60
 
61
  /**
62
- * Get the title for this post
63
  *
64
  * @since 0.1
65
- * @return string The title
66
  */
67
  public function get_the_title_rss() {
68
  $title = $this->get_the_title();
@@ -72,7 +111,7 @@ class Instant_Articles_Post {
72
  *
73
  * @since 0.1
74
  *
75
- * @param string $title The current post title.
76
  */
77
  $title = apply_filters( 'the_title_rss', $title );
78
 
@@ -86,7 +125,7 @@ class Instant_Articles_Post {
86
  * @return bool Whether the post has a subtitle or not
87
  */
88
  public function has_subtitle() {
89
-
90
  $has_subtitle = false;
91
 
92
  $subtitle = $this->get_the_subtitle();
@@ -129,30 +168,14 @@ class Instant_Articles_Post {
129
  }
130
 
131
  /**
132
- * Get the canonical URL for this post
133
- *
134
- * A little warning here: It is extremely important that this is the same canonical URL as is used on the web site.
135
- * This is the identificator Facebook use to connect the "read" web article with the instant article.
136
- * Do not add any querystring params or URL fragments it. Not any. Not even for tracking.
137
  *
138
  * @since 0.1
139
- * @return string The canonical URL
140
- */
141
- public function get_canonical_url() {
142
- $url = get_permalink( $this->get_the_ID() );
143
-
144
- return $url;
145
- }
146
-
147
- /**
148
- * Get the excerpt for this post
149
- *
150
- * @since 0.1
151
- * @return string The excerpt
152
  */
153
  public function get_the_excerpt() {
154
 
155
- $post = get_post( $this->get_the_ID() );
156
 
157
  // This should ideally not happen, but it may do so if someone tampers with the query.
158
  // Returning the same protected post excerpt as "usual" may help them identify what’s going on.
@@ -160,11 +183,11 @@ class Instant_Articles_Post {
160
  return __( 'There is no excerpt because this is a protected post.' );
161
  }
162
 
163
- // Make sure no “read more” link is added
164
  add_filter( 'excerpt_more', '__return_empty_string', 999 );
165
 
166
  /**
167
- * Apply the default WP Filters for the post excerpt
168
  *
169
  * @since 0.1
170
  *
@@ -173,12 +196,12 @@ class Instant_Articles_Post {
173
  $excerpt = apply_filters( 'get_the_excerpt', $post->post_excerpt );
174
 
175
  /**
176
- * Filter the post excerpt for instant articles
177
  *
178
  * @since 0.1
179
  *
180
- * @param string $excerpt The current post excerpt.
181
- * @param Instant_Article_Post $instant_article_post The instant article post
182
  */
183
  $excerpt = apply_filters( 'instant_articles_excerpt', $excerpt, $this );
184
 
@@ -207,6 +230,31 @@ class Instant_Articles_Post {
207
  return $excerpt;
208
  }
209
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210
  /**
211
  * Get the article body for this post
212
  *
@@ -231,34 +279,38 @@ class Instant_Articles_Post {
231
  */
232
  protected function _get_the_content() {
233
 
234
- // Try to get the content from a transient, but only if the cached version have the same modtime
235
- $cache_mod_time = get_transient( 'instantarticles_mod_' . $this->get_the_ID() );
236
- if ( $cache_mod_time == get_post_modified_time( 'Y-m-d H:i:s', true, $this->get_the_ID() ) ) {
237
- $content = get_transient( 'instantarticles_content_' . $this->get_the_ID() );
238
- if ( $content !== false && strlen( $content ) ) {
239
  return $content;
240
  }
241
  }
242
 
243
  global $post, $more;
244
 
245
- // force $more
 
 
 
 
246
  $orig_more = $more;
247
  $more = 1;
248
 
249
- // If we’re not it the loop or otherwise properly setup
250
  $reset_postdata = false;
251
- if ( $this->get_the_ID() !== $post->ID ) {
252
- $post = get_post( $this->get_the_ID() );
253
  setup_postdata( $post );
254
  $reset_postdata = true;
255
  }
256
 
257
- // Now get the content
258
- $content = get_the_content();
259
 
260
  /**
261
- * Apply the default filter 'the_content' for the post content
262
  *
263
  * @since 0.1
264
  * @param string $content The current post content.
@@ -275,133 +327,37 @@ class Instant_Articles_Post {
275
  $content = wpautop( $content );
276
 
277
  /**
278
- * Filter the post content for Instant Articles
279
  *
280
  * @since 0.1
281
  * @param string $content The post content.
282
  */
283
  $content = apply_filters( 'instant_articles_content', $content );
284
 
285
-
286
- if ( class_exists( 'DOMDocument' ) && has_action( 'instant_articles_register_dom_transformation_filters' ) ) {
287
-
288
- /* If we have filters that wants to work on the DOM, we generate one instance of DOMDocument
289
- they can all work on, instead of having to handle the conversion themselves. */
290
-
291
- $libxml_previous_state = libxml_use_internal_errors( true );
292
- $DOMDocument = new DOMDocument( '1.0', get_option( 'blog_charset' ) );
293
-
294
- // DOMDocument isn’t handling encodings too well, so let’s help it a little
295
- if ( function_exists( 'mb_convert_encoding' ) ) {
296
- $content = mb_convert_encoding( $content, 'HTML-ENTITIES', get_option( 'blog_charset' ) );
297
- }
298
-
299
- $result = $DOMDocument->loadHTML( '<!doctype html><html><body>' . $content . '</body></html>' );
300
- libxml_clear_errors();
301
- libxml_use_internal_errors( $libxml_previous_state );
302
-
303
- if ( $result ) {
304
-
305
- // Register the DOM transformation filters if not done yet
306
- if ( ! did_action( 'instant_articles_register_dom_transformation_filters' ) ) {
307
- do_action( 'instant_articles_register_dom_transformation_filters' );
308
- }
309
- Instant_Articles_DOM_Transform_Filter_Runner::run( $DOMDocument, $this->get_the_ID() );
310
-
311
-
312
- $body = $DOMDocument->getElementsByTagName( 'body' )->item( 0 );
313
-
314
- $filtered_content = '';
315
- foreach ( $body->childNodes as $node ) {
316
- if ( method_exists( $DOMDocument, 'saveHTML' ) ) { // Requires PHP 5.3.6
317
- $filtered_content .= $DOMDocument->saveHTML( $node );
318
- } else {
319
- $temp_content = $DOMDocument->saveXML( $node );
320
- $iframe_pattern = "#<iframe([^>]+)/>#is"; // self-closing iframe element
321
- $temp_content = preg_replace( $iframe_pattern, "<iframe$1></iframe>", $temp_content );
322
- $filtered_content .= $temp_content;
323
- }
324
- }
325
-
326
- $content = $filtered_content;
327
- unset( $filtered_content );
328
-
329
- }
330
-
331
- }
332
-
333
- // Cache the content
334
- set_transient( 'instantarticles_mod_' . $this->get_the_ID(), get_post_modified_time( 'Y-m-d H:i:s', true, $this->get_the_ID() ), WEEK_IN_SECONDS );
335
- set_transient( 'instantarticles_content_' . $this->get_the_ID(), $content, WEEK_IN_SECONDS );
336
 
337
  return $content;
338
  }
339
 
340
  /**
341
- * Get the published date for this post
342
  *
343
  * @since 0.1
344
- * @return string The published date
345
- */
346
- public function get_the_pubdate() {
347
-
348
- $date = get_post_time( get_option( 'date_format' ), true, $this->get_the_ID() );
349
-
350
- /**
351
- * Filter the post date for instant articles
352
- *
353
- * @since 0.1
354
- *
355
- * @param string $date The current post date.
356
- * @param Instant_Article_Post $instant_article_post The instant article post
357
- */
358
- $date = apply_filters( 'instant_articles_date', $date, $this );
359
-
360
- return $date;
361
-
362
- }
363
-
364
- /**
365
- * Get the modified date for this post
366
- *
367
- * @since 0.1
368
- * @return string The modified date
369
- */
370
- public function get_the_moddate() {
371
-
372
- $modified_date = get_post_modified_time( get_option('date_format'), true, $this->get_the_ID() );
373
-
374
- /**
375
- * Filter the post modified date for instant articles
376
- *
377
- * @since 0.1
378
- *
379
- * @param string $modified_date The current post modified date.
380
- * @param Instant_Article_Post $instant_article_post The instant article post
381
- */
382
- $modified_date = apply_filters( 'instant_articles_modified_date', $modified_date, $this );
383
-
384
- return $modified_date;
385
-
386
- }
387
-
388
- /**
389
- * Get the published date for this post (ISO 8601)
390
- *
391
- * @since 0.1
392
- * @return string The published date formatted suitable for use in the RSS feed and the html time elements (ISO 8601)
393
  */
394
  public function get_the_pubdate_iso() {
395
 
396
- $published_date = mysql2date( 'c', get_post_time( 'Y-m-d H:i:s', true, $this->get_the_ID() ), false );
397
 
398
  /**
399
- * Filter the post published date (ISO 8601)
400
  *
401
  * @since 0.1
402
  *
403
  * @param string $published_date The current post published date.
404
- * @param Instant_Article_Post $instant_article_post The instant article post
405
  */
406
  $published_date = apply_filters( 'instant_articles_published_date_iso', $published_date, $this );
407
 
@@ -410,22 +366,22 @@ class Instant_Articles_Post {
410
  }
411
 
412
  /**
413
- * Get the modified date for this post (ISO 8601)
414
  *
415
  * @since 0.1
416
- * @return string The modified date formatted suitable for use in the RSS feed and the html time elements (ISO 8601)
417
  */
418
  public function get_the_moddate_iso() {
419
 
420
- $modified_date = mysql2date( 'c', get_post_modified_time( 'Y-m-d H:i:s', true, $this->get_the_ID() ), false );
421
 
422
  /**
423
- * Filter the post modified date (ISO 8601)
424
  *
425
  * @since 0.1
426
  *
427
  * @param string $modified_date The current post modified date.
428
- * @param Instant_Article_Post $instant_article_post The instant article post
429
  */
430
  $modified_date = apply_filters( 'instant_articles_modified_date_iso', $modified_date, $this );
431
 
@@ -433,56 +389,54 @@ class Instant_Articles_Post {
433
 
434
  }
435
  /**
436
- * Get the author(s)
437
  *
438
  * @since 0.1
439
- * @return array $authors The post author(s)
440
  */
441
  public function get_the_authors() {
442
 
443
  $authors = array();
444
 
445
- $post = get_post( $this->get_the_ID() );
446
 
447
- $WP_User = get_userdata( $post->post_author );
448
-
449
- if ( is_a( $WP_User, 'WP_User' ) ) {
450
  $author = new stdClass;
451
- $author->ID = $WP_User->ID;
452
- $author->display_name = $WP_User->data->display_name;
453
- $author->first_name = $WP_User->first_name;
454
- $author->last_name = $WP_User->last_name;
455
- $author->user_login = $WP_User->data->user_login;
456
- $author->user_nicename = $WP_User->data->user_nicename;
457
- $author->user_email = $WP_User->data->user_email;
458
- $author->user_url = $WP_User->data->user_url;
459
- $author->bio = $WP_User->description;
460
 
461
  $authors[] = $author;
462
  }
463
 
464
  /**
465
- * Filter the post author(s)
466
  *
467
  * @since 0.1
468
  *
469
  * @param array $authors The current post author(s).
470
- * @param int $post_id The instant article post
471
  */
472
- $authors = apply_filters( 'instant_articles_authors', $authors, $this->get_the_ID() );
473
 
474
  return $authors;
475
  }
476
 
477
  /**
478
- * Get featured image for cover
479
  *
480
  * @since 0.1
481
  * @return array {
482
  * Array containing image source and caption.
483
  *
484
- * @type string $src Image URL
485
- * @type string $caption Image caption
486
  * }
487
  */
488
  public function get_the_featured_image() {
@@ -491,11 +445,11 @@ class Instant_Articles_Post {
491
  'src' => '',
492
  'caption' => '',
493
  );
494
- if ( has_post_thumbnail( $this->get_the_ID() ) ) {
 
 
 
495
 
496
- $image_array = wp_get_attachment_image_src( get_post_thumbnail_id( $this->get_the_ID() ), 'full' );
497
- $attachment_id = get_post_thumbnail_id( $this->get_the_ID() );
498
-
499
  if ( is_array( $image_array ) ) {
500
  $image_data['src'] = $image_array[0];
501
  $attachment_post = get_post( $attachment_id );
@@ -506,26 +460,26 @@ class Instant_Articles_Post {
506
  }
507
 
508
  /**
509
- * Filter the featured image
510
  *
511
  * @since 0.1
512
  * @param array $image_data {
513
  * Array containg image source and caption.
514
  *
515
- * @type string $src Image URL
516
- * @type string $caption Image caption
517
  * }
518
- * @param int $post_id The post ID
519
  */
520
- $image_data = apply_filters( 'instant_articles_featured_image', $image_data, $this->get_the_ID() );
521
  return $image_data;
522
  }
523
 
524
  /**
525
- * Get the cover media
526
  *
527
  * @since 0.1
528
- * @return array
529
  */
530
  public function get_cover_media() {
531
 
@@ -535,13 +489,13 @@ class Instant_Articles_Post {
535
  // If someone else is handling this, let them. Otherwise fall back to us trying to use the featured image.
536
  if ( has_filter( 'instant_articles_cover_media' ) ) {
537
  /**
538
- * Filter the cover media
539
  *
540
  * @since 0.1
541
- * @param stdClass $cover_media The cover media object
542
- * @param int $post_id The current post ID
543
  */
544
- $cover_media = apply_filters( 'instant_articles_cover_media', $cover_media, $this->get_the_ID() );
545
  } else {
546
  $featured_image_data = $this->get_the_featured_image();
547
  if ( isset( $featured_image_data['src'] ) && strlen( $featured_image_data['src'] ) ) {
@@ -555,10 +509,10 @@ class Instant_Articles_Post {
555
  }
556
 
557
  /**
558
- * Get kicker text
559
  *
560
  * @since 0.1
561
- * @return string
562
  */
563
  public function get_the_kicker() {
564
 
@@ -573,145 +527,341 @@ class Instant_Articles_Post {
573
  }
574
 
575
  /**
576
- * Filter the kicker text
577
  *
578
  * @since 0.1
579
  *
580
  * @param string $category The first category returned from get_the_category().
581
- * @param int $post_id The post ID
582
  */
583
- $category_kicker = apply_filters('instant_articles_cover_kicker', $category, $this->get_the_ID() );
584
 
585
  return $category_kicker ? $category_kicker : '';
586
  }
587
 
588
  /**
589
- * Get newsfeed cover type, image or video
590
  *
591
  * @since 0.1
592
- * @return string
593
  */
594
  public function get_newsfeed_cover() {
595
 
596
  $type = 'image';
597
 
598
  /**
599
- * Filter the cover type property
600
  *
601
  * @since 0.1
602
  *
603
  * @param string $type Set to 'video' for video cover. Featured image (image) is default.
604
- * @param int $post_id The post ID
605
  */
606
- $type = apply_filters( 'instant_articles_cover_type', $type, $this->get_the_ID() );
607
 
608
  return $type;
609
  }
610
 
 
611
  /**
612
- * Get credits for footer.
613
  *
614
  * @since 0.1
615
- * @return string
616
  */
617
- public function get_the_footer_credits() {
618
 
619
  /**
620
- * Filter credits
621
- *
622
- * @since 0.1
623
- *
624
- * @param string No credits set by default.
625
- * @param int The post ID
626
- */
627
- $footer_credits = apply_filters( 'instant_articles_footer_credits', '', $this->get_the_ID() );
628
- return $footer_credits;
629
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
630
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
631
 
632
  /**
633
- * Get copyright for footer
634
  *
635
- * @since 0.1
636
- * @return string
637
  */
638
- public function get_the_footer_copyright() {
 
639
 
640
- /**
641
- * Filter copyright
642
- *
643
- * @since 0.1
644
- *
645
- * @param string No copyright set by default.
646
- * @param int The post ID
647
- */
648
- $footer_copyright = apply_filters( 'instant_articles_footer_copyright', '', $this->get_the_ID() );
649
- return $footer_copyright;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
650
  }
651
 
652
  /**
653
- * Render post
654
  *
655
- * @since 0.1
656
  */
657
- function render() {
658
-
659
- /**
660
- * Fires before the instant article is rendered
661
- *
662
- * @since 0.1
663
- * @param Instant_Article_Post $instant_article_post The instant article post
664
- */
665
- do_action( 'instant_articles_before_render_post', $this );
666
-
667
- $default_template = dirname( __FILE__ ) . '/template.php';
 
 
 
 
 
 
 
 
668
 
669
- /**
670
- * Filter the path to the template to use to render the instant article
671
- *
672
- * @since 0.1
673
- * @param string $template Path to the current (default) template.
674
- * @param Instant_Article_Post $instant_article_post The instant article post
675
- */
676
- $template = apply_filters( 'instant_articles_render_post_template', $default_template, $this );
677
-
678
- // Make sure the template exists. Devs do the darndest things.
679
- // Note on validate_file(): Return value of 0 means nothing is wrong, greater than 0 means something was wrong.
680
- if ( ! file_exists( $template ) || validate_file( $template ) ) {
681
- $template = $default_template;
 
 
 
 
 
 
 
 
682
  }
683
- include $template;
684
-
685
- /**
686
- * Fires after the instant article is rendered
687
- *
688
- * @since 0.1
689
- * @param Instant_Article_Post $instant_article_post The instant article post
690
- */
691
- do_action( 'instant_articles_after_render_post', $this );
692
  }
693
 
694
  /**
695
- * Article <head> style
696
  *
697
  * @since 0.1
698
- * @return string The article style
699
  */
700
- function get_article_style() {
701
 
702
  /**
703
- * Filter the article style to use
704
- *
705
- * @since 0.1
706
- * @param string $template Path to the current (default) template.
707
- * @param Instant_Article_Post $instant_article_post The instant article post
708
- */
709
  $article_style = apply_filters( 'instant_articles_style', 'default', $this );
710
 
711
  return $article_style;
712
  }
713
-
714
  }
715
-
716
-
717
-
1
  <?php
2
+ /**
3
+ * Facebook Instant Articles for WP.
4
+ * This source code is licensed under the license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @package default
8
+ */
9
 
10
+ use Facebook\InstantArticles\Elements\InstantArticle;
11
+ use Facebook\InstantArticles\Elements\Header;
12
+ use Facebook\InstantArticles\Elements\Time;
13
+ use Facebook\InstantArticles\Elements\Ad;
14
+ use Facebook\InstantArticles\Elements\Analytics;
15
+ use Facebook\InstantArticles\Elements\Author;
16
+ use Facebook\InstantArticles\Elements\Image;
17
+ use Facebook\InstantArticles\Elements\Caption;
18
+ use Facebook\InstantArticles\Elements\Footer;
19
+ use Facebook\InstantArticles\Transformer\Transformer;
20
  /**
21
  * Class responsible for constructing our content and preparing it for rendering
22
  *
24
  */
25
  class Instant_Articles_Post {
26
 
27
+ /**
28
+ * The post
29
+ *
30
+ * @var $_post
31
+ */
32
+ protected $_post = null;
33
 
34
+ /**
35
+ * The post cached content
36
+ *
37
+ * @var string $_content
38
+ */
39
  protected $_content = null;
40
 
41
  /** @var string The post’s optional subtitle */
42
  protected $_subtitle = null;
43
 
44
+ /**
45
+ * Instant Article instance object
46
+ *
47
+ * @var InstantArticle Last built version of the Instant Article object
48
+ */
49
+ protected $_instant_article = null;
50
+
51
+ /**
52
+ * Instant Article Transformer instance object
53
+ *
54
+ * @var Transformer The Transformer object
55
+ */
56
+ public $transformer = null;
57
+
58
  /**
59
  * Setup data and build the content
60
  *
61
  * @since 0.1
62
+ * @param Instant_Article_Post $post ID of the post.
63
  */
64
+ public function __construct( $post ) {
65
+ $this->_post = $post;
66
  }
67
 
68
  /**
69
+ * Get the ID for this post.
70
  *
71
  * @since 0.1
72
+ * @return int The post ID.
73
  */
74
+ public function get_the_id() {
75
+ return $this->_post->ID;
76
  }
77
 
78
  /**
79
+ * Get the title for this post.
80
  *
81
  * @since 0.1
82
+ * @return string The title.
83
  */
84
  public function get_the_title() {
85
+ $title = $this->_post->post_title;
86
 
87
  /**
88
+ * Filter the post title for use in instant articles.
89
  *
90
  * @since 0.1
91
  *
92
+ * @param string $title The current post title.
93
+ * @param Instant_Article_Post $instant_article_post The instant article post.
94
  */
95
  $title = apply_filters( 'instant_articles_title', $title, $this );
96
 
98
  }
99
 
100
  /**
101
+ * Get the title for this post.
102
  *
103
  * @since 0.1
104
+ * @return string The title.
105
  */
106
  public function get_the_title_rss() {
107
  $title = $this->get_the_title();
111
  *
112
  * @since 0.1
113
  *
114
+ * @param string $title The current post title.
115
  */
116
  $title = apply_filters( 'the_title_rss', $title );
117
 
125
  * @return bool Whether the post has a subtitle or not
126
  */
127
  public function has_subtitle() {
128
+
129
  $has_subtitle = false;
130
 
131
  $subtitle = $this->get_the_subtitle();
168
  }
169
 
170
  /**
171
+ * Get the excerpt for this post.
 
 
 
 
172
  *
173
  * @since 0.1
174
+ * @return string The excerpt.
 
 
 
 
 
 
 
 
 
 
 
 
175
  */
176
  public function get_the_excerpt() {
177
 
178
+ $post = get_post( $this->get_the_id() );
179
 
180
  // This should ideally not happen, but it may do so if someone tampers with the query.
181
  // Returning the same protected post excerpt as "usual" may help them identify what’s going on.
183
  return __( 'There is no excerpt because this is a protected post.' );
184
  }
185
 
186
+ // Make sure no “read more” link is added.
187
  add_filter( 'excerpt_more', '__return_empty_string', 999 );
188
 
189
  /**
190
+ * Apply the default WP Filters for the post excerpt.
191
  *
192
  * @since 0.1
193
  *
196
  $excerpt = apply_filters( 'get_the_excerpt', $post->post_excerpt );
197
 
198
  /**
199
+ * Filter the post excerpt for instant articles.
200
  *
201
  * @since 0.1
202
  *
203
+ * @param string $excerpt The current post excerpt.
204
+ * @param Instant_Article_Post $instant_article_post The instant article post.
205
  */
206
  $excerpt = apply_filters( 'instant_articles_excerpt', $excerpt, $this );
207
 
230
  return $excerpt;
231
  }
232
 
233
+ /**
234
+ * Get the canonical URL for this post
235
+ *
236
+ * A little warning here: It is extremely important that this is the same canonical URL as is used on the web site.
237
+ * This is the identificator Facebook use to connect the "read" web article with the instant article.
238
+ * Do not add any querystring params or URL fragments it. Not any. Not even for tracking.
239
+ *
240
+ * @since 0.1
241
+ * @return string The canonical URL
242
+ */
243
+ public function get_canonical_url() {
244
+ // If post is draft, clone it to get the eventual permalink,
245
+ // see http://wordpress.stackexchange.com/a/42988.
246
+ if ( in_array( $this->_post->post_status, array( 'draft', 'pending', 'auto-draft' ), true ) ) {
247
+ $post_clone = clone $this->_post;
248
+ $post_clone->post_status = 'published';
249
+ $post_clone->post_name = sanitize_title( $post_clone->post_name ? $post_clone->post_name : $post_clone->post_title, $post_clone->ID );
250
+ $url = get_permalink( $post_clone );
251
+ } else {
252
+ $url = get_permalink( $this->_post );
253
+ }
254
+
255
+ return $url;
256
+ }
257
+
258
  /**
259
  * Get the article body for this post
260
  *
279
  */
280
  protected function _get_the_content() {
281
 
282
+ // Try to get the content from a transient, but only if the cached version have the same modtime.
283
+ $cache_mod_time = get_transient( 'instantarticles_mod_' . $this->_post->ID );
284
+ if ( get_post_modified_time( 'Y-m-d H:i:s', true, $this->_post->ID ) === $cache_mod_time ) {
285
+ $content = get_transient( 'instantarticles_content_' . $this->_post->ID );
286
+ if ( false !== $content && strlen( $content ) ) {
287
  return $content;
288
  }
289
  }
290
 
291
  global $post, $more;
292
 
293
+ if ( ! $post ) {
294
+ return '';
295
+ }
296
+
297
+ // Force $more.
298
  $orig_more = $more;
299
  $more = 1;
300
 
301
+ // If we’re not it the loop or otherwise properly setup.
302
  $reset_postdata = false;
303
+ if ( $this->_post->ID !== $post->ID ) {
304
+ $post = get_post( $this->_post->ID );
305
  setup_postdata( $post );
306
  $reset_postdata = true;
307
  }
308
 
309
+ // Now get the content.
310
+ $content = $this->_post->post_content;
311
 
312
  /**
313
+ * Apply the default filter 'the_content' for the post content.
314
  *
315
  * @since 0.1
316
  * @param string $content The current post content.
327
  $content = wpautop( $content );
328
 
329
  /**
330
+ * Filter the post content for Instant Articles.
331
  *
332
  * @since 0.1
333
  * @param string $content The post content.
334
  */
335
  $content = apply_filters( 'instant_articles_content', $content );
336
 
337
+ // Cache the content.
338
+ set_transient( 'instantarticles_mod_' . $this->_post->ID, get_post_modified_time( 'Y-m-d H:i:s', true, $this->_post->ID ), WEEK_IN_SECONDS );
339
+ set_transient( 'instantarticles_content_' . $this->_post->ID, $content, WEEK_IN_SECONDS );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
340
 
341
  return $content;
342
  }
343
 
344
  /**
345
+ * Get the published date for this post (ISO 8601).
346
  *
347
  * @since 0.1
348
+ * @return string The published date formatted suitable for use in the RSS feed and the html time elements (ISO 8601).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
349
  */
350
  public function get_the_pubdate_iso() {
351
 
352
+ $published_date = mysql2date( 'c', get_post_time( 'Y-m-d H:i:s', true, $this->_post->ID ), false );
353
 
354
  /**
355
+ * Filter the post published date (ISO 8601).
356
  *
357
  * @since 0.1
358
  *
359
  * @param string $published_date The current post published date.
360
+ * @param Instant_Article_Post $instant_article_post The instant article post.
361
  */
362
  $published_date = apply_filters( 'instant_articles_published_date_iso', $published_date, $this );
363
 
366
  }
367
 
368
  /**
369
+ * Get the modified date for this post (ISO 8601).
370
  *
371
  * @since 0.1
372
+ * @return string The modified date formatted suitable for use in the RSS feed and the html time elements (ISO 8601).
373
  */
374
  public function get_the_moddate_iso() {
375
 
376
+ $modified_date = mysql2date( 'c', get_post_modified_time( 'Y-m-d H:i:s', true, $this->_post->ID ), false );
377
 
378
  /**
379
+ * Filter the post modified date (ISO 8601).
380
  *
381
  * @since 0.1
382
  *
383
  * @param string $modified_date The current post modified date.
384
+ * @param Instant_Article_Post $instant_article_post The instant article post.
385
  */
386
  $modified_date = apply_filters( 'instant_articles_modified_date_iso', $modified_date, $this );
387
 
389
 
390
  }
391
  /**
392
+ * Get the author(s).
393
  *
394
  * @since 0.1
395
+ * @return array $authors The post author(s).
396
  */
397
  public function get_the_authors() {
398
 
399
  $authors = array();
400
 
401
+ $wp_user = get_userdata( $this->_post->author );
402
 
403
+ if ( is_a( $wp_user, 'WP_User' ) ) {
 
 
404
  $author = new stdClass;
405
+ $author->ID = $wp_user->ID;
406
+ $author->display_name = $wp_user->data->display_name;
407
+ $author->first_name = $wp_user->first_name;
408
+ $author->last_name = $wp_user->last_name;
409
+ $author->user_login = $wp_user->data->user_login;
410
+ $author->user_nicename = $wp_user->data->user_nicename;
411
+ $author->user_email = $wp_user->data->user_email;
412
+ $author->user_url = $wp_user->data->user_url;
413
+ $author->bio = $wp_user->description;
414
 
415
  $authors[] = $author;
416
  }
417
 
418
  /**
419
+ * Filter the post author(s).
420
  *
421
  * @since 0.1
422
  *
423
  * @param array $authors The current post author(s).
424
+ * @param int $post_id The instant article post.
425
  */
426
+ $authors = apply_filters( 'instant_articles_authors', $authors, $this->_post->ID );
427
 
428
  return $authors;
429
  }
430
 
431
  /**
432
+ * Get featured image for cover.
433
  *
434
  * @since 0.1
435
  * @return array {
436
  * Array containing image source and caption.
437
  *
438
+ * @type string $src Image URL.
439
+ * @type string $caption Image caption.
440
  * }
441
  */
442
  public function get_the_featured_image() {
445
  'src' => '',
446
  'caption' => '',
447
  );
448
+ if ( has_post_thumbnail( $this->_post->ID ) ) {
449
+
450
+ $image_array = wp_get_attachment_image_src( get_post_thumbnail_id( $this->_post->ID ), 'full' );
451
+ $attachment_id = get_post_thumbnail_id( $this->_post->ID );
452
 
 
 
 
453
  if ( is_array( $image_array ) ) {
454
  $image_data['src'] = $image_array[0];
455
  $attachment_post = get_post( $attachment_id );
460
  }
461
 
462
  /**
463
+ * Filter the featured image.
464
  *
465
  * @since 0.1
466
  * @param array $image_data {
467
  * Array containg image source and caption.
468
  *
469
+ * @type string $src Image URL.
470
+ * @type string $caption Image caption.
471
  * }
472
+ * @param int $post_id The post ID.
473
  */
474
+ $image_data = apply_filters( 'instant_articles_featured_image', $image_data, $this->_post->ID );
475
  return $image_data;
476
  }
477
 
478
  /**
479
+ * Get the cover media.
480
  *
481
  * @since 0.1
482
+ * @return array
483
  */
484
  public function get_cover_media() {
485
 
489
  // If someone else is handling this, let them. Otherwise fall back to us trying to use the featured image.
490
  if ( has_filter( 'instant_articles_cover_media' ) ) {
491
  /**
492
+ * Filter the cover media.
493
  *
494
  * @since 0.1
495
+ * @param stdClass $cover_media The cover media object.
496
+ * @param int $post_id The current post ID.
497
  */
498
+ $cover_media = apply_filters( 'instant_articles_cover_media', $cover_media, $this->_post->ID );
499
  } else {
500
  $featured_image_data = $this->get_the_featured_image();
501
  if ( isset( $featured_image_data['src'] ) && strlen( $featured_image_data['src'] ) ) {
509
  }
510
 
511
  /**
512
+ * Get kicker text.
513
  *
514
  * @since 0.1
515
+ * @return string
516
  */
517
  public function get_the_kicker() {
518
 
527
  }
528
 
529
  /**
530
+ * Filter the kicker text.
531
  *
532
  * @since 0.1
533
  *
534
  * @param string $category The first category returned from get_the_category().
535
+ * @param int $post_id The post ID.
536
  */
537
+ $category_kicker = apply_filters( 'instant_articles_cover_kicker', $category, $this->_post->ID );
538
 
539
  return $category_kicker ? $category_kicker : '';
540
  }
541
 
542
  /**
543
+ * Get newsfeed cover type, image or video.
544
  *
545
  * @since 0.1
546
+ * @return string
547
  */
548
  public function get_newsfeed_cover() {
549
 
550
  $type = 'image';
551
 
552
  /**
553
+ * Filter the cover type property.
554
  *
555
  * @since 0.1
556
  *
557
  * @param string $type Set to 'video' for video cover. Featured image (image) is default.
558
+ * @param int $post_id The post ID.
559
  */
560
+ $type = apply_filters( 'instant_articles_cover_type', $type, $this->_post->ID );
561
 
562
  return $type;
563
  }
564
 
565
+
566
  /**
567
+ * Render post
568
  *
569
  * @since 0.1
570
+ * @return InstantArticle
571
  */
572
+ public function to_instant_article() {
573
 
574
  /**
575
+ * Fires before the instant article is rendered.
576
+ *
577
+ * @since 0.1
578
+ * @param Instant_Article_Post $instant_article_post The instant article post.
579
+ */
580
+ do_action( 'instant_articles_before_transform_post', $this );
581
+
582
+ // Get time zone configured in WordPress. Default to UTC if no time zone configured.
583
+ $date_time_zone = get_option( 'timezone_string' ) ? new DateTimeZone( get_option( 'timezone_string' ) ) : new DateTimeZone( 'UTC' );
584
+
585
+ $header =
586
+ Header::create()
587
+ ->withPublishTime(
588
+ Time::create( Time::PUBLISHED )->withDatetime( new DateTime( $this->_post->post_date, $date_time_zone ) )
589
+ )
590
+ ->withModifyTime(
591
+ Time::create( Time::MODIFIED )->withDatetime( new DateTime( $this->_post->post_modified, $date_time_zone ) )
592
+ )
593
+ ->withTitle( $this->get_the_title() );
594
+
595
+ $authors = $this->get_the_authors();
596
+ foreach ( $authors as $author ) {
597
+ $author_obj = Author::create();
598
+ if ( $author->display_name ) {
599
+ $author_obj->withName( $author->display_name );
600
+ }
601
+ if ( $author->bio ) {
602
+ $author_obj->withDescription( $author->bio );
603
+ }
604
+ if ( $author->user_url ) {
605
+ $author_obj->withURL( $author->user_url );
606
+ }
607
+ $header->addAuthor( $author );
608
+ }
609
+ $kicker = $this->get_the_kicker();
610
+ if ( $kicker ) {
611
+ $header->withKicker( $kicker );
612
+ }
613
+ $cover = $this->get_the_featured_image();
614
+ if ( $cover['src'] ) {
615
+ $image = Image::create()->withURL( $cover['src'] );
616
+ if ( isset( $cover['caption'] ) && strlen( $cover['caption'] ) > 0 ) {
617
+ $image->withCaption(
618
+ Caption::create()->withTitle( $cover['caption'] )
619
+ );
620
+ }
621
+
622
+ $header->withCover( $image );
623
+ }
624
+ $this->instant_article =
625
+ InstantArticle::create()
626
+ ->withCanonicalUrl( $this->get_canonical_url() )
627
+ ->withHeader( $header );
628
+
629
+ $settings_style = Instant_Articles_Option_Styles::get_option_decoded();
630
+ if ( isset( $settings_style['article_style'] ) && ! empty ( $settings_style['article_style'] ) ) {
631
+ $this->instant_article->withStyle( $settings_style['article_style'] );
632
+ }
633
+ else {
634
+ $this->instant_article->withStyle( 'default' );
635
+ }
636
+
637
+ $file_path = plugin_dir_path( __FILE__ ) . 'rules-configuration.json';
638
+ $configuration = file_get_contents( $file_path );
639
 
640
+ $transformer = new Transformer();
641
+ $this->transformer = $transformer;
642
+ $transformer->loadRules( $configuration );
643
+
644
+ $transformer = apply_filters( 'instant_articles_transformer_rules_loaded', $transformer );
645
+
646
+ $settings_publishing = Instant_Articles_Option_Publishing::get_option_decoded();
647
+
648
+ if (
649
+ isset ( $settings_publishing['custom_rules_enabled'] ) &&
650
+ ! empty( $settings_publishing['custom_rules_enabled'] ) &&
651
+ isset ( $settings_publishing['custom_rules'] ) &&
652
+ ! empty( $settings_publishing['custom_rules'] )
653
+ ) {
654
+ $transformer->loadRules( $settings_publishing['custom_rules'] );
655
+ }
656
+
657
+ $transformer = apply_filters( 'instant_articles_transformer_custom_rules_loaded', $transformer );
658
+
659
+ $libxml_previous_state = libxml_use_internal_errors( true );
660
+ $document = new DOMDocument( '1.0', get_option( 'blog_charset' ) );
661
+ $content = $this->get_the_content();
662
+
663
+ // DOMDocument isn’t handling encodings too well, so let’s help it a little.
664
+ if ( function_exists( 'mb_convert_encoding' ) ) {
665
+ $content = mb_convert_encoding( $content, 'HTML-ENTITIES', get_option( 'blog_charset' ) );
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
+
672
+ $document = apply_filters( 'instant_articles_parsed_document', $document );
673
+
674
+ if ( $result ) {
675
+ $transformer->transform( $this->instant_article, $document );
676
+ }
677
+
678
+ $this->add_ads_from_settings();
679
+ $this->add_analytics_from_settings();
680
+
681
+ $this->instant_article = apply_filters( 'instant_articles_transformed_element', $this->instant_article );
682
+
683
+ /**
684
+ * Fires after the instant article is rendered.
685
+ *
686
+ * @since 0.1
687
+ * @param Instant_Article_Post $instant_article_post The instant article post.
688
+ */
689
+ do_action( 'instant_articles_after_transform_post', $this );
690
+
691
+ return $this->instant_article;
692
+ }
693
 
694
  /**
695
+ * Add all ad code(s) to the Header of an InstantArticle.
696
  *
697
+ * @since 0.3
 
698
  */
699
+ public function add_ads_from_settings() {
700
+ $header = $this->instant_article->getHeader();
701
 
702
+ $settings_ads = Instant_Articles_Option_Ads::get_option_decoded();
703
+
704
+ $width = 300;
705
+ $height = 250;
706
+
707
+ $dimensions_match = array();
708
+ $dimensions_raw = isset( $settings_ads['dimensions'] ) ? $settings_ads['dimensions'] : null;
709
+ if ( preg_match( '/^(?:\s)*(\d+)x(\d+)(?:\s)*$/', $dimensions_raw, $dimensions_match ) ) {
710
+ $width = intval( $dimensions_match[1] );
711
+ $height = intval( $dimensions_match[2] );
712
+ }
713
+
714
+ $ad = Ad::create()
715
+ ->enableDefaultForReuse()
716
+ ->withWidth( $width )
717
+ ->withHeight( $height );
718
+
719
+ $source_of_ad = isset( $settings_ads['ad_source'] ) ? $settings_ads['ad_source'] : 'none';
720
+ switch ( $source_of_ad ) {
721
+
722
+ case 'none':
723
+ break;
724
+
725
+ case 'fan':
726
+ if ( ! empty( $settings_ads['fan_placement_id'] ) ) {
727
+ $placement_id = $settings_ads['fan_placement_id'];
728
+
729
+ $ad->withSource(
730
+ add_query_arg(
731
+ array(
732
+ 'placement' => $placement_id,
733
+ 'adtype' => 'banner' . $width . 'x' . $height,
734
+ ),
735
+ 'https://www.facebook.com/adnw_request'
736
+ )
737
+ );
738
+
739
+ $header->addAd( $ad );
740
+ }
741
+ break;
742
+
743
+ case 'iframe':
744
+ if ( ! empty( $settings_ads['iframe_url'] ) ) {
745
+ $ad->withSource(
746
+ $settings_ads['iframe_url']
747
+ );
748
+
749
+ $header->addAd( $ad );
750
+ }
751
+ break;
752
+
753
+ case 'embed':
754
+ if ( ! empty( $settings_ads['embed_code'] ) ) {
755
+
756
+ $document = new DOMDocument();
757
+ $fragment = $document->createDocumentFragment();
758
+ $valid_html = @$fragment->appendXML( $settings_ads['embed_code'] );
759
+
760
+ if ( $valid_html ) {
761
+ $ad->withHTML(
762
+ $fragment
763
+ );
764
+ $header->addAd( $ad );
765
+ }
766
+ }
767
+ break;
768
+
769
+ default:
770
+ if ( ! empty( $source_of_ad ) ) {
771
+ $registered_compat_ads = Instant_Articles_Option::get_registered_compat( 'instant_articles_compat_registry_ads' );
772
+ foreach ( $registered_compat_ads as $compat_id => $compat_info ) {
773
+ if ( array_key_exists( $compat_id, $registered_compat_ads ) ) {
774
+
775
+ $document = new DOMDocument();
776
+ $fragment = $document->createDocumentFragment();
777
+ $valid_html = @$fragment->appendXML( $compat_info['payload'] );
778
+
779
+ if ( $valid_html ) {
780
+ $ad = Ad::create()
781
+ ->enableDefaultForReuse()
782
+ ->withWidth( $width )
783
+ ->withHeight( $height )
784
+ ->withHTML(
785
+ $fragment
786
+ );
787
+
788
+ $header->addAd( $ad );
789
+ }
790
+ }
791
+ }
792
+ }
793
+ break;
794
+ }
795
+
796
+ $this->instant_article->enableAutomaticAdPlacement();
797
  }
798
 
799
  /**
800
+ * Add all analytic tracking code(s) an InstantArticle.
801
  *
802
+ * @since 0.3
803
  */
804
+ public function add_analytics_from_settings() {
805
+ $settings_analytics = Instant_Articles_Option_Analytics::get_option_decoded();
806
+
807
+ if ( isset( $settings_analytics['embed_code_enabled'] ) && ! empty( $settings_analytics['embed_code'] ) ) {
808
+
809
+ $document = new DOMDocument();
810
+ $fragment = $document->createDocumentFragment();
811
+ $valid_html = @$fragment->appendXML( $settings_analytics['embed_code'] );
812
+
813
+ if ( $valid_html ) {
814
+ $this->instant_article
815
+ ->addChild(
816
+ Analytics::create()
817
+ ->withHTML(
818
+ $fragment
819
+ )
820
+ );
821
+ }
822
+ }
823
 
824
+ if ( ! empty( $settings_analytics['integrations'] ) ) {
825
+ $settings_analytics_compats = $settings_analytics['integrations'];
826
+ $registered_compat_analytics = Instant_Articles_Option::get_registered_compat( 'instant_articles_compat_registry_analytics' );
827
+ foreach ( $registered_compat_analytics as $compat_id => $compat_info ) {
828
+ if ( in_array( $compat_id, $settings_analytics_compats, true ) ) {
829
+
830
+ $document = new DOMDocument();
831
+ $fragment = $document->createDocumentFragment();
832
+ $valid_html = @$fragment->appendXML( $compat_info['payload'] );
833
+
834
+ if ( $valid_html ) {
835
+ $this->instant_article
836
+ ->addChild(
837
+ Analytics::create()
838
+ ->withHTML(
839
+ $fragment
840
+ )
841
+ );
842
+ }
843
+ }
844
+ }
845
  }
 
 
 
 
 
 
 
 
 
846
  }
847
 
848
  /**
849
+ * Article <head> style.
850
  *
851
  * @since 0.1
852
+ * @return string The article style.
853
  */
854
+ public function get_article_style() {
855
 
856
  /**
857
+ * Filter the article style to use.
858
+ *
859
+ * @since 0.1
860
+ * @param string $template Path to the current (default) template.
861
+ * @param Instant_Article_Post $instant_article_post The instant article post.
862
+ */
863
  $article_style = apply_filters( 'instant_articles_style', 'default', $this );
864
 
865
  return $article_style;
866
  }
 
867
  }
 
 
 
class-instant-articles-publisher.php ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Facebook Instant Articles for WP.
4
+ * This source code is licensed under the license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @package default
8
+ */
9
+
10
+ use Facebook\InstantArticles\Client\Client;
11
+ use Facebook\Facebook;
12
+
13
+ /**
14
+ * Class responsible for drawing the meta box on the post edit page
15
+ *
16
+ * @since 0.1
17
+ */
18
+ class Instant_Articles_Publisher {
19
+
20
+ /**
21
+ * Inits publisher.
22
+ */
23
+ public static function init() {
24
+ add_action( 'save_post', array( 'Instant_Articles_Publisher', 'submit_article' ), 10, 2 );
25
+ }
26
+
27
+ /**
28
+ * Submits article to Instant Articles.
29
+ *
30
+ * @param string $post_id The identifier of post.
31
+ * @param Post $post The WP Post.
32
+ */
33
+ public static function submit_article( $post_id, $post ) {
34
+
35
+ // Don't process if this is just a revision or an autosave.
36
+ if ( wp_is_post_revision( $post ) || wp_is_post_autosave( $post ) ) {
37
+ return;
38
+ }
39
+
40
+ // Transform the post to an Instant Article.
41
+ $adapter = new Instant_Articles_Post( $post );
42
+ $article = $adapter->to_instant_article();
43
+
44
+ // Instantiate an API client.
45
+ try {
46
+ $fb_app_settings = Instant_Articles_Option_FB_App::get_option_decoded();
47
+ $fb_page_settings = Instant_Articles_Option_FB_Page::get_option_decoded();
48
+ $publishing_settings = Instant_Articles_Option_Publishing::get_option_decoded();
49
+
50
+ $dev_mode = isset( $publishing_settings['dev_mode'] )
51
+ ? ( $publishing_settings['dev_mode'] ? true : false )
52
+ : false;
53
+
54
+ if ( isset( $fb_app_settings['app_id'] )
55
+ && isset( $fb_app_settings['app_secret'] )
56
+ && isset( $fb_page_settings['page_access_token'] )
57
+ && isset( $fb_page_settings['page_id'] ) ) {
58
+
59
+ $client = Client::create(
60
+ $fb_app_settings['app_id'],
61
+ $fb_app_settings['app_secret'],
62
+ $fb_page_settings['page_access_token'],
63
+ $fb_page_settings['page_id'],
64
+ $dev_mode
65
+ );
66
+
67
+ if ( $dev_mode ) {
68
+ $take_live = false;
69
+ } else {
70
+ // Any publish status other than 'publish' means draft for the Instant Article.
71
+ $take_live = 'publish' === $post->post_status;
72
+ }
73
+
74
+ try {
75
+ // Import the article.
76
+ $client->importArticle( $article, $take_live );
77
+ } catch ( Exception $e ) {
78
+ // Try without taking live for pages not yet reviewed.
79
+ $client->importArticle( $article, false );
80
+ }
81
+ }
82
+ } catch ( Exception $e ) {
83
+ Logger::getLogger( 'instantarticles-wp-plugin' )->error(
84
+ 'Unable to submit article.',
85
+ $e->getTraceAsString()
86
+ );
87
+ }
88
+ }
89
+ }
compat.php CHANGED
@@ -1,20 +1,27 @@
1
  <?php
 
 
 
 
 
 
 
2
 
3
- // Load compat layer for Co-Authors Plus
4
  if ( function_exists( 'get_coauthors' ) && ! defined( 'CAP_IA_COMPAT' ) ) {
5
- include( dirname( __FILE__ ) . '/compat/class-instant-articles-co-authors-plus.php' );
6
  $cap = new Instant_Articles_Co_Authors_Plus;
7
  $cap->init();
8
  }
9
 
10
- // Load compat layer for Yoast SEO
11
  if ( defined( 'WPSEO_VERSION' ) && ! defined( 'WPSEO_IA_COMPAT' ) ) {
12
- include( dirname( __FILE__ ) . '/compat/class-instant-articles-yoast-seo.php' );
13
  $yseo = new Instant_Articles_Yoast_SEO;
14
  $yseo->init();
15
  }
16
 
17
- // Load support for Google Analytics for WordPress (Google Analytics by Yoast)
18
  if ( defined( 'GAWP_VERSION' ) && ! defined( 'GAWP_IA_COMPAT' ) ) {
19
  include( dirname( __FILE__ ) . '/compat/class-instant-articles-google-analytics-for-wordpress.php' );
20
  $gawp = new Instant_Articles_Google_Analytics_For_WordPress;
@@ -27,4 +34,3 @@ if ( defined( 'JETPACK__VERSION' ) ) {
27
  $jp = new Instant_Articles_Jetpack;
28
  $jp->init();
29
  }
30
-
1
  <?php
2
+ /**
3
+ * Facebook Instant Articles for WP.
4
+ * This source code is licensed under the license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @package default
8
+ */
9
 
10
+ // Load compat layer for Co-Authors Plus.
11
  if ( function_exists( 'get_coauthors' ) && ! defined( 'CAP_IA_COMPAT' ) ) {
12
+ include( dirname( __FILE__ ) . '/compat/class-instant-articles-co-authors-plus.php' );
13
  $cap = new Instant_Articles_Co_Authors_Plus;
14
  $cap->init();
15
  }
16
 
17
+ // Load compat layer for Yoast SEO.
18
  if ( defined( 'WPSEO_VERSION' ) && ! defined( 'WPSEO_IA_COMPAT' ) ) {
19
+ include( dirname( __FILE__ ) . '/compat/class-instant-articles-yoast-seo.php' );
20
  $yseo = new Instant_Articles_Yoast_SEO;
21
  $yseo->init();
22
  }
23
 
24
+ // Load support for Google Analytics for WordPress (Google Analytics by Yoast).
25
  if ( defined( 'GAWP_VERSION' ) && ! defined( 'GAWP_IA_COMPAT' ) ) {
26
  include( dirname( __FILE__ ) . '/compat/class-instant-articles-google-analytics-for-wordpress.php' );
27
  $gawp = new Instant_Articles_Google_Analytics_For_WordPress;
34
  $jp = new Instant_Articles_Jetpack;
35
  $jp->init();
36
  }
 
compat/class-instant-articles-co-authors-plus.php CHANGED
@@ -1,33 +1,38 @@
1
  <?php
 
 
 
 
 
 
 
2
 
3
  /**
4
  * Compatibility layer for Co-Authors Plus
5
  *
6
  * @since 0.1
7
- *
8
  */
9
  class Instant_Articles_Co_Authors_Plus {
10
 
11
  /**
12
- * Init the compat layer
13
- *
14
  */
15
  function init() {
16
  add_filter( 'instant_articles_authors', array( $this, 'authors' ), 10, 2 );
17
  }
18
 
19
  /**
20
- * Filter the authors
21
  *
22
- * @param array $authors The current authors
23
- * @param int $post_id The current post ID
24
  */
25
  function authors( $authors, $post_id ) {
26
  if ( function_exists( 'get_coauthors' ) ) {
27
  $coauthors = get_coauthors( $post_id );
28
 
29
  $authors = array();
30
- foreach( $coauthors as $coauthor ) {
31
 
32
  $author = new stdClass;
33
  $author->ID = $coauthor->ID;
@@ -46,5 +51,4 @@ class Instant_Articles_Co_Authors_Plus {
46
 
47
  return $authors;
48
  }
49
-
50
  }
1
  <?php
2
+ /**
3
+ * Facebook Instant Articles for WP.
4
+ * This source code is licensed under the license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @package default
8
+ */
9
 
10
  /**
11
  * Compatibility layer for Co-Authors Plus
12
  *
13
  * @since 0.1
 
14
  */
15
  class Instant_Articles_Co_Authors_Plus {
16
 
17
  /**
18
+ * Init the compat layer.
 
19
  */
20
  function init() {
21
  add_filter( 'instant_articles_authors', array( $this, 'authors' ), 10, 2 );
22
  }
23
 
24
  /**
25
+ * Filter the authors.
26
  *
27
+ * @param array $authors The current authors.
28
+ * @param int $post_id The current post ID.
29
  */
30
  function authors( $authors, $post_id ) {
31
  if ( function_exists( 'get_coauthors' ) ) {
32
  $coauthors = get_coauthors( $post_id );
33
 
34
  $authors = array();
35
+ foreach ( $coauthors as $coauthor ) {
36
 
37
  $author = new stdClass;
38
  $author->ID = $coauthor->ID;
51
 
52
  return $authors;
53
  }
 
54
  }
compat/class-instant-articles-google-analytics-for-wordpress.php CHANGED
@@ -4,25 +4,50 @@
4
  * Support class for Google Analytics for WordPress (Google Analytics by Yoast)
5
  *
6
  * @since 0.1
7
- *
8
  */
9
  class Instant_Articles_Google_Analytics_For_WordPress {
10
 
11
  /**
12
- * Init the compat layer
13
  *
 
 
 
 
 
 
14
  */
15
  function init() {
16
- add_filter( 'instant_articles_content', array( $this, 'add_ga_code' ), 10, 1 );
17
  }
18
 
19
  /**
20
- * Add the GA tracking code to the end of the content
 
21
  *
22
- * @since 0.1
23
- * @param string $content The post content.
24
  */
25
- function add_ga_code( $content ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
  $options = Yoast_GA_Options::instance()->options;
28
 
@@ -36,15 +61,6 @@ class Instant_Articles_Google_Analytics_For_WordPress {
36
  $tracker->tracking();
37
  $ga_code = ob_get_clean();
38
 
39
- if ( strlen( $ga_code ) ) {
40
- $ga = '<figure class="op-tracker"><iframe>';
41
- $ga .= $ga_code;
42
- $ga .= '</iframe></figure>';
43
-
44
- $content .= $ga;
45
- }
46
-
47
- return $content;
48
  }
49
-
50
  }
4
  * Support class for Google Analytics for WordPress (Google Analytics by Yoast)
5
  *
6
  * @since 0.1
 
7
  */
8
  class Instant_Articles_Google_Analytics_For_WordPress {
9
 
10
  /**
11
+ * File and path for analytics.
12
  *
13
+ * @var string $plugin_file File and path of googleanalytics.
14
+ */
15
+ public static $plugin_file = 'google-analytics-for-wordpress/googleanalytics.php';
16
+
17
+ /**
18
+ * Init the compat layer
19
  */
20
  function init() {
21
+ add_action( 'instant_articles_compat_registry_analytics', array( $this, 'add_to_registry' ) );
22
  }
23
 
24
  /**
25
+ * Adds identifying information about this 3rd party plugin
26
+ * to the wider registry.
27
  *
28
+ * @since 0.3
29
+ * @param array $registry Reference param. The registry where it will be stored.
30
  */
31
+ function add_to_registry( &$registry ) {
32
+
33
+ $display_name = 'Google Analytics by Yoast';
34
+
35
+ $identifier = 'google-analytics-for-wordpress';
36
+
37
+ $embed_code = $this->get_raw_embed_code();
38
+
39
+ $registry[ $identifier ] = array(
40
+ 'name' => $display_name,
41
+ 'payload' => $embed_code,
42
+ );
43
+ }
44
+
45
+ /**
46
+ * Returns the GA tracking code
47
+ *
48
+ * @since 0.3
49
+ */
50
+ function get_raw_embed_code() {
51
 
52
  $options = Yoast_GA_Options::instance()->options;
53
 
61
  $tracker->tracking();
62
  $ga_code = ob_get_clean();
63
 
64
+ return $ga_code;
 
 
 
 
 
 
 
 
65
  }
 
66
  }
compat/class-instant-articles-yoast-seo.php CHANGED
@@ -1,41 +1,39 @@
1
  <?php
2
-
3
  /**
4
  * Compatibility layer for Yoast SEO
5
  *
6
  * @since 0.1
7
- *
8
  */
9
  class Instant_Articles_Yoast_SEO {
10
 
11
  /**
12
- * Init the compat layer
13
- *
14
  */
15
  function init() {
16
  add_filter( 'instant_articles_featured_image', array( $this, 'override_featured_image' ), 10, 2 );
17
- add_filter( 'instant_articles_authors', array( $this, 'user_url' ), 11 , 2 ); // Hook in after other author modifications (like the Co-Authors Plus plugin)
 
18
  }
19
 
20
  /**
21
- * Override the featured image with the one set for Facebook
22
  *
23
  * @since 0.1
24
- * @param array $image data The current image data
25
- * @param int $post_id The instant article post
26
- * @return array The filtered image data
27
  */
28
  function override_featured_image( $image_data, $post_id ) {
29
 
30
  $image_url = get_post_meta( $post_id, '_yoast_wpseo_opengraph-image', true );
31
 
32
  if ( strlen( $image_url ) ) {
33
- $image_data[ 'src' ] = $image_url;
34
 
35
  $desc = get_post_meta( $post_id, '_yoast_wpseo_opengraph-description', true );
36
 
37
  if ( strlen( $desc ) ) {
38
- $image_data[ 'caption' ] = $desc;
39
  }
40
  }
41
 
@@ -43,12 +41,12 @@ class Instant_Articles_Yoast_SEO {
43
  }
44
 
45
  /**
46
- * Use the facebook URL as user_url if no other is set
47
  *
48
  * @since 0.1
49
- * @param array $authors The current post author(s).
50
- * @param int $post_id The instant article post
51
- * @return array The filtered authors
52
  */
53
  function user_url( $authors, $post_id ) {
54
 
@@ -64,6 +62,5 @@ class Instant_Articles_Yoast_SEO {
64
 
65
  return $authors;
66
 
67
- }
68
-
69
  }
1
  <?php
 
2
  /**
3
  * Compatibility layer for Yoast SEO
4
  *
5
  * @since 0.1
 
6
  */
7
  class Instant_Articles_Yoast_SEO {
8
 
9
  /**
10
+ * Init the compat layer.
 
11
  */
12
  function init() {
13
  add_filter( 'instant_articles_featured_image', array( $this, 'override_featured_image' ), 10, 2 );
14
+ // Hook in after other author modifications (like the Co-Authors Plus plugin).
15
+ add_filter( 'instant_articles_authors', array( $this, 'user_url' ), 11 , 2 );
16
  }
17
 
18
  /**
19
+ * Override the featured image with the one set for Facebook.
20
  *
21
  * @since 0.1
22
+ * @param array $image_data The current image data.
23
+ * @param int $post_id The instant article post.
24
+ * @return array The filtered image data.
25
  */
26
  function override_featured_image( $image_data, $post_id ) {
27
 
28
  $image_url = get_post_meta( $post_id, '_yoast_wpseo_opengraph-image', true );
29
 
30
  if ( strlen( $image_url ) ) {
31
+ $image_data['src'] = $image_url;
32
 
33
  $desc = get_post_meta( $post_id, '_yoast_wpseo_opengraph-description', true );
34
 
35
  if ( strlen( $desc ) ) {
36
+ $image_data['caption'] = $desc;
37
  }
38
  }
39
 
41
  }
42
 
43
  /**
44
+ * Use the facebook URL as user_url if no other is set.
45
  *
46
  * @since 0.1
47
+ * @param array $authors The current post author(s).
48
+ * @param int $post_id The instant article post.
49
+ * @return array The filtered authors.
50
  */
51
  function user_url( $authors, $post_id ) {
52
 
62
 
63
  return $authors;
64
 
65
+ }
 
66
  }
css/instant-articles-meta-box.css ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .instant-articles-messages {
2
+ margin-left: 15px;
3
+ margin-top: 0px;
4
+ }
5
+
6
+ .instant-articles-messages li {
7
+ display: table-row;
8
+ }
9
+
10
+ .instant-articles-messages li > div,
11
+ .instant-articles-messages li > span {
12
+ display: table-cell;
13
+ }
14
+
15
+ .instant-articles-messages li > div {
16
+ padding-left: 5px;
17
+ }
18
+
19
+ .instant-articles-transformer-markup {
20
+ display: none;
21
+ }
22
+
23
+ .instant-articles-show-debug .instant-articles-transformer-markup {
24
+ display: block;
25
+ }
26
+
27
+ .instant-articles-messages li .message span {
28
+ display: none;
29
+ }
30
+
31
+ .instant-articles-messages li:hover .message span {
32
+ display: block;
33
+ position: absolute;
34
+ width: 50%;
35
+ height: auto;
36
+ border: 1px solid #bb9;
37
+ padding: 5px;
38
+ background: #ffe;
39
+ overflow-y: auto;
40
+ color: #666;
41
+ margin: 10px;
42
+ }
43
+ .instant-articles-transformer-markup {
44
+ border-top: 1px dashed #ccc;
45
+ padding-top: 10px;
46
+ margin-top: 10px;
47
+ }
48
+ .instant-articles-transformer-markup div {
49
+ width: 50%;
50
+ float: left;
51
+ box-sizing: padding-box;
52
+ }
53
+
54
+ .instant-articles-transformer-markup div textarea {
55
+ width: 100%;
56
+ height: 400px;
57
+ }
58
+
59
+ /* Spinner code */
60
+ @keyframes instant_articles_spinner {
61
+ to {transform: rotate(360deg);}
62
+ }
63
+
64
+ @-webkit-keyframes instant_articles_spinner {
65
+ to {-webkit-transform: rotate(360deg);}
66
+ }
67
+
68
+ .instant_articles_spinner {
69
+ min-width: 24px;
70
+ min-height: 24px;
71
+ margin: 20px;
72
+ }
73
+
74
+ .instant_articles_spinner:before {
75
+ content: 'Loading…';
76
+ position: absolute;
77
+ top: 50%;
78
+ left: 50%;
79
+ width: 16px;
80
+ height: 16px;
81
+ margin-top: -10px;
82
+ margin-left: -10px;
83
+ }
84
+
85
+ .instant_articles_spinner:not(:required):before {
86
+ content: '';
87
+ border-radius: 50%;
88
+ border-top: 2px solid #03ade0;
89
+ border-right: 2px solid transparent;
90
+ animation: instant_articles_spinner .6s linear infinite;
91
+ -webkit-animation: instant_articles_spinner .6s linear infinite;
92
+ }
css/instant-articles-settings-wizard.css ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ .instant-articles-inline-form input[name='submit'] {
2
+ display: inline;
3
+ }
css/instant-articles-settings.css ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .instant-articles-settings-box {
2
+ background-color: #fff;
3
+ border: 1px solid #e5e5e5;
4
+ box-shadow: 1px 1px 1px 0 rgba(0,0,0,0.04);
5
+ margin: 0.85em 0 1.7em 0;
6
+ }
7
+ .instant-articles-settings-box > h2 {
8
+ color: #444;
9
+ margin: 0em;
10
+ padding: 8px 12px;
11
+ border-bottom: 1px solid #ddd;
12
+ cursor: pointer;
13
+ }
14
+ .instant-articles-settings-box .inside {
15
+ padding: 8px 12px;
16
+ }
embeds.php CHANGED
@@ -1,16 +1,14 @@
1
  <?php
2
-
3
  /**
4
- * Oembed/embed handling
 
 
5
  *
6
- * The embed result is most likely cached, so we have to handle it late. If it is not cached and we handle it early, it will be cached with an unwanted result
7
- * for regular posts. So we resort to parsing the embed result in the embed_oembed_html and embed_handler_html filters.
8
  */
9
 
10
-
11
  /**
12
  * Remove all extra oembed html filters added by themes and plugins.
13
- *
14
  */
15
  remove_all_filters( 'embed_oembed_html' );
16
 
@@ -18,37 +16,37 @@ remove_all_filters( 'embed_oembed_html' );
18
  * Filter the oembed results to see if we should do some extra handling
19
  *
20
  * @since 0.1
21
- * @param string $html The original HTML returned from the external oembed provider
22
- * @param string $url The URL found in the content
23
- * @param mixed $attr An array with extra attributes
24
- * @param int $post_ID The post ID
25
- * @return string The potentially filtered HTML
26
  */
27
- function instant_articles_embed_oembed_html( $html, $url, $attr, $post_ID ) {
28
 
29
  if ( ! class_exists( 'WP_oEmbed' ) ) {
30
  include_once( ABSPATH . WPINC . '/class-oembed.php' );
31
  }
32
 
33
- // Instead of checking all possible URL variants, use the provider list from WP_oEmbed
34
- $WP_oEmbed = new WP_oEmbed();
35
- $providerURL = $WP_oEmbed->get_provider( $url );
36
 
37
  $provider_name = false;
38
- if ( false !== strpos( $providerURL, 'instagram.com' ) ) {
39
  $provider_name = 'instagram';
40
- } elseif( false !== strpos( $providerURL, 'twitter.com' ) ) {
41
  $provider_name = 'twitter';
42
- } elseif( false !== strpos( $providerURL, 'youtube.com' ) ) {
43
  $provider_name = 'youtube';
44
- } elseif( false !== strpos( $providerURL, 'vine.co' ) ) {
45
  $provider_name = 'vine';
46
  }
47
 
48
  $provider_name = apply_filters( 'instant_articles_social_embed_type', $provider_name, $url );
49
 
50
  if ( $provider_name ) {
51
- $html = instant_articles_embed_get_html( $provider_name, $html, $url, $attr, $post_ID );
52
  }
53
 
54
  return $html;
@@ -58,74 +56,41 @@ add_filter( 'embed_oembed_html', 'instant_articles_embed_oembed_html', 10, 4 );
58
 
59
 
60
  /**
61
- * Filter the embed results for embeds
62
  *
63
  * @since 0.1
64
- * @param string $provider_name The name of the embed provider. E.g. “instagram” or “youtube
65
- * @param string $html The original HTML returned from the external oembed/embed provider
66
- * @param string $url The URL found in the content
67
- * @param mixed $attr An array with extra attributes
68
- * @param int $post_ID The post ID
69
- * @return string The filtered HTML
70
  */
71
- function instant_articles_embed_get_html( $provider_name, $html, $url, $attr, $post_ID ) {
72
-
73
- /*
74
- Example output from instagram:
75
- <blockquote class="instagram-media" data-instgrm-version="6" style=" background:#FFF; border:0; border-radius:3px; box-shadow:0 0 1px 0 rgba(0,0,0,0.5),0 1px 10px 0 rgba(0,0,0,0.15); margin: 1px; max-width:658px; padding:0; width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);"><div style="padding:8px;">
76
- <div style=" background:#F8F8F8; line-height:0; margin-top:40px; padding:50.0% 0; text-align:center; width:100%;">
77
- <div style=" background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAMAAAApWqozAAAAGFBMVEUiIiI9PT0eHh4gIB4hIBkcHBwcHBwcHBydr+JQAAAACHRSTlMABA4YHyQsM5jtaMwAAADfSURBVDjL7ZVBEgMhCAQBAf//42xcNbpAqakcM0ftUmFAAIBE81IqBJdS3lS6zs3bIpB9WED3YYXFPmHRfT8sgyrCP1x8uEUxLMzNWElFOYCV6mHWWwMzdPEKHlhLw7NWJqkHc4uIZphavDzA2JPzUDsBZziNae2S6owH8xPmX8G7zzgKEOPUoYHvGz1TBCxMkd3kwNVbU0gKHkx+iZILf77IofhrY1nYFnB/lQPb79drWOyJVa/DAvg9B/rLB4cC+Nqgdz/TvBbBnr6GBReqn/nRmDgaQEej7WhonozjF+Y2I/fZou/qAAAAAElFTkSuQmCC); display:block; height:44px; margin:0 auto -44px; position:relative; top:-22px; width:44px;"/>
78
- </div>
79
- <p style=" color:#c9c8cd; font-family:Arial,sans-serif; font-size:14px; line-height:17px; margin-bottom:0; margin-top:8px; overflow:hidden; padding:8px 0 7px; text-align:center; text-overflow:ellipsis; white-space:nowrap;"><a href="https://www.instagram.com/p/6l9z5RTbAN/" style=" color:#c9c8cd; font-family:Arial,sans-serif; font-size:14px; font-style:normal; font-weight:normal; line-height:17px; text-decoration:none;" target="_blank">A photo posted by Bjørn Johansen (@bjornjohansen)</a> on <time style=" font-family:Arial,sans-serif; font-size:14px; line-height:17px;" datetime="2015-08-20T05:19:53+00:00">Aug 19, 2015 at 10:19pm PDT</time></p>
80
- </div>
81
- </blockquote>
82
- <p><script async="" defer="defer" src="//platform.instagram.com/en_US/embeds.js"/></p>
83
- */
84
-
85
- /*
86
- Example output from twitter:
87
- <blockquote class="twitter-tweet" width="550"><p lang="en" dir="ltr">Will my Drupal site upgrade itself automatically to version 8, or do I click a button somewhere?</p>
88
- <p>— Bjørn Johansen (@bjornjohansen) <a href="https://twitter.com/bjornjohansen/status/667263124794417152">November 19, 2015</a></p>
89
- </blockquote>
90
- <p><script async="" src="//platform.twitter.com/widgets.js" charset="utf-8"/></p>
91
- */
92
-
93
- /*
94
- Example output from youtube:
95
- <iframe width="660" height="371" src="https://www.youtube.com/embed/SQjSJ0T7PiE?feature=oembed" frameborder="0" allowfullscreen></iframe>
96
- */
97
-
98
- /*
99
- Example output from vine:
100
- <iframe class="vine-embed" src="https://vine.co/v/e9U7gav5e5h/embed/simple" width="660" height="660" frameborder="0"/><script async="" src="//platform.vine.co/static/scripts/embed.js"/>
101
- */
102
 
103
  /**
104
- * Filter the HTML that will go into the Instant Article Social Embed markup
105
  *
106
  * @since 0.1
107
- * @param string $html The HTML
108
- * @param string $url The URL found in the content
109
- * @param mixed $attr An array with extra attributes
110
- * @param int $post_ID The post ID
111
  */
112
- $html = apply_filters( "instant_articles_social_embed_{$provider_name}", $html, $url, $attr, $post_ID);
113
 
114
- $html = sprintf( '<figure class="op-social"><iframe>%s</iframe></figure>', $html );
115
 
116
  /**
117
- * Filter the Instant Article Social Embed markup
118
  *
119
  * @since 0.1
120
- * @param string $html The Social Embed markup
121
- * @param string $url The URL found in the content
122
- * @param mixed $attr An array with extra attributes
123
- * @param int $post_ID The post ID
124
  */
125
- $html = apply_filters( 'instant_articles_social_embed', $html, $url, $attr, $post_ID );
126
 
127
  return $html;
128
  }
129
-
130
-
131
-
1
  <?php
 
2
  /**
3
+ * Facebook Instant Articles for WP.
4
+ * This source code is licensed under the license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
  *
7
+ * @package default
 
8
  */
9
 
 
10
  /**
11
  * Remove all extra oembed html filters added by themes and plugins.
 
12
  */
13
  remove_all_filters( 'embed_oembed_html' );
14
 
16
  * Filter the oembed results to see if we should do some extra handling
17
  *
18
  * @since 0.1
19
+ * @param string $html The original HTML returned from the external oembed provider.
20
+ * @param string $url The URL found in the content.
21
+ * @param mixed $attr An array with extra attributes.
22
+ * @param int $post_id The post ID.
23
+ * @return string The potentially filtered HTML.
24
  */
25
+ function instant_articles_embed_oembed_html( $html, $url, $attr, $post_id ) {
26
 
27
  if ( ! class_exists( 'WP_oEmbed' ) ) {
28
  include_once( ABSPATH . WPINC . '/class-oembed.php' );
29
  }
30
 
31
+ // Instead of checking all possible URL variants, use the provider list from WP_oEmbed.
32
+ $wp_oembed = new WP_oEmbed();
33
+ $provider_url = $wp_oembed->get_provider( $url );
34
 
35
  $provider_name = false;
36
+ if ( false !== strpos( $provider_url, 'instagram.com' ) ) {
37
  $provider_name = 'instagram';
38
+ } elseif ( false !== strpos( $provider_url, 'twitter.com' ) ) {
39
  $provider_name = 'twitter';
40
+ } elseif ( false !== strpos( $provider_url, 'youtube.com' ) ) {
41
  $provider_name = 'youtube';
42
+ } elseif ( false !== strpos( $provider_url, 'vine.co' ) ) {
43
  $provider_name = 'vine';
44
  }
45
 
46
  $provider_name = apply_filters( 'instant_articles_social_embed_type', $provider_name, $url );
47
 
48
  if ( $provider_name ) {
49
+ $html = instant_articles_embed_get_html( $provider_name, $html, $url, $attr, $post_id );
50
  }
51
 
52
  return $html;
56
 
57
 
58
  /**
59
+ * Filter the embed results for embeds.
60
  *
61
  * @since 0.1
62
+ * @param string $provider_name The name of the embed provider. E.g. “instagram” or “youtube”.
63
+ * @param string $html The original HTML returned from the external oembed/embed provider.
64
+ * @param string $url The URL found in the content.
65
+ * @param mixed $attr An array with extra attributes.
66
+ * @param int $post_id The post ID.
67
+ * @return string The filtered HTML.
68
  */
69
+ function instant_articles_embed_get_html( $provider_name, $html, $url, $attr, $post_id ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
 
71
  /**
72
+ * Filter the HTML that will go into the Instant Article Social Embed markup.
73
  *
74
  * @since 0.1
75
+ * @param string $html The HTML.
76
+ * @param string $url The URL found in the content.
77
+ * @param mixed $attr An array with extra attributes.
78
+ * @param int $post_id The post ID.
79
  */
80
+ $html = apply_filters( "instant_articles_social_embed_{$provider_name}", $html, $url, $attr, $post_id );
81
 
82
+ $html = sprintf( '<div class="embed">%s</div>', $html );
83
 
84
  /**
85
+ * Filter the Instant Article Social Embed markup.
86
  *
87
  * @since 0.1
88
+ * @param string $html The Social Embed markup.
89
+ * @param string $url The URL found in the content.
90
+ * @param mixed $attr An array with extra attributes.
91
+ * @param int $post_id The post ID.
92
  */
93
+ $html = apply_filters( 'instant_articles_social_embed', $html, $url, $attr, $post_id );
94
 
95
  return $html;
96
  }
 
 
 
facebook-instant-articles.php CHANGED
@@ -2,186 +2,309 @@
2
  /**
3
  * Plugin Name: Instant Articles for WP
4
  * Description: Add support for Instant Articles for Facebook to your WordPress site.
5
- * Author: Automattic, Dekode
6
  * Author URI: https://vip.wordpress.com/plugins/instant-articles/
7
- * Version: 0.2
8
  * Text Domain: instant-articles
9
  * License: GPLv2
10
  * License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
- */
12
-
13
- defined( 'ABSPATH' ) || die('Shame on you');
14
-
15
-
16
- // Let users define their own feed slug
17
- if ( ! defined( 'INSTANT_ARTICLES_SLUG' ) ) {
18
- define( 'INSTANT_ARTICLES_SLUG', 'instant-articles' );
19
- }
20
-
21
- require_once( dirname( __FILE__ ) . '/dom-transform-filters/class-instant-articles-dom-transform-filter.php' );
22
- require_once( dirname( __FILE__ ) . '/class-instant-articles-dom-transform-filter-runner.php' );
23
- require_once( dirname( __FILE__ ) . '/class-instant-articles-post.php' );
24
-
25
- /**
26
- * Plugin activation hook to add our rewrite rules
27
- *
28
- * @since 0.1
29
- */
30
- function instant_articles_activate(){
31
- instant_articles_init();
32
- flush_rewrite_rules();
33
- }
34
- register_activation_hook( __FILE__, 'instant_articles_activate' );
35
-
36
- /**
37
- * Plugin activation hook to remove our rewrite rules
38
  *
39
- * @since 0.1
40
  */
41
- function instant_articles_deactivate(){
42
- flush_rewrite_rules();
43
- }
44
- register_deactivation_hook( __FILE__, 'instant_articles_deactivate' );
45
 
46
- /**
47
- * Load plugin textdomain
48
- *
49
- * @since 0.1
50
- */
51
- function instant_articles_load_textdomain() {
52
- load_plugin_textdomain( 'instant-articles', false, plugin_dir_path( __FILE__ ) . '/languages' );
53
- }
54
- add_action( 'plugins_loaded', 'instant_articles_load_textdomain' );
55
-
56
- /**
57
- * Register our special feed
58
- *
59
- * @since 0.1
60
- */
61
- function instant_articles_init() {
62
- add_feed( INSTANT_ARTICLES_SLUG, 'instant_articles_feed' );
63
- }
64
- add_action( 'init', 'instant_articles_init' );
65
-
66
- /**
67
- * Feed display callback
68
- *
69
- * @since 0.1
70
- */
71
- function instant_articles_feed() {
72
-
73
- // Load compat layers
74
- include( dirname( __FILE__ ) . '/compat.php' );
75
-
76
- // Load shortcode handlers
77
- include( dirname( __FILE__ ) . '/shortcodes.php' );
78
-
79
- // Load embedded content handlers
80
- include( dirname( __FILE__ ) . '/embeds.php' );
81
-
82
- // Load the feed template
83
- include( dirname( __FILE__ ) . '/feed-template.php' );
84
-
85
- }
 
 
 
 
 
 
 
 
 
 
 
86
 
87
- /**
88
- * Register included DOM transformation filters
89
- *
90
- * @since 0.1
91
- */
92
- function instant_articles_register_transformation_filters() {
93
 
94
- include( dirname( __FILE__ ) . '/dom-transform-filters/class-instant-articles-dom-transform-filter-video.php' );
95
- Instant_Articles_DOM_Transform_Filter_Runner::register( 'Instant_Articles_DOM_Transform_Filter_Video' );
96
 
97
- include( dirname( __FILE__ ) . '/dom-transform-filters/class-instant-articles-dom-transform-filter-image.php' );
98
- Instant_Articles_DOM_Transform_Filter_Runner::register( 'Instant_Articles_DOM_Transform_Filter_Image' );
 
 
99
 
100
- include( dirname( __FILE__ ) . '/dom-transform-filters/class-instant-articles-dom-transform-filter-blockquote.php' );
101
- Instant_Articles_DOM_Transform_Filter_Runner::register( 'Instant_Articles_DOM_Transform_Filter_Blockquote' );
 
 
102
 
103
- include( dirname( __FILE__ ) . '/dom-transform-filters/class-instant-articles-dom-transform-filter-unordered-list.php' );
104
- Instant_Articles_DOM_Transform_Filter_Runner::register( 'Instant_Articles_DOM_Transform_Filter_Unordered_List' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
 
106
- include( dirname( __FILE__ ) . '/dom-transform-filters/class-instant-articles-dom-transform-filter-ordered-list.php' );
107
- Instant_Articles_DOM_Transform_Filter_Runner::register( 'Instant_Articles_DOM_Transform_Filter_Ordered_List' );
108
 
109
- include( dirname( __FILE__ ) . '/dom-transform-filters/class-instant-articles-dom-transform-filter-table.php' );
110
- Instant_Articles_DOM_Transform_Filter_Runner::register( 'Instant_Articles_DOM_Transform_Filter_Table' );
 
 
 
 
111
 
112
- include( dirname( __FILE__ ) . '/dom-transform-filters/class-instant-articles-dom-transform-filter-address.php' );
113
- Instant_Articles_DOM_Transform_Filter_Runner::register( 'Instant_Articles_DOM_Transform_Filter_Address' );
114
 
115
- //Instant articles only support h1 and h2. Convert h3-h6 to h2.
116
- include( dirname( __FILE__ ) . '/dom-transform-filters/class-instant-articles-dom-transform-filter-heading.php' );
117
- Instant_Articles_DOM_Transform_Filter_Runner::register( 'Instant_Articles_DOM_Transform_Filter_Heading' );
118
 
119
- // Remove empty elements
120
- include( dirname( __FILE__ ) . '/dom-transform-filters/class-instant-articles-dom-transform-filter-emptyelements.php' );
121
- Instant_Articles_DOM_Transform_Filter_Runner::register( 'Instant_Articles_DOM_Transform_Filter_Emptyelements', 90 );
122
- }
123
- add_action( 'instant_articles_register_dom_transformation_filters', 'instant_articles_register_transformation_filters' );
124
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
 
126
- /**
127
- * Modify the main query for our feed.
128
- *
129
- * We want the posts in the modified order, to provide Facebook with content updates even for older posts.
130
- * Facebook will only import 100 posts at the time.
131
- * Facebook will only update posts modified within the last 24 hours
132
- *
133
- * @param WP_Query $query The WP_Query object. Passed by reference.
134
- */
135
- function instant_articles_query( $query ) {
136
 
137
- if ( $query->is_main_query() && $query->is_feed( INSTANT_ARTICLES_SLUG ) ) {
138
 
139
- $query->set( 'orderby', 'modified' );
140
- $query->set( 'posts_per_page', 100 );
141
- $query->set( 'posts_per_rss', 100 );
 
 
 
 
 
 
142
 
143
- /**
144
- * If the constant INSTANT_ARTICLES_LIMIT_POSTS is set to true, we will limit the feed
145
- * to only include posts which are modified within the last 24 hours.
146
- * Facebook will initially need 100 posts to pass the review, but will only update
147
- * already imported articles if they are modified within the last 24 hours.
148
- */
149
  if ( defined( 'INSTANT_ARTICLES_LIMIT_POSTS' ) && INSTANT_ARTICLES_LIMIT_POSTS ) {
150
- $query->set( 'date_query', array(
151
- array(
152
- 'column' => 'post_modified',
153
- 'after' => '1 day ago',
154
- ),
155
- ) );
156
  }
157
- }
158
-
159
- }
160
- add_action( 'pre_get_posts', 'instant_articles_query', 10, 1 );
161
-
162
-
163
- /**
164
- * Filter the SQL query to not include posts with empty content -- FB will complain
165
- *
166
- * @since 0.1
167
- * @param string $where The original where part of the SQL statement
168
- * @param WP_Query $query The WP_Query instance
169
- * @return string The modified where part of the SQL statement
170
- */
171
- function instant_articles_query_where( $where, $query ) {
172
 
173
- // Don’t modify the SQL query with a potentially expensive WHERE clause if we’re OK with fewer posts than 100 and are OK with filtering in the loop
174
- if ( defined( 'INSTANT_ARTICLES_LIMIT_POSTS' ) && INSTANT_ARTICLES_LIMIT_POSTS ) {
 
 
175
  return $where;
176
- }
177
 
178
- if ( $query->is_main_query() && $query->is_feed( INSTANT_ARTICLES_SLUG ) ) {
179
- global $wpdb;
180
- $where .= " AND {$wpdb->posts}.post_content NOT LIKE ''";
181
  }
182
- return $where;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
 
184
- }
185
- add_filter( 'posts_where' , 'instant_articles_query_where', 10, 2 );
186
 
 
 
187
 
 
 
 
2
  /**
3
  * Plugin Name: Instant Articles for WP
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.1
8
  * Text Domain: instant-articles
9
  * License: GPLv2
10
  * License URI: http://www.gnu.org/licenses/gpl-2.0.html
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  *
12
+ * @package default
13
  */
 
 
 
 
14
 
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.5 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 {
31
+
32
+ $autoloader = require __DIR__ . '/vendor/autoload.php';
33
+ $autoloader->add( 'Facebook\\', __DIR__ . '/vendor/facebook/facebook-instant-articles-sdk-php/src' );
34
+
35
+ // Configures log to go through console.
36
+ \Logger::configure(
37
+ array(
38
+ 'rootLogger' => array(
39
+ 'appenders' => array( 'facebook-instantarticles-transformer' ),
40
+ ),
41
+ 'appenders' => array(
42
+ 'facebook-instantarticles-transformer' => array(
43
+ 'class' => 'LoggerAppenderConsole',
44
+ 'threshold' => 'INFO',
45
+ 'layout' => array(
46
+ 'class' => 'LoggerLayoutSimple',
47
+ ),
48
+ ),
49
+ 'facebook-instantarticles-client' => array(
50
+ 'class' => 'LoggerAppenderConsole',
51
+ 'threshold' => 'INFO',
52
+ 'layout' => array(
53
+ 'class' => 'LoggerLayoutSimple',
54
+ ),
55
+ ),
56
+ 'instantarticles-wp-plugin' => array(
57
+ 'class' => 'LoggerAppenderConsole',
58
+ 'threshold' => 'INFO',
59
+ 'layout' => array(
60
+ 'class' => 'LoggerLayoutSimple',
61
+ ),
62
+ ),
63
+ ),
64
+ )
65
+ );
66
 
 
 
 
 
 
 
67
 
68
+ defined( 'ABSPATH' ) || die( 'Shame on you' );
 
69
 
70
+ define( 'IA_PLUGIN_PATH_FULL', __FILE__ );
71
+ define( 'IA_PLUGIN_PATH', plugin_basename( __FILE__ ) );
72
+ define( 'IA_PLUGIN_FILE_BASENAME', pathinfo( __FILE__, PATHINFO_FILENAME ) );
73
+ define( 'IA_PLUGIN_TEXT_DOMAIN', 'instant-articles' );
74
 
75
+ // Let users define their own feed slug.
76
+ if ( ! defined( 'INSTANT_ARTICLES_SLUG' ) ) {
77
+ define( 'INSTANT_ARTICLES_SLUG', 'instant-articles' );
78
+ }
79
 
80
+ require_once( dirname( __FILE__ ) . '/embeds.php' );
81
+ require_once( dirname( __FILE__ ) . '/class-instant-articles-post.php' );
82
+ require_once( dirname( __FILE__ ) . '/settings/class-instant-articles-settings.php' );
83
+ require_once( dirname( __FILE__ ) . '/meta-box/class-instant-articles-meta-box.php' );
84
+ require_once( dirname( __FILE__ ) . '/class-instant-articles-publisher.php' );
85
+
86
+ /**
87
+ * Plugin activation hook to add our rewrite rules.
88
+ *
89
+ * @since 0.1
90
+ */
91
+ function instant_articles_activate() {
92
+ instant_articles_init();
93
+ flush_rewrite_rules();
94
+ }
95
+ register_activation_hook( __FILE__, 'instant_articles_activate' );
96
+
97
+ /**
98
+ * Plugin activation hook to remove our rewrite rules.
99
+ *
100
+ * @since 0.1
101
+ */
102
+ function instant_articles_deactivate() {
103
+ flush_rewrite_rules();
104
+ }
105
+ register_deactivation_hook( __FILE__, 'instant_articles_deactivate' );
106
+
107
+ /**
108
+ * Load plugin textdomain.
109
+ *
110
+ * @since 0.1
111
+ */
112
+ function instant_articles_load_textdomain() {
113
+ load_plugin_textdomain( 'instant-articles', false, plugin_dir_path( __FILE__ ) . '/languages' );
114
+ }
115
+ add_action( 'plugins_loaded', 'instant_articles_load_textdomain' );
116
+
117
+ /**
118
+ * Plugin hook to load compat layers.
119
+ *
120
+ * @since 2.0
121
+ */
122
+ function instant_articles_load_compat() {
123
+ require_once( dirname( __FILE__ ) . '/compat.php' );
124
+ }
125
+ add_action( 'plugins_loaded', 'instant_articles_load_compat' );
126
+
127
+ /**
128
+ * Register our special feed.
129
+ *
130
+ * @since 0.1
131
+ */
132
+ function instant_articles_init() {
133
+ add_feed( INSTANT_ARTICLES_SLUG, 'instant_articles_feed' );
134
+ }
135
+ add_action( 'init', 'instant_articles_init' );
136
 
 
 
137
 
138
+ /**
139
+ * Feed display callback.
140
+ *
141
+ * @since 0.1
142
+ */
143
+ function instant_articles_feed() {
144
 
145
+ // Load the feed template.
146
+ include( dirname( __FILE__ ) . '/feed-template.php' );
147
 
148
+ }
 
 
149
 
 
 
 
 
 
150
 
151
+ /**
152
+ * Modify the main query for our feed.
153
+ *
154
+ * We want the posts in the modified order, to provide Facebook with content updates even for older posts.
155
+ * Facebook will only import 100 posts at the time.
156
+ * Facebook will only update posts modified within the last 24 hours
157
+ *
158
+ * @param WP_Query $query The WP_Query object. Passed by reference.
159
+ */
160
+ function instant_articles_query( $query ) {
161
+
162
+ if ( $query->is_main_query() && $query->is_feed( INSTANT_ARTICLES_SLUG ) ) {
163
+
164
+ $query->set( 'orderby', 'modified' );
165
+ $query->set( 'posts_per_page', 100 );
166
+ $query->set( 'posts_per_rss', 100 );
167
+
168
+ /**
169
+ * If the constant INSTANT_ARTICLES_LIMIT_POSTS is set to true, we will limit the feed
170
+ * to only include posts which are modified within the last 24 hours.
171
+ * Facebook will initially need 100 posts to pass the review, but will only update
172
+ * already imported articles if they are modified within the last 24 hours.
173
+ */
174
+ if ( defined( 'INSTANT_ARTICLES_LIMIT_POSTS' ) && INSTANT_ARTICLES_LIMIT_POSTS ) {
175
+ $query->set( 'date_query', array(
176
+ array(
177
+ 'column' => 'post_modified',
178
+ 'after' => '1 day ago',
179
+ ),
180
+ ) );
181
+ }
182
+ }
183
 
184
+ }
185
+ add_action( 'pre_get_posts', 'instant_articles_query', 10, 1 );
 
 
 
 
 
 
 
 
186
 
 
187
 
188
+ /**
189
+ * Filter the SQL query to not include posts with empty content -- FB will complain.
190
+ *
191
+ * @since 0.1
192
+ * @param string $where The original where part of the SQL statement.
193
+ * @param WP_Query $query The WP_Query instance.
194
+ * @return string The modified where part of the SQL statement.
195
+ */
196
+ function instant_articles_query_where( $where, $query ) {
197
 
198
+ // Don’t modify the SQL query with a potentially expensive WHERE clause if we’re OK with fewer posts than 100 and are OK with filtering in the loop.
 
 
 
 
 
199
  if ( defined( 'INSTANT_ARTICLES_LIMIT_POSTS' ) && INSTANT_ARTICLES_LIMIT_POSTS ) {
200
+ return $where;
 
 
 
 
 
201
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
202
 
203
+ if ( $query->is_main_query() && $query->is_feed( INSTANT_ARTICLES_SLUG ) ) {
204
+ global $wpdb;
205
+ $where .= " AND {$wpdb->posts}.post_content NOT LIKE ''";
206
+ }
207
  return $where;
 
208
 
 
 
 
209
  }
210
+ add_filter( 'posts_where' , 'instant_articles_query_where', 10, 2 );
211
+
212
+ /**
213
+ * Register all scripts and styles for the admin UI.
214
+ *
215
+ * @since 0.4
216
+ */
217
+ function instant_articles_register_scripts() {
218
+ wp_register_style(
219
+ 'instant-articles-meta-box',
220
+ plugins_url( '/css/instant-articles-meta-box.css', __FILE__ )
221
+ );
222
+ wp_register_style(
223
+ 'instant-articles-settings-wizard',
224
+ plugins_url( '/css/instant-articles-settings-wizard.css', __FILE__ )
225
+ );
226
+ wp_register_style(
227
+ 'instant-articles-settings',
228
+ plugins_url( '/css/instant-articles-settings.css', __FILE__ )
229
+ );
230
+
231
+ wp_register_script(
232
+ 'instant-articles-meta-box',
233
+ plugins_url( '/js/instant-articles-meta-box.js', __FILE__ )
234
+ );
235
+ wp_register_script(
236
+ 'instant-articles-option-ads',
237
+ plugins_url( '/js/instant-articles-option-ads.js', __FILE__ ),
238
+ null,
239
+ null,
240
+ true
241
+ );
242
+ wp_register_script(
243
+ 'instant-articles-option-analytics',
244
+ plugins_url( '/js/instant-articles-option-analytics.js', __FILE__ ),
245
+ null,
246
+ null,
247
+ true
248
+ );
249
+ wp_register_script(
250
+ 'instant-articles-option-publishing',
251
+ plugins_url( '/js/instant-articles-option-publishing.js', __FILE__ ),
252
+ null,
253
+ null,
254
+ true
255
+ );
256
+ wp_register_script(
257
+ 'instant-articles-settings',
258
+ plugins_url( '/js/instant-articles-settings.js', __FILE__ ),
259
+ null,
260
+ null,
261
+ true
262
+ );
263
+ }
264
+ add_action( 'init', 'instant_articles_register_scripts' );
265
+
266
+ /**
267
+ * Enqueue all scripts and styles for the admin UI.
268
+ *
269
+ * @since 0.4
270
+ */
271
+ function instant_articles_enqueue_scripts() {
272
+ wp_enqueue_style( 'instant-articles-meta-box' );
273
+ wp_enqueue_style( 'instant-articles-settings-wizard' );
274
+ wp_enqueue_style( 'instant-articles-settings' );
275
+
276
+ wp_enqueue_script( 'instant-articles-meta-box' );
277
+ wp_enqueue_script( 'instant-articles-option-ads' );
278
+ wp_enqueue_script( 'instant-articles-option-analytics' );
279
+ wp_enqueue_script( 'instant-articles-option-publishing' );
280
+ wp_enqueue_script( 'instant-articles-settings' );
281
+ }
282
+ add_action( 'admin_enqueue_scripts', 'instant_articles_enqueue_scripts' );
283
+
284
+ /**
285
+ * Automatically add meta tag for Instant Articles URL claiming
286
+ * when page is set.
287
+ *
288
+ * @since 0.4
289
+ */
290
+ function inject_url_claiming_meta_tag() {
291
+ $publishing_settings = Instant_Articles_Option_Publishing::get_option_decoded();
292
+ $fb_page_settings = Instant_Articles_Option_FB_Page::get_option_decoded();
293
+
294
+ if ( isset( $fb_page_settings['page_id'] ) ) {
295
+ ?>
296
+ <meta property="fb:pages" content="<?php echo absint( $fb_page_settings['page_id'] ); ?>" />
297
+ <?php
298
+ }
299
+ }
300
+ add_action( 'wp_head', 'inject_url_claiming_meta_tag' );
301
 
302
+ // Initialize the Instant Articles settings page.
303
+ Instant_Articles_Settings::init();
304
 
305
+ // Initialize the Instant Articles meta box.
306
+ Instant_Articles_Meta_Box::init();
307
 
308
+ // Initialize the Instant Articles publisher.
309
+ Instant_Articles_Publisher::init();
310
+ }
feed-template.php CHANGED
@@ -1,4 +1,12 @@
1
  <?php
 
 
 
 
 
 
 
 
2
  header( 'Content-Type: ' . feed_content_type( 'rss2' ) . '; charset=' . get_option( 'blog_charset' ), true );
3
  echo '<?xml version="1.0" encoding="' . esc_attr( get_option( 'blog_charset' ) ) . '"?' . '>';
4
 
@@ -7,28 +15,30 @@ $last_modified = null;
7
  <rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
8
  <channel>
9
  <title><?php bloginfo_rss( 'name' ); ?> - <?php esc_html_e( 'Instant Articles', 'instant-articles' ); ?></title>
10
- <link><?php bloginfo_rss('url') ?></link>
11
  <description><?php bloginfo_rss( 'description' ) ?></description>
12
  <?php while ( have_posts() ) : the_post(); ?>
13
  <?php
14
- $instant_article_post = new Instant_Articles_Post( get_the_ID() );
15
-
16
  // If we’re OK with a limited post set: Do not include posts with empty content -- FB will complain.
17
  if ( defined( 'INSTANT_ARTICLES_LIMIT_POSTS' ) && INSTANT_ARTICLES_LIMIT_POSTS && ! strlen( trim( $instant_article_post->get_the_content() ) ) ) {
18
  continue;
19
  }
20
 
21
- // Posts are sorted by modification time, so our first accepted post should be the one last modified
22
  if ( is_null( $last_modified ) ) {
23
  $last_modified = $instant_article_post->get_the_moddate_iso();
24
  }
25
  ?>
26
  <item>
27
- <title><?php echo esc_html( $instant_article_post->get_the_title_rss() ); ?></title>
28
  <link><?php echo esc_url( $instant_article_post->get_canonical_url() ); ?></link>
29
- <content:encoded><![CDATA[<?php $instant_article_post->render(); ?>]]></content:encoded>
 
 
30
  <guid isPermaLink="false"><?php esc_html( the_guid() ); ?></guid>
31
- <description><![CDATA[<?php echo esc_html( $instant_article_post->get_the_excerpt_rss() ); ?>]]></description>
32
  <pubDate><?php echo esc_html( $instant_article_post->get_the_pubdate_iso() ); ?></pubDate>
33
  <modDate><?php echo esc_html( $instant_article_post->get_the_moddate_iso() ); ?></modDate>
34
  <?php $authors = $instant_article_post->get_the_authors(); ?>
1
  <?php
2
+ /**
3
+ * Facebook Instant Articles for WP.
4
+ * This source code is licensed under the license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @package default
8
+ */
9
+
10
  header( 'Content-Type: ' . feed_content_type( 'rss2' ) . '; charset=' . get_option( 'blog_charset' ), true );
11
  echo '<?xml version="1.0" encoding="' . esc_attr( get_option( 'blog_charset' ) ) . '"?' . '>';
12
 
15
  <rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
16
  <channel>
17
  <title><?php bloginfo_rss( 'name' ); ?> - <?php esc_html_e( 'Instant Articles', 'instant-articles' ); ?></title>
18
+ <link><?php bloginfo_rss( 'url' ) ?></link>
19
  <description><?php bloginfo_rss( 'description' ) ?></description>
20
  <?php while ( have_posts() ) : the_post(); ?>
21
  <?php
22
+ $instant_article_post = new Instant_Articles_Post( get_post( get_the_id() ) );
23
+
24
  // If we’re OK with a limited post set: Do not include posts with empty content -- FB will complain.
25
  if ( defined( 'INSTANT_ARTICLES_LIMIT_POSTS' ) && INSTANT_ARTICLES_LIMIT_POSTS && ! strlen( trim( $instant_article_post->get_the_content() ) ) ) {
26
  continue;
27
  }
28
 
29
+ // Posts are sorted by modification time, so our first accepted post should be the one last modified.
30
  if ( is_null( $last_modified ) ) {
31
  $last_modified = $instant_article_post->get_the_moddate_iso();
32
  }
33
  ?>
34
  <item>
35
+ <title><?php echo esc_html( $instant_article_post->get_the_title() ); ?></title>
36
  <link><?php echo esc_url( $instant_article_post->get_canonical_url() ); ?></link>
37
+ <content:encoded>
38
+ <![CDATA[<?php echo $instant_article_post->to_instant_article()->render(); ?>]]>
39
+ </content:encoded>
40
  <guid isPermaLink="false"><?php esc_html( the_guid() ); ?></guid>
41
+ <description><![CDATA[<?php echo esc_html( $instant_article_post->get_the_excerpt() ); ?>]]></description>
42
  <pubDate><?php echo esc_html( $instant_article_post->get_the_pubdate_iso() ); ?></pubDate>
43
  <modDate><?php echo esc_html( $instant_article_post->get_the_moddate_iso() ); ?></modDate>
44
  <?php $authors = $instant_article_post->get_the_authors(); ?>
js/instant-articles-meta-box.js ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function instant_articles_load_meta_box ( post_ID ) {
2
+ jQuery( document ).ready( function( $ ) {
3
+ var data = {
4
+ 'action': 'instant_articles_meta_box',
5
+ 'post_ID': post_ID
6
+ };
7
+ jQuery.post( ajaxurl, data, function(response) {
8
+ jQuery( '#instant_article_meta_box .inside' ).html( response );
9
+ }, 'html' );
10
+ jQuery( '#instant_article_meta_box' ).delegate( '.instant-articles-toggle-debug', 'click', function () {
11
+ jQuery( '#instant_article_meta_box' ).toggleClass( 'instant-articles-show-debug' );
12
+ return false;
13
+ } );
14
+ });
15
+ }
js/instant-articles-option-ads.js ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery( function () {
2
+ var idAdSource = '#' + INSTANT_ARTICLES_OPTION_ADS['option_field_id_source'];
3
+ var idFanPlacementId = '#' + INSTANT_ARTICLES_OPTION_ADS['option_field_id_fan'];
4
+ var idIframeUrl = '#' + INSTANT_ARTICLES_OPTION_ADS['option_field_id_iframe'];
5
+ var idEmbedCode = '#' + INSTANT_ARTICLES_OPTION_ADS['option_field_id_embed'];
6
+ var idDimensions = '#' + INSTANT_ARTICLES_OPTION_ADS['option_field_id_dimensions'];
7
+ var $rowFanPlacementId = jQuery( idFanPlacementId ).parents( 'tr' );
8
+ var $rowIframeUrl = jQuery( idIframeUrl ) .parents( 'tr' );
9
+ var $rowEmbedCode = jQuery( idEmbedCode ) .parents( 'tr' );
10
+ var $rowDimensions = jQuery( idDimensions ) .parents( 'tr' );
11
+ jQuery( idAdSource ).change( function () {
12
+ switch (jQuery( this ).val()) {
13
+ case 'fan':
14
+ $rowFanPlacementId.show();
15
+ $rowIframeUrl .hide();
16
+ $rowEmbedCode .hide();
17
+ $rowDimensions .show();
18
+ break;
19
+
20
+ case 'iframe':
21
+ $rowFanPlacementId.hide();
22
+ $rowIframeUrl .show();
23
+ $rowEmbedCode .hide();
24
+ $rowDimensions .show();
25
+ break;
26
+
27
+ case 'embed':
28
+ $rowFanPlacementId.hide();
29
+ $rowIframeUrl .hide();
30
+ $rowEmbedCode .show();
31
+ $rowDimensions .show();
32
+ break;
33
+
34
+ default:
35
+ $rowFanPlacementId.hide();
36
+ $rowIframeUrl .hide();
37
+ $rowEmbedCode .hide();
38
+ $rowDimensions .hide();
39
+ break;
40
+ }
41
+ } ).trigger( 'change' );
42
+ } );
js/instant-articles-option-analytics.js ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery( function () {
2
+ var idEmbedCodeEnabled = '#' + INSTANT_ARTICLES_OPTION_ANALYTICS['option_field_id_embed_code_enabled'];
3
+ var idEmbedCode = '#' + INSTANT_ARTICLES_OPTION_ANALYTICS['option_field_id_embed_code'];
4
+ var $rowEmbedCode = jQuery( idEmbedCode ).parents( 'tr' );
5
+ var $embedCodeEnabled = jQuery( idEmbedCodeEnabled );
6
+ $embedCodeEnabled.change( function () {
7
+ if ( $embedCodeEnabled.is( ':checked' ) ) {
8
+
9
+ $rowEmbedCode.show();
10
+
11
+ } else {
12
+
13
+ $rowEmbedCode.hide();
14
+
15
+ }
16
+ } ).trigger( 'change' );
17
+ } );
js/instant-articles-option-publishing.js ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery( function () {
2
+ var idCustomRulesEnabled = '#' + INSTANT_ARTICLES_OPTION_PUBLISHING['option_field_id_custom_rules_enabled'];
3
+ var idCustomRules = '#' + INSTANT_ARTICLES_OPTION_PUBLISHING['option_field_id_custom_rules'];
4
+ var $rowCustomRules = jQuery( idCustomRules ).parents( 'tr' );
5
+ var $customRulesEnabled = jQuery( idCustomRulesEnabled );
6
+ $customRulesEnabled.change( function () {
7
+ if ( $customRulesEnabled.is( ':checked' ) ) {
8
+
9
+ $rowCustomRules.show();
10
+
11
+ } else {
12
+
13
+ $rowCustomRules.hide();
14
+
15
+ }
16
+ } ).trigger( 'change' );
17
+ } );
js/instant-articles-settings.js ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery( function () {
2
+ jQuery( '#instant-articles-fb-page-selector' ).change(function () {
3
+ var val = jQuery( this ).val();
4
+ var obj = jQuery.parseJSON( val );
5
+
6
+ if ( val ) {
7
+ jQuery( 'input[name=instant-articles-select-page]' ).attr( 'disabled', false );
8
+ jQuery.each( obj, function ( key, value ) {
9
+ jQuery( 'input[name="instant-articles-option-fb-page[' + key + ']"]' )
10
+ .val( value );
11
+ });
12
+ }
13
+ else {
14
+ jQuery( 'input[name=instant-articles-select-page]' ).attr( 'disabled', true );
15
+ }
16
+ } ).trigger( 'change' );
17
+
18
+
19
+ jQuery( '.instant-articles-settings-box > h2' ).click(function () {
20
+ $h2 = jQuery( this );
21
+ $h2.siblings('.inside').toggle();
22
+ $h2.toggleClass('dashicons-arrow-down');
23
+ $h2.toggleClass('dashicons-arrow-right');
24
+ })
25
+ } );
meta-box/class-instant-articles-meta-box.php ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Facebook Instant Articles for WP.
4
+ * This source code is licensed under the license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @package default
8
+ */
9
+
10
+ use Facebook\InstantArticles\Client\Client;
11
+ use Facebook\InstantArticles\Client\InstantArticleStatus;
12
+ use Facebook\InstantArticles\Client\ServerMessage;
13
+ use Facebook\Exceptions\FacebookResponseException;
14
+
15
+ /**
16
+ * Class responsible for drawing the meta box on the post edit page
17
+ *
18
+ * @since 0.1
19
+ */
20
+ class Instant_Articles_Meta_Box {
21
+
22
+ /**
23
+ * Initiator for Metabox.
24
+ */
25
+ public static function init() {
26
+ add_action( 'add_meta_boxes', array( 'Instant_Articles_Meta_Box', 'register_meta_box' ) );
27
+ add_action(
28
+ 'wp_ajax_instant_articles_meta_box',
29
+ array( 'Instant_Articles_Meta_Box', 'render_meta_box' )
30
+ );
31
+ }
32
+
33
+ /**
34
+ * Register Meta Box renderer.
35
+ */
36
+ public static function register_meta_box() {
37
+ add_meta_box(
38
+ 'instant_article_meta_box',
39
+ 'Facebook Instant Articles',
40
+ array( 'Instant_Articles_Meta_Box', 'render_meta_box_loader' ),
41
+ 'post',
42
+ 'normal',
43
+ 'default'
44
+ );
45
+ }
46
+
47
+ /**
48
+ * Includes the template for Metabox.
49
+ *
50
+ * @param Post $post the post request content.
51
+ */
52
+ public static function render_meta_box_loader( $post ) {
53
+ include( dirname( __FILE__ ) . '/meta-box-loader-template.php' );
54
+ }
55
+
56
+ /**
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();
64
+ $submission_status = null;
65
+
66
+ Instant_Articles_Settings::menu_items();
67
+ $settings_page_href = Instant_Articles_Settings::get_href_to_settings_page();
68
+
69
+ try {
70
+ $fb_app_settings = Instant_Articles_Option_FB_App::get_option_decoded();
71
+ $fb_page_settings = Instant_Articles_Option_FB_Page::get_option_decoded();
72
+
73
+ if ( isset( $fb_app_settings['app_id'] )
74
+ && isset( $fb_app_settings['app_secret'] )
75
+ && isset( $fb_page_settings['page_access_token'] )
76
+ && isset( $fb_page_settings['page_id'] ) ) {
77
+ // Instantiate a new Client to get the status of this article.
78
+ $client = Client::create(
79
+ $fb_app_settings['app_id'],
80
+ $fb_app_settings['app_secret'],
81
+ $fb_page_settings['page_access_token'],
82
+ $fb_page_settings['page_id']
83
+ );
84
+
85
+ // Grab the latest status of this article and display.
86
+ $article_id = $client->getArticleIDFromCanonicalURL( $canonical_url );
87
+ $submission_status = $client->getLastSubmissionStatus( $article_id );
88
+ }
89
+ } catch ( FacebookResponseException $e ) {
90
+ $submission_status = null;
91
+ }
92
+
93
+ include( dirname( __FILE__ ) . '/meta-box-template.php' );
94
+
95
+ die();
96
+ }
97
+ }
meta-box/meta-box-loader-template.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Facebook Instant Articles for WP.
4
+ * This source code is licensed under the license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @package default
8
+ */
9
+
10
+ ?>
11
+ <span class="instant_articles_spinner" ></span>
12
+
13
+ <script>
14
+ instant_articles_load_meta_box( <?php echo absint( $post->ID ); ?> );
15
+ </script>
meta-box/meta-box-template.php ADDED
@@ -0,0 +1,178 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Facebook Instant Articles for WP.
4
+ * This source code is licensed under the license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @package default
8
+ */
9
+
10
+ use Facebook\InstantArticles\Client\InstantArticleStatus;
11
+ use Facebook\InstantArticles\Client\ServerMessage;
12
+ ?>
13
+
14
+ <!-- Submission status -->
15
+ <?php if ( $submission_status ) : ?>
16
+
17
+ <!-- Display the last submission status -->
18
+ <?php switch ( $submission_status->getStatus() ) :
19
+ case InstantArticleStatus::SUCCESS : ?>
20
+ <p>
21
+ <b>
22
+ <span class="dashicons dashicons-yes"></span>
23
+ Your article was submitted to Instant Articles successfully
24
+ </b>
25
+ </p>
26
+ <?php break; ?>
27
+
28
+ <?php case InstantArticleStatus::FAILED : ?>
29
+ <p>
30
+ <b>
31
+ <span class="dashicons dashicons-no-alt"></span>
32
+ It wasn't possible to submit your article
33
+ </b>
34
+ </p>
35
+ <?php break; ?>
36
+
37
+ <?php case InstantArticleStatus::IN_PROGRESS : ?>
38
+ <p>
39
+ <b>
40
+ <span class="dashicons dashicons-update"></span>
41
+ Your article is being submitted...
42
+ </b>
43
+ </p>
44
+ <script>
45
+ setTimeout(function () {
46
+ instant_articles_load_meta_box( <?php echo absint( $post->ID ); ?> );
47
+ }, 2000);
48
+ </script>
49
+
50
+ <?php break; ?>
51
+
52
+ <?php default : ?>
53
+ <p>
54
+ <b>
55
+ <span class="dashicons dashicons-no-alt"></span>
56
+ This post was not yet submitted to Instant Articles.
57
+ </b>
58
+ </p>
59
+ <?php break; ?>
60
+
61
+ <?php endswitch; ?>
62
+
63
+
64
+ <!-- Display the submission messages if any -->
65
+ <?php if ( count( $submission_status->getMessages() ) > 0 ) : ?>
66
+
67
+ <p>The server responded with the following messages:</p>
68
+
69
+ <ul class="instant-articles-messages">
70
+
71
+ <?php foreach ( $submission_status->getMessages() as $message ) : ?>
72
+
73
+ <?php switch ( $message->getLevel() ) :
74
+ case ServerMessage::WARNING : ?>
75
+ <li class="wp-ui-text-highlight">
76
+ <span class="dashicons dashicons-warning"></span>
77
+ <div>
78
+ <?php echo esc_html( $message->getMessage() ); ?>
79
+ </div>
80
+ </li>
81
+ <?php break; ?>
82
+
83
+ <?php case ServerMessage::ERROR : ?>
84
+ <li class="wp-ui-text-notification">
85
+ <span class="dashicons dashicons-dismiss"></span>
86
+ <div>
87
+ <?php echo esc_html( $message->getMessage() ); ?>
88
+ </div>
89
+ </li>
90
+ <?php break; ?>
91
+
92
+ <?php case ServerMessage::FATAL : ?>
93
+ <li class="wp-ui-text-notification">
94
+ <span class="dashicons dashicons-sos"></span>
95
+ <div>
96
+ <?php echo esc_html( $message->getMessage() ); ?>
97
+ </div>
98
+ </li>
99
+ <?php break; ?>
100
+
101
+ <?php default: ?>
102
+ <li class="wp-ui-text-highlight">
103
+ <span class="dashicons dashicons-info"></span>
104
+ <div>
105
+ <?php echo esc_html( $message->getMessage() ); ?>
106
+ </div>
107
+ </li>
108
+
109
+ <?php endswitch; ?>
110
+
111
+ <?php endforeach; ?>
112
+ </ul>
113
+
114
+ <?php endif; ?>
115
+
116
+ <?php else : ?>
117
+
118
+ <p>
119
+ <b>
120
+ <span class="dashicons dashicons-no-alt"></span>
121
+ Could not connect to your page. Please check the
122
+ <a href="<?php echo esc_url( $settings_page_href ); ?>">Instant Articles plugin settings</a>.
123
+ </b>
124
+ </p>
125
+
126
+ <?php endif; ?>
127
+
128
+ <hr>
129
+
130
+ <!-- Transformer messages -->
131
+ <?php if ( count( $adapter->transformer->getWarnings() ) > 0 ) : ?>
132
+ <p>
133
+ <span class="dashicons dashicons-warning"></span>
134
+ This post was transformed into an Instant Article with some warnings
135
+ <a href="#" class="instant-articles-toggle-debug">
136
+ (toggle debug information)
137
+ </a>
138
+ </p>
139
+ <ul class="instant-articles-messages">
140
+ <?php foreach ( $adapter->transformer->getWarnings() as $warning ) : ?>
141
+ <li class="wp-ui-text-highlight">
142
+ <span class="dashicons dashicons-warning"></span>
143
+ <div class="message">
144
+ <?php echo esc_html( $warning ); ?>
145
+ <span>
146
+ <?php
147
+ echo esc_html(
148
+ $warning->getNode()->ownerDocument->saveHTML( $warning->getNode() )
149
+ );
150
+ ?>
151
+ </span>
152
+ </div>
153
+ </dl>
154
+ </li>
155
+ <?php endforeach; ?>
156
+ </ul>
157
+
158
+ <?php else : ?>
159
+ <p>
160
+ <span class="dashicons dashicons-yes"></span>
161
+ This post was transformed into an Instant Article with no warnings
162
+ <a href="#" class="instant-articles-toggle-debug">
163
+ (toggle debug information)
164
+ </a>
165
+ </p>
166
+ <?php endif; ?>
167
+
168
+ <div class="instant-articles-transformer-markup">
169
+ <div>
170
+ <label for="source">Source Markup:</label>
171
+ <textarea class="source" readonly><?php echo esc_textarea( $adapter->get_the_content() ); ?></textarea>
172
+ </div>
173
+ <div>
174
+ <label for="transformed">Transformed Markup:</label>
175
+ <textarea class="source" readonly><?php echo esc_textarea( $article->render( '', true ) ); ?></textarea>
176
+ </div>
177
+ <br clear="all">
178
+ </div>
readme.txt CHANGED
@@ -1,21 +1,19 @@
1
- === Facebook Instant Articles for WP ===
2
- Contributors: automattic, bjornjohansen, dekode, trrine, olethomas, philipjohn
3
  Tags: instant articles, facebook, mobile
4
  Requires at least: 4.3
5
  Tested up to: 4.5
6
- Stable tag: 0.2
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
10
- Enable Instant Articles for Facebook on your WordPress site.
11
 
12
  == Description ==
13
 
14
  This plugin adds support for Instant Articles for Facebook, which is a new way for publishers to distribute fast, interactive stories on Facebook. Instant Articles are preloaded in the Facebook mobile app so they load instantly.
15
 
16
- With the plugin active, a special RSS feed will be available at the URL `/feed/instant-articles`.
17
-
18
- Developers: please note that this plugin is still in early stages and the underlying APIs (like filters, classes, etc.) may change.
19
 
20
  = Feed submission to Facebook =
21
 
@@ -25,22 +23,30 @@ It's important to note that if you use meta fields to add extra text, images or
25
 
26
  [See Facebook's documentation for full details of the submission process.](https://developers.facebook.com/docs/instant-articles)
27
 
28
- Facebook requires a minimum number of articles in your feed before they will review it. Once your feed has been approved, you can set the constant `INSTANT_ARTICLES_LIMIT_POSTS` to `true` to limit the feed to only show posts that have been modified within the last 24 hours. (Facebook will ignore any articles which were last modified more than 24 hours ago.)
29
-
30
- Facebook will fetch your feed every 3 minutes.
31
 
32
  == Installation ==
33
 
34
- 1. Upload the folder to the `/wp-content/plugins/` directory
35
- 1. Activate the plugin through the 'Plugins' menu in WordPress
 
 
 
 
 
 
 
 
 
 
36
 
37
  == Frequently Asked Questions ==
38
 
39
  = How do I customize the output for my site? =
40
 
41
- There are a number of filters available in the plugin for modifying the output. Note that these are not finalized and may change.
42
 
43
- = How do I change the feed slug/URL? =
44
 
45
  To change the feed slug, set the constant INSTANT_ARTICLES_SLUG to whatever you like. If you do, remember to flush the rewrite rules afterwards.
46
  By default it is set to `instant-articles` which usually will give you a feed URL set to `/feed/instant-articles`
@@ -51,11 +57,13 @@ Usually simply visiting the permalinks settings page in the WordPress dashboard
51
 
52
  == Changelog ==
53
 
54
- = 0.2 =
55
-
56
- * Fixes bug in formatting of YouTube videos
57
- * Fixes bug in formatting of Facebook embeds
58
- * Adds support for subtitles - see `instant_articles_subtitle` filter
59
-
60
  = 0.1 =
61
  * Initial version
 
 
 
 
 
 
 
 
1
+ === Instant Articles for WP ===
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.1
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
10
+ Enable [Instant Articles for Facebook](https://developers.facebook.com/docs/instant-articles) on your WordPress site.
11
 
12
  == Description ==
13
 
14
  This plugin adds support for Instant Articles for Facebook, which is a new way for publishers to distribute fast, interactive stories on Facebook. Instant Articles are preloaded in the Facebook mobile app so they load instantly.
15
 
16
+ With the plugin active, a new menu will be available for you to connect to your Facebook Page and start publishing your Instant Articles. You'll also see the status of each Instant Articles submission on the edit page of your posts.
 
 
17
 
18
  = Feed submission to Facebook =
19
 
23
 
24
  [See Facebook's documentation for full details of the submission process.](https://developers.facebook.com/docs/instant-articles)
25
 
26
+ Facebook requires a minimum number of articles in your feed before they will review it. Once your feed has been approved, new posts will automatically be taken live on Instant Articles, and existing posts will be taken live once you update them.
 
 
27
 
28
  == Installation ==
29
 
30
+ = From your WordPress dashboard =
31
+ * Visit 'Plugins > Add New'
32
+ * Search for 'Facebook Instant Articles for WP'
33
+ * Activate the plugin on your Plugins page
34
+
35
+ = From WordPress.org =
36
+ * Download Facebook Instant Articles for WP
37
+ * Upload the uncompressed directory to '/wp-content/plugins/'
38
+ * Activate the plugin on your Plugins page
39
+
40
+ = Once Activated =
41
+ * Click on the 'Instant Articles' menu and follow the instructions to activate the plugin
42
 
43
  == Frequently Asked Questions ==
44
 
45
  = How do I customize the output for my site? =
46
 
47
+ There are a number of filters available in the plugin for modifying the output.
48
 
49
+ = How do I change the feed slug/URL if I'm using the RSS integration? =
50
 
51
  To change the feed slug, set the constant INSTANT_ARTICLES_SLUG to whatever you like. If you do, remember to flush the rewrite rules afterwards.
52
  By default it is set to `instant-articles` which usually will give you a feed URL set to `/feed/instant-articles`
57
 
58
  == Changelog ==
59
 
 
 
 
 
 
 
60
  = 0.1 =
61
  * Initial version
62
+
63
+ = 2.0 =
64
+ * Using Facebook Instant Articles SDK for PHP
65
+ * Added API integration
66
+
67
+ = 2.1 =
68
+ * Fixes compatibility with PHP 5.4+
69
+ * Bug fixes
rules-configuration.json ADDED
@@ -0,0 +1,259 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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": "ImageRule",
61
+ "selector": "//p[img]",
62
+ "properties": {
63
+ "image.url": {
64
+ "type": "string",
65
+ "selector": "img",
66
+ "attribute": "src"
67
+ },
68
+ "image.caption": {
69
+ "type": "element",
70
+ "selector": "img"
71
+ }
72
+ }
73
+ },{
74
+ "class": "ImageRule",
75
+ "selector": "img",
76
+ "properties": {
77
+ "image.url": {
78
+ "type": "string",
79
+ "selector": "img",
80
+ "attribute": "src"
81
+ },
82
+ "image.caption": {
83
+ "type": "element",
84
+ "selector": "img[@alt]"
85
+ }
86
+ }
87
+ }, {
88
+ "class": "CaptionRule",
89
+ "selector": "img",
90
+ "properties": {
91
+ "caption.default": {
92
+ "type": "string",
93
+ "selector": "img",
94
+ "attribute": "alt"
95
+ }
96
+ }
97
+ }, {
98
+ "class": "ListItemRule",
99
+ "selector" : "li"
100
+ }, {
101
+ "class": "ListElementRule",
102
+ "selector" : "ul"
103
+ }, {
104
+ "class": "ListElementRule",
105
+ "selector" : "ol"
106
+ }, {
107
+ "class": "BlockquoteRule",
108
+ "selector" : "blockquote"
109
+ }, {
110
+ "class": "H1Rule",
111
+ "selector" : "h1",
112
+ "properties" : {
113
+ "h1.class" : {
114
+ "type" : "string",
115
+ "selector" : "link",
116
+ "attribute": "class"
117
+ }
118
+ }
119
+ }, {
120
+ "class": "H1Rule",
121
+ "selector" : "title"
122
+ }, {
123
+ "class": "H2Rule",
124
+ "selector" : "h2",
125
+ "properties" : {
126
+ "h2.class" : {
127
+ "type" : "string",
128
+ "selector" : "link",
129
+ "attribute": "class"
130
+ }
131
+ }
132
+ },
133
+ {
134
+ "class": "SocialEmbedRule",
135
+ "selector" : "iframe",
136
+ "properties" : {
137
+ "socialembed.url" : {
138
+ "type" : "string",
139
+ "selector" : "iframe",
140
+ "attribute": "src"
141
+ },
142
+ "socialembed.iframe" : {
143
+ "type" : "children",
144
+ "selector" : "iframe"
145
+ },
146
+ "socialembed.caption" : {
147
+ "type" : "element",
148
+ "selector" : "figcaption"
149
+ }
150
+ }
151
+ }, {
152
+ "class": "SocialEmbedRule",
153
+ "selector" : "//p[iframe]",
154
+ "properties" : {
155
+ "socialembed.url" : {
156
+ "type" : "string",
157
+ "selector" : "iframe",
158
+ "attribute": "src"
159
+ },
160
+ "socialembed.iframe" : {
161
+ "type" : "children",
162
+ "selector" : "iframe"
163
+ },
164
+ "socialembed.caption" : {
165
+ "type" : "element",
166
+ "selector" : "figcaption"
167
+ }
168
+ }
169
+ },{
170
+ "class": "SocialEmbedRule",
171
+ "selector" : "div.embed",
172
+ "properties" : {
173
+ "socialembed.iframe" : {
174
+ "type" : "children",
175
+ "selector" : "div.embed"
176
+ }
177
+ }
178
+ }, {
179
+ "class": "SocialEmbedRule",
180
+ "selector" : "//div[@class='embed' and iframe]",
181
+ "properties" : {
182
+ "socialembed.url" : {
183
+ "type" : "string",
184
+ "selector" : "iframe",
185
+ "attribute": "src"
186
+ }
187
+ }
188
+ }, {
189
+ "class": "ImageRule",
190
+ "selector": "//p[a[img]]|//a[img]",
191
+ "properties": {
192
+ "image.url": {
193
+ "type": "string",
194
+ "selector": "img",
195
+ "attribute": "src"
196
+ },
197
+ "image.caption": {
198
+ "type": "element",
199
+ "selector": "img[@alt]"
200
+ }
201
+ }
202
+ }, {
203
+ "class": "SlideshowImageRule",
204
+ "selector" : "figure",
205
+ "properties" : {
206
+ "image.url" : {
207
+ "type" : "string",
208
+ "selector" : "img",
209
+ "attribute": "src"
210
+ },
211
+ "caption.title" : {
212
+ "type" : "string",
213
+ "selector" : "figcaption"
214
+ }
215
+ }
216
+ }, {
217
+ "class": "SlideshowRule",
218
+ "selector" : "div.gallery"
219
+ }, {
220
+ "class": "CaptionRule",
221
+ "selector" : "figcaption"
222
+ },
223
+ {
224
+ "class": "ImageRule",
225
+ "selector" : "figure",
226
+ "properties" : {
227
+ "image.url" : {
228
+ "type" : "string",
229
+ "selector" : "img",
230
+ "attribute": "src"
231
+ }
232
+ }
233
+ }, {
234
+ "class": "VideoRule",
235
+ "selector" : "div.wp-video",
236
+ "containsChild": "video",
237
+ "properties" : {
238
+ "video.url" : {
239
+ "type" : "string",
240
+ "selector" : "source",
241
+ "attribute": "src"
242
+ },
243
+ "video.type" : {
244
+ "type" : "string",
245
+ "selector" : "source",
246
+ "attribute": "type"
247
+ }
248
+ }
249
+ }, {
250
+ "class": "InteractiveRule",
251
+ "selector" : "table",
252
+ "properties" : {
253
+ "interactive.iframe" : {
254
+ "type" : "element",
255
+ "selector" : "table"
256
+ }
257
+ }
258
+ }]
259
+ }
settings/class-instant-articles-option-ads.php ADDED
@@ -0,0 +1,254 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Facebook Instant Articles for WP.
4
+ * This source code is licensed under the license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @package default
8
+ */
9
+
10
+ require_once( dirname( __FILE__ ) . '/class-instant-articles-option.php' );
11
+
12
+ /**
13
+ * Configuration class for Ads.
14
+ */
15
+ class Instant_Articles_Option_Ads extends Instant_Articles_Option {
16
+
17
+ const OPTION_KEY = 'instant-articles-option-ads';
18
+
19
+ public static $sections = array(
20
+ 'title' => 'Ads',
21
+ 'description' => '<p>Choose your preferred method for displaying ads in your Instant Articles and input the code in the boxes below. Learn more about your options for <a href="https://developers.facebook.com/docs/instant-articles/ads-analytics" target="_blank">advertising in Instant Articles</a>.</p>',
22
+ );
23
+
24
+ public static $fields = array(
25
+
26
+ 'ad_source' => array(
27
+ 'label' => 'Ad Type',
28
+ 'description' => 'This plugin will automatically place the ads within your articles.',
29
+ 'render' => array( 'Instant_Articles_Option_Ads', 'custom_render_ad_source' ),
30
+ 'select_options' => array(
31
+ 'none' => 'None',
32
+ 'fan' => 'Facebook Audience Network',
33
+ 'iframe' => 'Custom iframe URL',
34
+ 'embed' => 'Custom Embed Code',
35
+ ),
36
+ 'default' => 'none',
37
+ ),
38
+
39
+ 'fan_placement_id' => array(
40
+ 'label' => 'Audience Network Placement ID',
41
+ 'description' => 'Find your <a href="https://developers.facebook.com/docs/audience-network/instantarticles/banner" target="_blank">Placement ID</a> for Facebook Audience Network on your app\'s Audience Network Portal',
42
+ 'default' => null,
43
+ ),
44
+
45
+ 'iframe_url' => array(
46
+ 'label' => 'Source URL',
47
+ 'placeholder' => '//ad-server.com/my-ad',
48
+ 'description' => 'Note: Instant Articles only supports Direct Sold ads. No programmatic ad networks, other than Facebook\'s Audience Network, are permitted.',
49
+ 'default' => '',
50
+ ),
51
+
52
+ 'embed_code' => array(
53
+ 'label' => 'Embed Code',
54
+ 'render' => 'textarea',
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(
61
+ 'label' => 'Ad Dimensions',
62
+ 'render' => 'select',
63
+ 'select_options' => array(
64
+ '300x250' => 'Large (300 x 250)',
65
+ '320x50' => 'Small (320 x 50)',
66
+ ),
67
+ 'default' => '300x250',
68
+ ),
69
+
70
+ );
71
+
72
+ /**
73
+ * Constructor.
74
+ *
75
+ * @since 0.4
76
+ */
77
+ public function __construct() {
78
+ parent::__construct(
79
+ self::OPTION_KEY,
80
+ self::$sections,
81
+ self::$fields
82
+ );
83
+ wp_localize_script( 'instant-articles-option-ads', 'INSTANT_ARTICLES_OPTION_ADS', array(
84
+ 'option_field_id_source' => self::OPTION_KEY . '-ad_source',
85
+ 'option_field_id_fan' => self::OPTION_KEY . '-fan_placement_id',
86
+ 'option_field_id_iframe' => self::OPTION_KEY . '-iframe_url',
87
+ 'option_field_id_embed' => self::OPTION_KEY . '-embed_code',
88
+ 'option_field_id_dimensions' => self::OPTION_KEY . '-dimensions',
89
+ ) );
90
+ }
91
+
92
+ /**
93
+ * Renders the ad source.
94
+ *
95
+ * @param array $args configuration fields for the ad.
96
+ * @since 0.4
97
+ */
98
+ public static function custom_render_ad_source( $args ) {
99
+ $id = $args['label_for'];
100
+ $name = $args['serialized_with_group'] . '[ad_source]';
101
+
102
+ $description = isset( $args['description'] )
103
+ ? '<p class="description">' . esc_html( $args['description'] ) . '</p>'
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 ); ?>"
114
+ <?php echo selected( self::$settings['ad_source'], $ad_source_key ) ?>
115
+ >
116
+ <?php echo esc_html( $ad_source_name ); ?>
117
+ </option>
118
+ <?php endforeach; ?>
119
+
120
+ <?php
121
+ $compat_plugins = parent::get_registered_compat( 'instant_articles_compat_registry_ads' );
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 ); ?>"
131
+ <?php echo selected( self::$settings['ad_source'], $ad_source_key ) ?>
132
+ >
133
+ <?php echo esc_html( $ad_source_info['name'] ); ?>
134
+ </option>
135
+ <?php endforeach; ?>
136
+ </optgroup>
137
+ <?php endif; ?>
138
+
139
+ ?>
140
+ </select>
141
+ <?php echo $description; ?>
142
+ <?php
143
+ }
144
+
145
+ /**
146
+ * Sanitize and return all the field values.
147
+ *
148
+ * This method receives a payload containing all value for its fields and
149
+ * should return the same payload after having been sanitized.
150
+ *
151
+ * Do not, encode the payload as this is performed by the
152
+ * universal_sanitize_and_encode_handler() of the parent class.
153
+ *
154
+ * @param array $field_values The array map with field values.
155
+ * @since 0.5
156
+ */
157
+ public function sanitize_option_fields( $field_values ) {
158
+ foreach ( $field_values as $field_id => $field_value ) {
159
+ $field = self::$fields[ $field_id ];
160
+
161
+ switch ( $field_id ) {
162
+ case 'ad_source':
163
+ $all_options = array();
164
+
165
+ $registered_compat_ads = Instant_Articles_Option::get_registered_compat(
166
+ 'instant_articles_compat_registry_ads'
167
+ );
168
+
169
+ foreach ( $field['select_options'] as $option_id => $option_info ) {
170
+ $all_options[] = $option_id;
171
+ }
172
+ foreach ( $registered_compat_ads as $compat_id => $compat_info ) {
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,
180
+ 'invalid_option',
181
+ 'Invalid Ad Source'
182
+ );
183
+ }
184
+ break;
185
+
186
+ case 'fan_placement_id':
187
+ if ( isset( $field_values['ad_source'] ) && 'fan' === $field_values['ad_source'] ) {
188
+ if (
189
+ ! is_numeric( $field_values[ $field_id ] ) ||
190
+ strval( absint( $field_values[ $field_id ] ) ) !== $field_values[ $field_id ]
191
+ ) {
192
+ add_settings_error(
193
+ $field_id,
194
+ 'invalid_placement_id',
195
+ 'Invalid Audience Network Placement ID provided'
196
+ );
197
+ $field_values[ $field_id ] = $field['default'];
198
+ } else {
199
+ $field_values[ $field_id ] = absint( $field_values[ $field_id ] );
200
+ }
201
+ }
202
+ break;
203
+
204
+ case 'iframe_url':
205
+ if ( isset( $field_values['ad_source'] ) && 'iframe' === $field_values['ad_source'] ) {
206
+ $url = $field_values[$field_id];
207
+ if ( substr( $url, 0, 2 ) === '//' ) {
208
+ // Allow URLs without protocol prefix
209
+ $url = 'http:' . $url;
210
+ }
211
+ $url = filter_var( $url , FILTER_VALIDATE_URL );
212
+ if ( ! $url ) {
213
+ $field_values[ $field_id ] = $field['default'];
214
+ add_settings_error(
215
+ $field_id,
216
+ 'invalid_url',
217
+ 'Invalid URL provided for Ad iframe'
218
+ );
219
+ }
220
+ }
221
+ break;
222
+
223
+ case 'embed_code':
224
+ if ( isset( $field_values['ad_source'] ) && 'embed' === $field_values['ad_source'] ) {
225
+ $document = new DOMDocument();
226
+ $fragment = $document->createDocumentFragment();
227
+ if ( ! @$fragment->appendXML( $field_values[ $field_id ] ) ) {
228
+ add_settings_error(
229
+ 'embed_code',
230
+ 'invalid_markup',
231
+ 'Invalid HTML markup provided for ad custom embed code'
232
+ );
233
+ }
234
+ }
235
+ break;
236
+
237
+ case 'dimensions':
238
+ if ( isset( $field_values['ad_source'] ) && 'none' !== $field_values['ad_source'] ) {
239
+ if ( ! array_key_exists( $field_value, $field['select_options'] ) ) {
240
+ $field_values[ $field_id ] = $field['default'];
241
+ add_settings_error(
242
+ 'embed_code',
243
+ 'invalid_dimensions',
244
+ 'Invalid dimensions provided for Ad'
245
+ );
246
+ }
247
+ }
248
+ break;
249
+ }
250
+ }
251
+
252
+ return $field_values;
253
+ }
254
+ }
settings/class-instant-articles-option-analytics.php ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Facebook Instant Articles for WP.
4
+ * This source code is licensed under the license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @package default
8
+ */
9
+
10
+ require_once( dirname( __FILE__ ) . '/class-instant-articles-option.php' );
11
+
12
+ /**
13
+ * Analytics configuration class.
14
+ */
15
+ class Instant_Articles_Option_Analytics extends Instant_Articles_Option {
16
+
17
+ const OPTION_KEY = 'instant-articles-option-analytics';
18
+
19
+ public static $sections = array(
20
+ 'title' => 'Analytics',
21
+ 'description' => '<p>Enable 3rd-party analytics to be used with Instant Articles.</p><p>If you already use a Wordpress plugin to manage analytics, you can enable it below. You can also embed code to insert your own trackers and analytics. <a href="https://developers.facebook.com/docs/instant-articles/ads-analytics#analytics" target="_blank">Learn more about Analytics in Instant Articles</a>.</p>',
22
+ );
23
+
24
+ public static $fields = array(
25
+
26
+ 'integrations' => array(
27
+ 'label' => '3rd party integrations',
28
+ 'render' => array( 'Instant_Articles_Option_Analytics', 'custom_render_integrations' ),
29
+ 'default' => array(),
30
+ ),
31
+
32
+ 'embed_code_enabled' => array(
33
+ 'label' => 'Embed code',
34
+ 'render' => 'checkbox',
35
+ 'default' => false,
36
+ 'description' => 'Add code for any other analytics services you wish to use.',
37
+ 'checkbox_label' => 'Enable custom embed code',
38
+ ),
39
+
40
+ 'embed_code' => array(
41
+ 'label' => '',
42
+ 'render' => 'textarea',
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
+
49
+ /**
50
+ * Constructor.
51
+ *
52
+ * @since 0.4
53
+ */
54
+ public function __construct() {
55
+ parent::__construct(
56
+ self::OPTION_KEY,
57
+ self::$sections,
58
+ self::$fields
59
+ );
60
+ wp_localize_script( 'instant-articles-option-analytics', 'INSTANT_ARTICLES_OPTION_ANALYTICS', array(
61
+ 'option_field_id_embed_code_enabled' => self::OPTION_KEY . '-embed_code_enabled',
62
+ 'option_field_id_embed_code' => self::OPTION_KEY . '-embed_code',
63
+ ) );
64
+ }
65
+
66
+ /**
67
+ * Renders the markup for the `integrations` field.
68
+ *
69
+ * @param array $args The array with configuration of fields.
70
+ * @since 0.4
71
+ */
72
+ public static function custom_render_integrations( $args ) {
73
+ $name = $args['serialized_with_group'] . '[integrations][]';
74
+
75
+ $compat_plugins = parent::get_registered_compat( 'instant_articles_compat_registry_analytics' );
76
+
77
+ if ( empty( $compat_plugins ) ) {
78
+ ?>
79
+ <em>
80
+ <?php echo esc_html( 'No supported analytics plugins are installed nor activated' ); ?>
81
+ </em>
82
+ <?php
83
+
84
+ return;
85
+ }
86
+
87
+ asort( $compat_plugins );
88
+ foreach ( $compat_plugins as $plugin_id => $plugin_info ) {
89
+ ?>
90
+ <label>
91
+ <input
92
+ type="checkbox"
93
+ name="<?php echo esc_attr( $name ); ?>"
94
+ value="<?php echo esc_attr( $plugin_id ); ?>"
95
+ <?php echo checked( in_array( $plugin_id, self::$settings['integrations'], true ) ) ?>
96
+ >
97
+ <?php echo esc_html( $plugin_info['name'] ); ?>
98
+ </label>
99
+ <br />
100
+ <?php
101
+ }
102
+ ?>
103
+ <p class="description">Select which analytics services you'd like to use with Instant Articles.</p>
104
+ <?php
105
+ }
106
+
107
+ /**
108
+ * Sanitize and return all the field values.
109
+ *
110
+ * This method receives a payload containing all value for its fields and
111
+ * should return the same payload after having been sanitized.
112
+ *
113
+ * Do not encode the payload as this is performed by the
114
+ * universal_sanitize_and_encode_handler() of the parent class.
115
+ *
116
+ * @param array $field_values The values in an array mapped keys.
117
+ * @since 0.5
118
+ */
119
+ public function sanitize_option_fields( $field_values ) {
120
+ foreach ( $field_values as $field_id => $field_value ) {
121
+ $field = self::$fields[ $field_id ];
122
+
123
+ switch ( $field_id ) {
124
+ case 'embed_code':
125
+ if ( isset( $field_values['embed_code_enabled'] ) && $field_values['embed_code_enabled'] ) {
126
+ $document = new DOMDocument();
127
+ $fragment = $document->createDocumentFragment();
128
+ if ( ! @$fragment->appendXML( $field_values[ $field_id ] ) ) {
129
+ add_settings_error(
130
+ 'embed_code',
131
+ 'invalid_markup',
132
+ 'Invalid HTML markup provided for custom analytics tracker code'
133
+ );
134
+ }
135
+ }
136
+
137
+ break;
138
+ }
139
+ }
140
+
141
+ return $field_values;
142
+ }
143
+ }
settings/class-instant-articles-option-fb-app.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Facebook Instant Articles for WP.
4
+ * This source code is licensed under the license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @package default
8
+ */
9
+
10
+ require_once( dirname( __FILE__ ) . '/class-instant-articles-option.php' );
11
+
12
+ /**
13
+ * The Instant Articles FB app configuration.
14
+ */
15
+ class Instant_Articles_Option_FB_App extends Instant_Articles_Option {
16
+
17
+ const OPTION_KEY = 'instant-articles-option-fb-app';
18
+
19
+ public static $sections = array(
20
+ 'title' => '',
21
+ 'description' => '',
22
+ );
23
+
24
+ public static $fields = array(
25
+
26
+ 'app_id' => array(
27
+ 'label' => 'App ID',
28
+ 'default' => '',
29
+ ),
30
+
31
+ 'app_secret' => array(
32
+ 'label' => 'App Secret',
33
+ 'render' => 'password',
34
+ 'default' => '',
35
+ ),
36
+
37
+ );
38
+
39
+ /**
40
+ * Consturctor.
41
+ *
42
+ * @since 0.4
43
+ */
44
+ public function __construct() {
45
+ $this->options_manager = new parent(
46
+ self::OPTION_KEY,
47
+ self::$sections,
48
+ self::$fields,
49
+ /**
50
+ * Register this Option on a specific page group (used as the first
51
+ * argument of `register_setting()` and called by `settings_fields()`).
52
+ *
53
+ * @since 0.5
54
+ */
55
+ Instant_Articles_Option::PAGE_OPTION_GROUP_WIZARD
56
+ );
57
+ }
58
+ }
settings/class-instant-articles-option-fb-page.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Facebook Instant Articles for WP.
4
+ * This source code is licensed under the license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @package default
8
+ */
9
+
10
+ require_once( dirname( __FILE__ ) . '/class-instant-articles-option.php' );
11
+
12
+ /**
13
+ * FB Page configuration.
14
+ */
15
+ class Instant_Articles_Option_FB_Page extends Instant_Articles_Option {
16
+
17
+ const OPTION_KEY = 'instant-articles-option-fb-page';
18
+
19
+ public static $sections = array(
20
+ 'title' => '',
21
+ 'description' => '',
22
+ );
23
+
24
+ public static $fields = array(
25
+
26
+ 'page_id' => array(
27
+ 'visible' => false,
28
+ 'label' => 'Page ID',
29
+ 'default' => '',
30
+ ),
31
+
32
+ 'page_name' => array(
33
+ 'visible' => false,
34
+ 'label' => 'Page Name',
35
+ 'default' => '',
36
+ ),
37
+
38
+ 'page_access_token' => array(
39
+ 'visible' => false,
40
+ 'label' => 'Page Access Token',
41
+ 'default' => '',
42
+ ),
43
+
44
+ 'page_access_token_expiration' => array(
45
+ 'visible' => false,
46
+ 'label' => 'Page Token Expiration',
47
+ 'default' => '',
48
+ ),
49
+
50
+ );
51
+
52
+ /**
53
+ * Constructor.
54
+ *
55
+ * @since 0.4
56
+ */
57
+ public function __construct() {
58
+ $this->options_manager = new parent(
59
+ self::OPTION_KEY,
60
+ self::$sections,
61
+ self::$fields,
62
+ /**
63
+ * Register this Option on a specific page group (used as the first
64
+ * argument of `register_setting()` and called by `settings_fields()`).
65
+ *
66
+ * @since 0.5
67
+ */
68
+ Instant_Articles_Option::PAGE_OPTION_GROUP_WIZARD
69
+ );
70
+ }
71
+ }
settings/class-instant-articles-option-publishing.php ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Facebook Instant Articles for WP.
4
+ * This source code is licensed under the license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @package default
8
+ */
9
+
10
+ require_once( dirname( __FILE__ ) . '/class-instant-articles-option.php' );
11
+
12
+ /**
13
+ * Class for publishing configuration.
14
+ */
15
+ class Instant_Articles_Option_Publishing extends Instant_Articles_Option {
16
+
17
+ const OPTION_KEY = 'instant-articles-option-publishing';
18
+
19
+ public static $sections = array(
20
+ 'title' => 'Publishing Settings',
21
+ );
22
+
23
+ public static $fields = array(
24
+
25
+ 'dev_mode' => array(
26
+ 'label' => 'Development Mode',
27
+ 'description' => 'When publishing in development, none of your articles will be made live, and they will be saved as drafts you can edit in the Instant Articles library on your Facebook Page. Whether in development mode or not, articles will not be published live until you have submitted a sample batch to Facebook and passed a one-time review.',
28
+ 'render' => 'checkbox',
29
+ 'default' => false,
30
+ 'checkbox_label' => 'Enable development mode',
31
+ ),
32
+
33
+ 'custom_rules_enabled' => array(
34
+ 'label' => 'Custom transformer rules',
35
+ 'render' => 'checkbox',
36
+ 'default' => '',
37
+ 'checkbox_label' => 'Enable custom transformer rules',
38
+ 'description' => 'You can provide a JSON with a list of additional <a href="https://github.com/facebook/facebook-instant-articles-sdk-php/blob/master/docs/QuickStart.md#transformer" target="_blanl">Transformer Rules</a> to customize the output of your Instant Articles.',
39
+ 'default' => '',
40
+ ),
41
+
42
+ 'custom_rules' => array(
43
+ 'label' => '',
44
+ 'render' => 'textarea',
45
+ 'placeholder' => '{ "rules": [{ "class": "BoldRule", "selector": "span.bold" }, ... ] }',
46
+ 'description' => 'Refer to the <a href="https://github.com/facebook/facebook-instant-articles-sdk-php/blob/master/tests/Facebook/InstantArticles/Transformer/instant-article-example-rules.json" target="_blank">example JSON</a> on the <a href="https://github.com/facebook/facebook-instant-articles-sdk-php" target="_blank">Facebook Instant Articles PHP SDK</a> for sample configurations for all built-in rules.'
47
+ ),
48
+
49
+ );
50
+
51
+ /**
52
+ * Constructor.
53
+ *
54
+ * @since 0.4
55
+ */
56
+ public function __construct() {
57
+ parent::__construct(
58
+ self::OPTION_KEY,
59
+ self::$sections,
60
+ self::$fields
61
+ );
62
+ wp_localize_script( 'instant-articles-option-publishing', 'INSTANT_ARTICLES_OPTION_PUBLISHING', array(
63
+ 'option_field_id_custom_rules_enabled' => self::OPTION_KEY . '-custom_rules_enabled',
64
+ 'option_field_id_custom_rules' => self::OPTION_KEY . '-custom_rules'
65
+ ) );
66
+ }
67
+
68
+ /**
69
+ * Sanitize and return all the field values.
70
+ *
71
+ * This method receives a payload containing all value for its fields and
72
+ * should return the same payload after having been sanitized.
73
+ *
74
+ * Do not encode the payload as this is performed by the
75
+ * universal_sanitize_and_encode_handler() of the parent class.
76
+ *
77
+ * @param array $field_values array map with key field_id => value.
78
+ * @since 0.5
79
+ */
80
+ public function sanitize_option_fields( $field_values ) {
81
+ foreach ( $field_values as $field_id => $field_value ) {
82
+ $field = self::$fields[ $field_id ];
83
+
84
+ switch ( $field_id ) {
85
+ case 'dev_mode':
86
+ $field_values[ $field_id ] = (bool) $field_value
87
+ ? (string) true
88
+ : (string) $field['default'];
89
+ break;
90
+
91
+ case 'custom_rules':
92
+ if ( isset( $field_values['custom_rules_enabled'] ) && $field_values['custom_rules_enabled'] ) {
93
+ $custom_rules_json = json_decode( $field_values['custom_rules'] );
94
+ if ( $custom_rules_json === null ) {
95
+ $field_values['custom_rules'] = $field['default'];
96
+ add_settings_error(
97
+ 'custom_embed',
98
+ 'invalid_json',
99
+ 'Invalid JSON provided for custom rules code'
100
+ );
101
+ }
102
+ }
103
+ break;
104
+
105
+ default:
106
+ // Should never happen.
107
+ break;
108
+ }
109
+ }
110
+
111
+ return $field_values;
112
+ }
113
+ }
settings/class-instant-articles-option-styles.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Facebook Instant Articles for WP.
4
+ * This source code is licensed under the license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @package default
8
+ */
9
+
10
+ require_once( dirname( __FILE__ ) . '/class-instant-articles-option.php' );
11
+
12
+ /**
13
+ * Configuration class for Ads.
14
+ */
15
+ class Instant_Articles_Option_Styles extends Instant_Articles_Option {
16
+
17
+ const OPTION_KEY = 'instant-articles-option-styles';
18
+
19
+ public static $sections = array(
20
+ 'title' => 'Styles',
21
+ 'description' => '<p>Assign your Instant Articles a custom style. To begin, customize a template using the Style Editor. Next, input the name of the style below.</p><p><strong>Note:</strong> If this field is left blank, the plugin will enable the “Default” style. Learn more about Instant Articles style options in the <a href="https://developers.facebook.com/docs/instant-articles/guides/design" target="_blank">Design Guide</a>.</p>',
22
+ );
23
+
24
+ public static $fields = array(
25
+
26
+ 'article_style' => array(
27
+ 'label' => 'Article Style',
28
+ 'default' => 'default',
29
+ ),
30
+
31
+ );
32
+
33
+ /**
34
+ * Constructor.
35
+ *
36
+ * @since 0.4
37
+ */
38
+ public function __construct() {
39
+ parent::__construct(
40
+ self::OPTION_KEY,
41
+ self::$sections,
42
+ self::$fields
43
+ );
44
+ }
45
+ }
settings/class-instant-articles-option.php ADDED
@@ -0,0 +1,457 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Facebook Instant Articles for WP.
4
+ * This source code is licensed under the license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @package default
8
+ */
9
+
10
+ /**
11
+ * Base class for configurations.
12
+ */
13
+ class Instant_Articles_Option {
14
+
15
+ const PAGE_OPTION_GROUP = 'instant-articles-settings';
16
+ const PAGE_OPTION_GROUP_WIZARD = 'instant-articles-settings-wizard';
17
+ public static $fields = array();
18
+
19
+ /**
20
+ * Settings for options.
21
+ *
22
+ * @var array $settings The settings for each option.
23
+ */
24
+ public static $settings = array();
25
+
26
+ /**
27
+ * The key for field.
28
+ *
29
+ * @var string $key The key for field.
30
+ */
31
+ private $key;
32
+
33
+ /**
34
+ * Each section.
35
+ *
36
+ * @var array $sections The sections where fields will be stored/showed.
37
+ */
38
+ private $sections;
39
+
40
+ /**
41
+ * Page options.
42
+ *
43
+ * @var array $page_option_group
44
+ */
45
+ private $page_option_group;
46
+
47
+ /**
48
+ * Contains all the fields for the option. Supported field properties:
49
+ *
50
+ * Id - String. COMING SOON (to avoid using the key as the identifier)
51
+ * visible - Boolean. Use this to hide the entire row of the rendered field in the UI. Defaults to true.
52
+ * disable - Boolean|Array. Use to place the `disabled` attribute on the field. For fields with multiple options (<select>) an Array containing keys of all disabled `select_options` can be defined. Defaults to false.
53
+ * serialized_with_group - String|false/null. Controls whether a particular field of a setting is serialized with the group or saved as its own independant option. Defaults to true.
54
+ * label - String|null. The label for the field.
55
+ * description - String. The description for the field, rendered as additional information below the field.
56
+ * render - String|Function. How the field should be rendered as. Non-strings are assumed to be a function for rendering the field (third parameter of `add_settings_field()`). If a String, it is meant to be any of the standard <form> input types (checkbox, radio, textarea, hidden, select, textarea, password etc.') and the rendering will be handled by self::universal_render_handler(); if not defined, "text" is assumed
57
+ * select_options - Array. Defines the <options> for a checkbox (key of this Array is used as its `value` attribute). Only used if the `render` is "select".
58
+ * radio_options - Array. TO BE IMPLEMENTED (should mimic the "select_options" functionality)
59
+ * placeholder - String. Used as the `placeholder` attribute for the <form> field.
60
+ * default - String|null. Used as a default value for the field when there is no value yet saved in the db.
61
+ *
62
+ * @var array $fields The fields for option and its properties.
63
+ * @since 0.4
64
+ */
65
+ private $field_definitions;
66
+
67
+ /**
68
+ * If $option_group is not specified, the Option will be registered with a
69
+ * "default" page group (the first argument of `register_setting()` and called
70
+ * by `settings_fields()`).
71
+ *
72
+ * @param string $option_key The ID for the field.
73
+ * @param array $sections The sections for each field.
74
+ * @param array $option_fields All the fields.
75
+ * @param array $option_group Optional, if not informed will use self::PAGE_OPTION_GROUP.
76
+ * @since 0.4
77
+ */
78
+ public function __construct( $option_key, $sections, $option_fields, $option_group = null ) {
79
+ $this->key = $option_key;
80
+ $this->sections = $sections;
81
+ $this->field_definitions = $option_fields;
82
+ $this->page_option_group = null === $option_group
83
+ ? self::PAGE_OPTION_GROUP
84
+ : $option_group;
85
+
86
+ $this->init();
87
+ }
88
+
89
+ /**
90
+ * Option initiator.
91
+ *
92
+ * @since 0.4
93
+ */
94
+ private function init() {
95
+ $saved_options = self::get_option_decoded( $this->key );
96
+
97
+ foreach ( $this->field_definitions as $field_key => $field ) {
98
+ self::$settings[ $field_key ] = isset( $saved_options[ $field_key ] )
99
+ ? $saved_options[ $field_key ]
100
+ : $field['default'];
101
+ }
102
+
103
+ $this->wp_bootstrap_register_option();
104
+ $this->wp_bootstrap_create_sections();
105
+ $this->wp_bootstrap_add_fields_to_section();
106
+ }
107
+
108
+ /**
109
+ * Decodes the option.
110
+ *
111
+ * @param string $option_key to be returned.
112
+ * @return array from a json decoded content.
113
+ * @since 0.4
114
+ */
115
+ public static function get_option_decoded( $option_key = null ) {
116
+ if ( ! isset( $option_key ) ) {
117
+ // Late Static Binding to use the const OPTION_KEY from the child class which called this function.
118
+ $option_key = static::OPTION_KEY;
119
+ }
120
+
121
+ $raw_data = get_option( $option_key );
122
+
123
+ // Hack which creates an empty setting if it doesn't yet exist.
124
+ // Temporary solution to an unknown oddity which is double-escaping the JSON
125
+ // data as a string when attempting to access a setting that doesn't exist.
126
+ if ( false === $raw_data ) {
127
+ add_option( $option_key );
128
+ $raw_data = get_option( $option_key );
129
+ }
130
+
131
+ return json_decode( $raw_data, true );
132
+ }
133
+
134
+ /**
135
+ * Obtains the compat related to $action_tag.
136
+ *
137
+ * @param string $action_tag The tag registered compat will be retrieved.
138
+ * @since 0.4
139
+ */
140
+ public static function get_registered_compat( $action_tag ) {
141
+ $registered_compat_integrations = array();
142
+
143
+ do_action_ref_array(
144
+ $action_tag,
145
+ array( &$registered_compat_integrations )
146
+ );
147
+ return $registered_compat_integrations;
148
+ }
149
+
150
+ /**
151
+ * Registers the sanitization and encoding handler.
152
+ *
153
+ * @since 0.4
154
+ */
155
+ private function wp_bootstrap_register_option() {
156
+ register_setting(
157
+ $this->page_option_group,
158
+ $this->key,
159
+ array( $this, 'universal_sanitize_and_encode_handler' )
160
+ );
161
+ }
162
+
163
+ /**
164
+ * Create title and description sections.
165
+ *
166
+ * @since 0.4
167
+ */
168
+ private function wp_bootstrap_create_sections() {
169
+ $title = isset( $this->sections['title'] )
170
+ ? $this->sections['title']
171
+ : '';
172
+
173
+ $description = isset( $this->sections['description'] )
174
+ ? wp_kses(
175
+ $this->sections['description'],
176
+ array(
177
+ 'a' => array(
178
+ 'href' => array(),
179
+ 'target' => array()
180
+ ),
181
+ 'em' => array(),
182
+ 'p' => array(),
183
+ 'strong' => array()
184
+ )
185
+ )
186
+ : '';
187
+
188
+ add_settings_section(
189
+ $this->key,
190
+ esc_html( $title ),
191
+ function () use ( $description ) {
192
+ echo $description;
193
+ },
194
+ $this->key
195
+ );
196
+ }
197
+
198
+ /**
199
+ * Add fields to defined section.
200
+ *
201
+ * @since 0.4
202
+ */
203
+ private function wp_bootstrap_add_fields_to_section() {
204
+ foreach ( $this->field_definitions as $field_key => $field ) {
205
+ $standalone_id = $this->key . '-' . $field_key;
206
+
207
+ // Default values of arguments for renderer.
208
+ $renderer_args = array(
209
+ // The "label_for" arg causes WordPress to wrap the label of the field with a <label> tag.
210
+ 'label_for' => $standalone_id,
211
+ 'serialized_with_group' => $this->key,
212
+ 'render' => 'text',
213
+ 'value' => self::$settings[ $field_key ],
214
+ );
215
+
216
+ // Override default arguments for renderer.
217
+ foreach ( $field as $key => $val ) {
218
+ $renderer_args[ $key ] = $val;
219
+
220
+ // The WordPress do_settings_fields() will add a `class` attribute to
221
+ // the <tr> tag of the rendered output with value of anything defined in
222
+ // a "class" key of the args for the renderer.
223
+ // We force it to include a value of "hidden" since this class is
224
+ // defined in WordPress's global CSS with `display: none;`.
225
+ if ( 'visible' === $key && false === $val ) {
226
+ $renderer_args['class'] = ( ! empty( $renderer_args['class'] )
227
+ ? $renderer_args['class'] . ' '
228
+ : '') . 'hidden';
229
+ }
230
+ }
231
+
232
+ $renderer_handle = 'string' === gettype( $renderer_args['render'] )
233
+ ? array( 'Instant_Articles_Option', 'universal_render_handler' )
234
+ : $renderer_args['render'];
235
+
236
+ add_settings_field(
237
+ $standalone_id,
238
+ $field['label'],
239
+ $renderer_handle,
240
+ $this->key,
241
+ $this->key,
242
+ $renderer_args
243
+ );
244
+ }
245
+ }
246
+
247
+ /**
248
+ * Function to render all fields with its labels and inputs.
249
+ *
250
+ * @param array $args array map with its field names and values.
251
+ * @since 0.4
252
+ */
253
+ public static function universal_render_handler( $args = null ) {
254
+ $id = isset( $args['label_for'] )
255
+ ? $args['label_for']
256
+ : '';
257
+
258
+ $type = isset( $args['render'] ) && gettype( 'string' === $args['render'] )
259
+ ? $args['render']
260
+ : 'text';
261
+
262
+ if ( ! empty( $args['value'] ) ) {
263
+ $option_value = $args['value'];
264
+ } elseif ( ! empty( $args['default'] ) ) {
265
+ $option_value = $args['default'];
266
+ } else {
267
+ $option_value = '';
268
+ }
269
+
270
+ // Determines correct values based on whether the settings option
271
+ // is intended to be serialized as a field of a parent option name.
272
+ if ( gettype( 'string' === $args['serialized_with_group'] ) ) {
273
+ $group = $args['serialized_with_group'];
274
+ $group_key = substr( $id, strlen( $group . '-' ) );
275
+ $name = $group . '[' . $group_key . ']';
276
+ } else {
277
+ $name = $id;
278
+ }
279
+
280
+ $placeholder = isset( $args['placeholder'] )
281
+ ? $args['placeholder']
282
+ : '';
283
+
284
+ $attr_disabled = isset( $args['disable'] ) && true === $args['disable']
285
+ ? disabled()
286
+ : '';
287
+
288
+ $field_description = isset( $args['description'] )
289
+ ? wp_kses(
290
+ $args['description'],
291
+ array(
292
+ 'a' => array(
293
+ 'href' => array(),
294
+ 'target' => array()
295
+ ),
296
+ 'em' => array(),
297
+ 'strong' => array()
298
+ )
299
+ )
300
+ : '';
301
+
302
+ $field_checkbox_label = isset( $args['checkbox_label'] )
303
+ ? $args['checkbox_label']
304
+ : '';
305
+
306
+ switch ( $type ) {
307
+ case 'hidden':
308
+ ?>
309
+ <input
310
+ type="hidden"
311
+ name="<?php echo esc_attr( $name ) ?>"
312
+ id="<?php echo esc_attr( $id ) ?>"
313
+ value="<?php echo esc_attr( $option_value ); ?>"
314
+ />
315
+ <?php if ( $field_description ) : ?>
316
+ <p class="description">
317
+ <?php echo $field_description; ?>
318
+ </p>
319
+ <?php endif; ?>
320
+ <?php
321
+ break;
322
+
323
+ case 'checkbox':
324
+ $attr_checked = checked( 1, $option_value, false );
325
+ ?>
326
+ <label>
327
+ <input
328
+ type="checkbox"
329
+ value="1"
330
+ name="<?php echo esc_attr( $name ) ?>"
331
+ id="<?php echo esc_attr( $id ) ?>"
332
+ <?php echo esc_attr( $attr_checked ); ?>
333
+ <?php echo esc_attr( $attr_disabled ); ?>
334
+ />
335
+ <?php echo esc_html( $field_checkbox_label ); ?>
336
+ </label>
337
+ <?php if ( $field_description ) : ?>
338
+ <p class="description">
339
+ <?php echo $field_description; ?>
340
+ </p>
341
+ <?php endif; ?>
342
+ <?php
343
+ break;
344
+
345
+ case 'select':
346
+ ?>
347
+ <select
348
+ id="<?php echo esc_attr( $id ) ?>"
349
+ name="<?php echo esc_attr( $name ) ?>"
350
+ <?php echo esc_html( $attr_disabled ) ?>
351
+ >
352
+ <?php foreach ( $args['select_options'] as $option_key => $option_name ) : ?>
353
+ <option
354
+ value="<?php echo esc_attr( $option_key ) ?>"
355
+ <?php echo selected( $option_key, $option_value ) ?>
356
+ <?php echo isset( $args['disable'] )
357
+ && gettype( $args['disable'] ) === 'array'
358
+ && in_array( $option_key, $args['disable'], true )
359
+ ? disabled()
360
+ : '';
361
+ ?>
362
+ >
363
+ <?php echo esc_html( $option_name ); ?>
364
+ </option>
365
+ <?php endforeach; ?>
366
+ </select>
367
+ <?php if ( $field_description ) : ?>
368
+ <p class="description">
369
+ <?php echo $field_description; ?>
370
+ </p>
371
+ <?php endif; ?>
372
+ <?php
373
+ break;
374
+
375
+ case 'textarea':
376
+ ?>
377
+ <textarea
378
+ name="<?php echo esc_attr( $name ) ?>"
379
+ id="<?php echo esc_attr( $id ) ?>"
380
+ <?php if ( $placeholder ) : ?>
381
+ placeholder="<?php echo esc_attr( $placeholder ); ?>"
382
+ <?php endif; ?>
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
393
+ break;
394
+
395
+ case 'text':
396
+ case 'password':
397
+ default:
398
+ ?>
399
+ <input
400
+ type="<?php echo esc_attr( $type ) ?>"
401
+ name="<?php echo esc_attr( $name ) ?>"
402
+ id="<?php echo esc_attr( $id ) ?>"
403
+ <?php if ( $placeholder ) : ?>
404
+ placeholder="<?php echo esc_attr( $placeholder ) ?>"
405
+ <?php endif; ?>
406
+ <?php echo esc_attr( $attr_disabled ) ?>
407
+ value="<?php echo esc_attr( $option_value ) ?>"
408
+ class="regular-text"
409
+ />
410
+ <?php if ( $field_description ) : ?>
411
+ <p class="description">
412
+ <?php echo $field_description; ?>
413
+ </p>
414
+ <?php endif; ?>
415
+ <?php
416
+ break;
417
+ }
418
+ }
419
+
420
+ /**
421
+ * Intercepts the form data for an individual option on its way to the server.
422
+ * Receives one argument containing the payload data and passes it along to
423
+ * the child's own sanitation method. Returns an encoded payload for it
424
+ * to continue its way to the server.
425
+ *
426
+ * @param array $payload map of fields and their values.
427
+ * @return string encoded json with fields.
428
+ * @since 0.5
429
+ */
430
+ public function universal_sanitize_and_encode_handler( $payload ) {
431
+ // Handle empty payload.
432
+ if ( ! is_array( $payload ) ) {
433
+ $payload = array();
434
+ }
435
+
436
+ // Remove any fields which could have been injected into the payload client-side.
437
+ $allowed_payload = array_intersect_key( $payload, static::$fields );
438
+ $allowed_payload = $payload;
439
+
440
+ // Pass the value along to the Child class's method to perform sanitation on its fields.
441
+ $sanitized_payload = static::sanitize_option_fields( $allowed_payload );
442
+
443
+ // Encode the payload into JSON before it's sent off to be saved.
444
+ return wp_json_encode( $sanitized_payload );
445
+ }
446
+
447
+ /**
448
+ * "Pass through" function. This should be overridden in child classes which
449
+ * are responsible for sanitizing its own $field_values.
450
+ *
451
+ * @param array $field_values array of values for fields.
452
+ * @since 0.5
453
+ */
454
+ public function sanitize_option_fields( $field_values ) {
455
+ return $field_values;
456
+ }
457
+ }
settings/class-instant-articles-settings-fb-page.php ADDED
@@ -0,0 +1,194 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Facebook Instant Articles for WP.
4
+ * This source code is licensed under the license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @package default
8
+ */
9
+
10
+ /**
11
+ * Class responsible for functionality and rendering of the settings
12
+ *
13
+ * @since 0.4
14
+ */
15
+ class Instant_Articles_Settings_FB_Page {
16
+
17
+ /**
18
+ * Facebook Permissions.
19
+ *
20
+ * @var array $fb_app_permissions The permissions asked for FB user to list pages he manages.
21
+ */
22
+ public static $fb_app_permissions = array( 'pages_manage_instant_articles', 'pages_show_list' );
23
+
24
+ /**
25
+ * SDK instance.
26
+ *
27
+ * @var Facebook $fb_sdk the instance reference to FB sdk
28
+ */
29
+ public $fb_sdk;
30
+
31
+ /**
32
+ * Settings structure.
33
+ *
34
+ * @var array $fb_app_settings The map data structure to store settings.
35
+ */
36
+ protected $fb_app_settings;
37
+
38
+ /**
39
+ * Constructor for Settings page.
40
+ *
41
+ * @since 0.4
42
+ */
43
+ public function __construct() {
44
+ $this->fb_app_settings = Instant_Articles_Option_FB_App::get_option_decoded();
45
+
46
+ if ( isset( $this->fb_app_settings['app_id'] ) && isset( $this->fb_app_settings['app_secret'] ) ) {
47
+ $app_id = $this->fb_app_settings['app_id'];
48
+ $app_secret = $this->fb_app_settings['app_secret'];
49
+ }
50
+
51
+ if ( ! empty( $app_id ) && ! empty( $app_secret ) ) {
52
+ $this->fb_sdk = new Facebook\Facebook(array(
53
+ 'app_id' => $app_id,
54
+ 'app_secret' => $app_secret,
55
+ 'default_graph_version' => 'v2.2',
56
+ ));
57
+
58
+ $this->render_settings_page_scripts();
59
+ }
60
+ }
61
+
62
+ /**
63
+ * Gets the login url scaped.
64
+ *
65
+ * @since 0.4
66
+ */
67
+ public function get_escaped_login_url() {
68
+ if ( isset( $this->fb_sdk ) ) {
69
+ $helper = $this->fb_sdk->getRedirectLoginHelper();
70
+
71
+ $login_url = $helper->getLoginUrl(
72
+ Instant_Articles_Settings::get_href_to_settings_page(),
73
+ self::$fb_app_permissions
74
+ );
75
+
76
+ return htmlspecialchars( $login_url );
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Retrieves granted permissions.
82
+ *
83
+ * @param string $access_token The user access token.
84
+ * @since 0.5
85
+ */
86
+ public function get_fb_permissions( $access_token ) {
87
+
88
+ $permissions = array();
89
+
90
+ if ( isset( $this->fb_sdk ) && $access_token ) {
91
+
92
+ try {
93
+ $permissions_query = $this->fb_sdk->get( '/me/permissions', $access_token );
94
+ $decoded_permissions = $permissions_query->getDecodedBody();
95
+ if ( isset( $decoded_permissions['data'] ) ) {
96
+ foreach ( $decoded_permissions['data'] as $permission ) {
97
+ if ( 'granted' === $permission['status'] ) {
98
+ $permissions[ $permission['permission'] ] = 'granted';
99
+ }
100
+ }
101
+ }
102
+ } catch (Facebook\Exceptions\FacebookResponseException $e) {
103
+ // When Graph returns an error.
104
+ Logger::getLogger( 'instantarticles-wp-plugin' )->error(
105
+ 'Graph returned an error: '.$e->getMessage(),
106
+ $e->getTraceAsString()
107
+ );
108
+
109
+ } catch (Facebook\Exceptions\FacebookSDKException $e) {
110
+ // When validation fails or other local issues.
111
+ Logger::getLogger( 'instantarticles-wp-plugin' )->error(
112
+ 'Facebook SDK returned an error: '.$e->getMessage(),
113
+ $e->getTraceAsString()
114
+ );
115
+
116
+ }
117
+ }
118
+
119
+ if ( isset( $permissions ) ) {
120
+ // Logged in.
121
+ return $permissions;
122
+ }
123
+ }
124
+
125
+ /**
126
+ * Retrieves Facebook access token.
127
+ *
128
+ * @since 0.4
129
+ */
130
+ public function get_fb_access_token() {
131
+ $access_token = null;
132
+
133
+ if ( isset( $this->fb_sdk ) ) {
134
+ $js_helper = $this->fb_sdk->getJavaScriptHelper();
135
+
136
+ try {
137
+ $access_token = $js_helper->getAccessToken();
138
+
139
+ } catch (Facebook\Exceptions\FacebookResponseException $e) {
140
+ // When Graph returns an error.
141
+ Logger::getLogger( 'instantarticles-wp-plugin' )->error(
142
+ 'Graph returned an error: '.$e->getMessage(),
143
+ $e->getTraceAsString()
144
+ );
145
+
146
+ } catch (Facebook\Exceptions\FacebookSDKException $e) {
147
+ // When validation fails or other local issues.
148
+ Logger::getLogger( 'instantarticles-wp-plugin' )->error(
149
+ 'Facebook SDK returned an error: '.$e->getMessage(),
150
+ $e->getTraceAsString()
151
+ );
152
+ }
153
+ }
154
+
155
+ if ( null !== $access_token ) {
156
+ // Logged in.
157
+ return $access_token;
158
+ }
159
+ }
160
+
161
+ /**
162
+ * Render the page scripts.
163
+ *
164
+ * @since 0.4
165
+ */
166
+ public function render_settings_page_scripts() {
167
+ $app_id = $this->fb_app_settings['app_id'];
168
+
169
+ ?>
170
+ <script>
171
+ window.fbAsyncInit = function() {
172
+ FB.init({
173
+ appId : <?php echo esc_html( $app_id ); ?>,
174
+ xfbml : true,
175
+ version : "v2.5",
176
+ cookie : true
177
+ });
178
+ };
179
+
180
+ (function(d, s, id){
181
+ var js, fjs = d.getElementsByTagName(s)[0];
182
+ if (d.getElementById(id)) {return;}
183
+ js = d.createElement(s); js.id = id;
184
+ js.src = "//connect.facebook.net/en_US/sdk.js";
185
+ fjs.parentNode.insertBefore(js, fjs);
186
+ }(document, "script", "facebook-jssdk"));
187
+
188
+ function loginCallback(response) {
189
+ location.reload();
190
+ }
191
+ </script>
192
+ <?php
193
+ }
194
+ }
settings/class-instant-articles-settings-wizard.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Facebook Instant Articles for WP.
4
+ * This source code is licensed under the license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @package default
8
+ */
9
+
10
+ /**
11
+ * Class responsible for functionality and rendering of the Setup Wizard
12
+ *
13
+ * @since 0.5
14
+ */
15
+ class Instant_Articles_Settings_Wizard {
16
+
17
+ const STEP_ID_APP_SETUP = 'app-setup';
18
+ const STEP_ID_PAGE_SELECTION = 'page-selection';
19
+ const STEP_ID_DONE = 'done';
20
+
21
+ /**
22
+ * Wizard steps.
23
+ *
24
+ * @var array $steps The steps for wizard
25
+ */
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
+ /**
33
+ * Returns the current step for the wizard.
34
+ *
35
+ * @since 0.5
36
+ */
37
+ public static function get_current_step_id() {
38
+
39
+ $fb_page_settings = Instant_Articles_Option_FB_Page::get_option_decoded();
40
+ $fb_app_settings = Instant_Articles_Option_FB_App::get_option_decoded();
41
+
42
+ if ( empty( $fb_app_settings['app_id'] ) || empty( $fb_app_settings['app_secret'] ) ) {
43
+ return self::STEP_ID_APP_SETUP;
44
+ } elseif ( empty( $fb_page_settings['page_id'] ) || empty( $fb_page_settings['page_name'] ) ) {
45
+ return self::STEP_ID_PAGE_SELECTION;
46
+ } else {
47
+ return self::STEP_ID_DONE;
48
+ }
49
+ }
50
+ }
settings/class-instant-articles-settings.php ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Facebook Instant Articles for WP.
4
+ * This source code is licensed under the license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @package default
8
+ */
9
+
10
+ require_once( dirname( __FILE__ ) . '/class-instant-articles-option-fb-page.php' );
11
+ require_once( dirname( __FILE__ ) . '/class-instant-articles-option-fb-app.php' );
12
+ require_once( dirname( __FILE__ ) . '/class-instant-articles-option-ads.php' );
13
+ require_once( dirname( __FILE__ ) . '/class-instant-articles-option-styles.php' );
14
+ require_once( dirname( __FILE__ ) . '/class-instant-articles-option-analytics.php' );
15
+ require_once( dirname( __FILE__ ) . '/class-instant-articles-option-publishing.php' );
16
+
17
+ require_once( dirname( __FILE__ ) . '/class-instant-articles-settings-wizard.php' );
18
+ require_once( dirname( __FILE__ ) . '/class-instant-articles-settings-fb-page.php' );
19
+
20
+ /**
21
+ * Class responsible for functionality and rendering of the settings.
22
+ *
23
+ * @since 0.4
24
+ */
25
+ class Instant_Articles_Settings {
26
+
27
+ const IA_PLUGIN_SETTINGS_SLUG = 'instant-articles-settings';
28
+
29
+ /**
30
+ * Initiator.
31
+ *
32
+ * @since 0.4
33
+ */
34
+ public static function init() {
35
+ add_action( 'admin_menu', array( 'Instant_Articles_Settings', 'menu_items' ) );
36
+
37
+ add_filter( 'plugin_action_links_' . IA_PLUGIN_PATH, array( 'Instant_Articles_Settings', 'add_settings_link_to_plugin_actions' ) );
38
+
39
+ add_action( 'admin_init', function () {
40
+ new Instant_Articles_Option_FB_App();
41
+ new Instant_Articles_Option_FB_Page();
42
+ new Instant_Articles_Option_Styles();
43
+ new Instant_Articles_Option_Ads();
44
+ new Instant_Articles_Option_Analytics();
45
+ new Instant_Articles_Option_Publishing();
46
+ });
47
+
48
+ }
49
+
50
+ /**
51
+ * Gets the URL/path for this page.
52
+ *
53
+ * @since 0.4
54
+ */
55
+ public static function get_href_to_settings_page() {
56
+ return menu_page_url( self::IA_PLUGIN_SETTINGS_SLUG, false );
57
+ }
58
+
59
+ /**
60
+ * Creates an anchor element.
61
+ *
62
+ * @param array $links The links will be added to anchor.
63
+ * @since 0.4
64
+ */
65
+ public static function add_settings_link_to_plugin_actions( $links ) {
66
+ $link_text = __( 'Settings' );
67
+ $settings_href = self::get_href_to_settings_page();
68
+ $settings_link = '<a href="' . esc_url( $settings_href ) . '">' . $link_text . '</a>';
69
+ array_push( $links, $settings_link );
70
+ return $links;
71
+ }
72
+
73
+ /**
74
+ * Creates the menu items for FB Instant Article in WordPress side menu.
75
+ *
76
+ * @since 0.4
77
+ */
78
+ public static function menu_items() {
79
+ add_menu_page(
80
+ 'Instant Articles Settings',
81
+ 'Instant Articles',
82
+ 'manage_options',
83
+ self::IA_PLUGIN_SETTINGS_SLUG,
84
+ array( 'Instant_Articles_Settings', 'render_settings_page' )
85
+ ,'dashicons-facebook'
86
+ );
87
+ }
88
+
89
+ /**
90
+ * Optains the state for current step from state-machine.
91
+ *
92
+ * @param int $step_id The step identifier.
93
+ * @since 0.4
94
+ */
95
+ public static function get_state_for_wizard_step( $step_id ) {
96
+ $fb_page_settings = Instant_Articles_Option_FB_Page::get_option_decoded();
97
+
98
+ switch ( $step_id ) {
99
+ case 'app-id':
100
+ if ( isset( $fb_page_settings['app_id'] ) && isset( $fb_page_settings['app_secret'] ) ) {
101
+ return '';
102
+ } else {
103
+ return 'current';
104
+ }
105
+ break;
106
+
107
+ case 'page-id':
108
+ if ( isset( $fb_page_settings['page_id'] ) && isset( $fb_page_settings['page_access_token'] ) ) {
109
+ return '';
110
+ } else {
111
+ return 'current';
112
+ }
113
+ break;
114
+
115
+ default:
116
+ # code...
117
+ break;
118
+ }
119
+ }
120
+
121
+ /**
122
+ *
123
+ *
124
+ * @since 0.4
125
+ */
126
+ public static function render_settings_page() {
127
+ if ( ! current_user_can( 'manage_options' ) ) {
128
+ wp_die( esc_html( 'You do not have sufficient permissions to access this page.' ) );
129
+ }
130
+
131
+ settings_errors();
132
+
133
+ $fb_page_settings = Instant_Articles_Option_FB_Page::get_option_decoded();
134
+ $fb_app_settings = Instant_Articles_Option_FB_App::get_option_decoded();
135
+
136
+ if ( isset( $fb_page_settings['page_id'] ) && ! empty( $fb_page_settings['page_id'] ) ) {
137
+
138
+ $claim_url_href = add_query_arg(
139
+ array(
140
+ 'section' => 'claim-url',
141
+ 'url-placeholder' => wp_parse_url( site_url(), PHP_URL_HOST ),
142
+ ),
143
+ 'https://www.facebook.com/' . $fb_page_settings['page_id'] . '/settings/?tab=instant_articles'
144
+ );
145
+
146
+ }
147
+
148
+ if ( filter_input( INPUT_GET, 'current_tab' ) ) {
149
+ $tab = filter_input( INPUT_GET, 'current_tab' );
150
+ } else {
151
+ $tab = 'basic';
152
+ }
153
+
154
+ $settings_page_href = self::get_href_to_settings_page();
155
+
156
+ include( dirname( __FILE__ ) . '/template-settings.php' );
157
+ }
158
+ }
settings/template-settings-advanced.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Facebook Instant Articles for WP.
4
+ * This source code is licensed under the license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @package default
8
+ */
9
+
10
+ ?>
11
+ <form method="post" action="options.php">
12
+ <?php settings_fields( Instant_Articles_Option::PAGE_OPTION_GROUP ); ?>
13
+
14
+ <p>Configure settings for your styles, ads, analytics and publishing in Instant Articles. Review our <a href="https://developers.facebook.com/docs/instant-articles" target="_blank">developer documentation</a> to learn more.</p>
15
+ <hr />
16
+ <?php do_settings_sections( Instant_Articles_Option_Styles::OPTION_KEY ); ?>
17
+ <hr />
18
+ <?php do_settings_sections( Instant_Articles_Option_Ads::OPTION_KEY ); ?>
19
+ <hr />
20
+ <?php do_settings_sections( Instant_Articles_Option_Analytics::OPTION_KEY ); ?>
21
+ <hr />
22
+ <?php do_settings_sections( Instant_Articles_Option_Publishing::OPTION_KEY ); ?>
23
+ <hr />
24
+ <?php submit_button( __( 'Save changes' ) ); ?>
25
+ </form>
settings/template-settings-info.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Facebook Instant Articles for WP.
4
+ * This source code is licensed under the license found in the
5
+ * LICENSE file in the root directory of this source tree.
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(site_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 absint( $fb_page_settings['page_id'] ); ?>/settings/?tab=instant_articles" target="_blank">here</a>.
20
+ <?php endif; ?>
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 and <a href="" target="_blank">sign up here</a>.
24
+ <li>[Optional] Set up your ads and analytics, including Audience Network, in the Configuration area, below.
25
+ <?php if ( isset( $fb_page_settings['page_id'] ) && ! empty ( $fb_page_settings['page_id'] ) ) : ?>
26
+ <li>
27
+ <a
28
+ href="https://www.facebook.com/<?php echo absint( $fb_page_settings['page_id'] ); ?>/settings/?tab=instant_articles" target="_blank">Submit your articles for review</a>.
29
+ </li>
30
+ <?php else : ?>
31
+ <li>Submit your articles for review.</li>
32
+ <?php endif; ?>
33
+
34
+ </ol>
35
+
36
+ <p>Other Resources:</p>
37
+ <ol>
38
+ <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.
39
+ <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.
40
+ <?php if ( isset( $fb_page_settings['page_id'] ) && ! empty ( $fb_page_settings['page_id'] ) ) : ?>
41
+ <li>
42
+ To give other members of your team access to your Instant Articles
43
+ <a
44
+ href="https://www.facebook.com/<?php echo absint( $fb_page_settings['page_id'] ); ?>/settings/?tab=instant_articles" target="_blank">tools</a>
45
+ on your Facebook Page, assign them Page roles
46
+ <a
47
+ href="https://www.facebook.com/<?php echo absint( $fb_page_settings['page_id'] ); ?>/settings/?tab=admin_roles" target="_blank">here</a>.
48
+ </li>
49
+ <?php else : ?>
50
+ <li>To give other members of your team access to your Instant Articles tools on your Facebook Page, assign them Page roles.
51
+ <?php endif; ?>
52
+
53
+ </ol>
settings/template-settings-wizard.php ADDED
@@ -0,0 +1,216 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Facebook Instant Articles for WP.
4
+ * This source code is licensed under the license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
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
+
14
+ <form class="instant-articles-inline-form" method="post" action="options.php">
15
+ <p>
16
+ Your App is
17
+ <a
18
+ href="http://developers.facebook.com/apps/<?php echo absint( $fb_app_settings['app_id'] ); ?>"
19
+ target="_blank"><?php
20
+ echo absint( $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
+
28
+ <form class="instant-articles-inline-form" method="post" action="options.php">
29
+ <p>
30
+ Your page is
31
+ <a
32
+ href="http://facebook.com/<?php echo absint( $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
+
44
+ <?php elseif ( Instant_Articles_Settings_Wizard::get_current_step_id() === 'app-setup' ) : ?>
45
+
46
+ <form method="post" action="options.php">
47
+ <?php settings_fields( Instant_Articles_Option::PAGE_OPTION_GROUP_WIZARD ); ?>
48
+
49
+ <p>
50
+ You need a Facebook App to publish Instant Articles using this plugin. If you already have one, input the App ID and App Secret below, which you can find by clicking on your app <a href="https://developers.facebook.com/apps" target="_blank">here</a>. If you don't, create one <a href="https://developers.facebook.com/apps" target="_blank">here</a> before continuing.
51
+ </p>
52
+
53
+ <?php do_settings_sections( Instant_Articles_Option_FB_App::OPTION_KEY ); ?>
54
+
55
+ <?php submit_button( __( 'Next' ) ); ?>
56
+ </form>
57
+
58
+ <?php elseif ( Instant_Articles_Settings_Wizard::get_current_step_id() === 'page-selection' ) : ?>
59
+
60
+ <form class="instant-articles-inline-form" method="post" action="options.php">
61
+ <p>
62
+ Your App is
63
+ <a
64
+ href="http://developers.facebook.com/apps/<?php echo absint( $fb_app_settings['app_id'] ); ?>"
65
+ target="_blank"><?php
66
+ echo absint( $fb_app_settings['app_id'] );
67
+ ?></a>.
68
+
69
+ <?php settings_fields( Instant_Articles_Option::PAGE_OPTION_GROUP_WIZARD ); ?>
70
+ <?php submit_button( __( 'Update' ), 'default', 'submit', false ); ?>
71
+ </p>
72
+ </form>
73
+
74
+ <hr>
75
+
76
+ <form method="post" action="options.php">
77
+ <?php settings_fields( Instant_Articles_Option::PAGE_OPTION_GROUP_WIZARD ); ?>
78
+ <?php do_settings_sections( Instant_Articles_Option_FB_Page::OPTION_KEY ); ?>
79
+ <div style="display: none">
80
+ <?php do_settings_sections( Instant_Articles_Option_FB_App::OPTION_KEY ); ?>
81
+ </div>
82
+
83
+ <?php
84
+ $fb_helper = new Instant_Articles_Settings_FB_Page();
85
+ $access_token = $fb_helper->get_fb_access_token();
86
+ $permissions = $fb_helper->get_fb_permissions( $access_token );
87
+ ?>
88
+
89
+ <?php if ( ! $access_token ) : ?>
90
+
91
+ <script>
92
+ function instant_articles_login_callback(response) {
93
+ if (response.status === 'connected') {
94
+ location.reload();
95
+ //probably good to do an ajax call to a login_callback page
96
+ } else if (response.status === 'not_authorized') {
97
+ // The person is logged into Facebook, but not your app.
98
+ } else {
99
+ // The person is not logged into Facebook, so we're not sure if
100
+ // they are logged into this app or not.
101
+ }
102
+ }
103
+ </script>
104
+
105
+ <p>Login to Facebook and select the Facebook Page where you will publish Instant Articles.</p>
106
+
107
+ <div
108
+ class="fb-login-button"
109
+ data-size="large"
110
+ data-scope="<?php
111
+ echo esc_html(
112
+ implode( Instant_Articles_Settings_FB_Page::$fb_app_permissions, ',' )
113
+ );
114
+ ?>"
115
+ onlogin="instant_articles_login_callback">
116
+ Login with Facebook
117
+ </div>
118
+
119
+ <?php
120
+ elseif (
121
+ ( ! isset( $permissions['pages_manage_instant_articles'] ) ) ||
122
+ ( ! isset( $permissions['pages_show_list'] ) )
123
+ ) :
124
+ ?>
125
+
126
+ <script>
127
+ //*
128
+ function instant_articles_login_callback(response) {
129
+ if (response.status === 'connected') {
130
+ location.reload();
131
+ //probably good to do an ajax call to a login_callback page
132
+ } else if (response.status === 'not_authorized') {
133
+ // The person is logged into Facebook, but not your app.
134
+ } else {
135
+ // The person is not logged into Facebook, so we're not sure if
136
+ // they are logged into this app or not.
137
+ }
138
+ }
139
+ //*/
140
+ </script>
141
+
142
+ <p>In order to finish the activation, you need to grant all the requested permissions:</p>
143
+ <ul>
144
+ <?php if ( ! isset( $permissions['pages_show_list'] ) ) : ?>
145
+ <li>
146
+ <b>Show a list of the Pages you manage</b>: allows the plugin to show the list of your
147
+ pages for you to select one.
148
+ </li>
149
+ <?php endif; ?>
150
+ <?php if ( ! isset( $permissions['pages_manage_instant_articles'] ) ) : ?>
151
+ <li>
152
+ <b>Manage Instant Articles for your Pages</b>: allows us to publish
153
+ Instant Articles to your selected page.
154
+ </li>
155
+ <?php endif; ?>
156
+ </p>
157
+
158
+ <p>Please grant the needed permissions to continue:</p>
159
+
160
+ <div
161
+ class="fb-login-button"
162
+ data-size="large"
163
+ data-scope="<?php
164
+ echo esc_attr(
165
+ implode( Instant_Articles_Settings_FB_Page::$fb_app_permissions, ',' )
166
+ );
167
+ ?>"
168
+ onlogin="instant_articles_login_callback">
169
+ Login with Facebook
170
+ </div>
171
+
172
+ <?php else : ?>
173
+
174
+ <?php
175
+ $helper = new Facebook\InstantArticles\Client\Helper(
176
+ $fb_helper->fb_sdk
177
+ );
178
+
179
+ $fb_page_settings = Instant_Articles_Option_FB_Page::get_option_decoded();
180
+
181
+ // Map GraphNode objects to simple value objects that are smaller when serialized.
182
+ $pages_and_tokens = array_map(function( $page_node ) {
183
+ return (object) array(
184
+ 'page_id' => $page_node->getField( 'id' ),
185
+ 'page_name' => $page_node->getField( 'name' ),
186
+ 'page_access_token' => $page_node->getField( 'access_token' ),
187
+ 'supports_instant_articles' => $page_node->getField( 'supports_instant_articles' )
188
+ );
189
+ }, $helper->getPagesAndTokens( $access_token )->all() );
190
+
191
+ $pages_and_tokens = array_filter( $pages_and_tokens, function ( $page ) {
192
+ return $page->supports_instant_articles;
193
+ } );
194
+ ?>
195
+
196
+ <?php if ( ! empty ( $pages_and_tokens ) ) : ?>
197
+ <p>Select the Facebook Pages where you will publish Instant Articles:</p>
198
+
199
+ <select id="<?php echo esc_attr( 'instant-articles-fb-page-selector' ) ?>">
200
+ <option value="" disabled selected>Select Page</option>
201
+ <?php foreach ( $pages_and_tokens as $page ) : ?>
202
+ <option value="<?php echo esc_attr( json_encode( $page ) ) ?>">
203
+ <?php echo esc_html( $page->page_name ) ?>
204
+ </option>
205
+ <?php endforeach; ?>
206
+ </select>
207
+ <?php submit_button( 'Next', 'primary', 'instant-articles-select-page', true ); ?>
208
+ <?php else : ?>
209
+ <p>Sorry, you have no Pages signed up for Instant Articles.</p>
210
+ <p><a href="https://www.facebook.com/instant_articles/signup" target="_blank">Sign up</a> for Instant Articles and refresh this page to continue.</p>
211
+ <?php endif; ?>
212
+
213
+ <?php endif; ?>
214
+ </form>
215
+
216
+ <?php endif;
settings/template-settings.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Facebook Instant Articles for WP.
4
+ * This source code is licensed under the license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @package default
8
+ */
9
+
10
+ ?>
11
+ <div class="wrap">
12
+ <h1>Facebook Instant Articles Settings</h1>
13
+ <div id="instant-articles-settings-basic" class="instant-articles-settings-box">
14
+ <h2 class="dashicons-before dashicons-arrow-down"> Plugin Activation</h2>
15
+ <div class="inside">
16
+ <?php include( dirname( __FILE__ ) . '/template-settings-wizard.php' ); ?>
17
+ </div>
18
+ </div>
19
+
20
+ <div id="instant-articles-settings-info" class="instant-articles-settings-box">
21
+ <h2 class="dashicons-before dashicons-arrow-down"> Instant Articles Configuration</h2>
22
+ <div class="inside">
23
+ <?php include( dirname( __FILE__ ) . '/template-settings-info.php' ); ?>
24
+ </div>
25
+ </div>
26
+
27
+ <div id="instant-articles-settings-advanced" class="instant-articles-settings-box">
28
+ <h2 class="dashicons-before dashicons-arrow-down"> Plugin Configuration</h2>
29
+ <div class="inside">
30
+ <?php include( dirname( __FILE__ ) . '/template-settings-advanced.php' ); ?>
31
+ </div>
32
+ </div>
33
+ </div>
vendor/apache/log4php ADDED
@@ -0,0 +1 @@
 
1
+ Subproject commit cac428b6f67d2035af39784da1d1a299ef42fcf2
vendor/autoload.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload.php @generated by Composer
4
+
5
+ require_once __DIR__ . '/composer' . '/autoload_real.php';
6
+
7
+ return ComposerAutoloaderInit3e565f617e78b30946ba0a1809aa93f8::getLoader();
vendor/composer/ClassLoader.php ADDED
@@ -0,0 +1,413 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Composer.
5
+ *
6
+ * (c) Nils Adermann <naderman@naderman.de>
7
+ * Jordi Boggiano <j.boggiano@seld.be>
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ namespace Composer\Autoload;
14
+
15
+ /**
16
+ * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
17
+ *
18
+ * $loader = new \Composer\Autoload\ClassLoader();
19
+ *
20
+ * // register classes with namespaces
21
+ * $loader->add('Symfony\Component', __DIR__.'/component');
22
+ * $loader->add('Symfony', __DIR__.'/framework');
23
+ *
24
+ * // activate the autoloader
25
+ * $loader->register();
26
+ *
27
+ * // to enable searching the include path (eg. for PEAR packages)
28
+ * $loader->setUseIncludePath(true);
29
+ *
30
+ * In this example, if you try to use a class in the Symfony\Component
31
+ * namespace or one of its children (Symfony\Component\Console for instance),
32
+ * the autoloader will first look for the class under the component/
33
+ * directory, and it will then fallback to the framework/ directory if not
34
+ * found before giving up.
35
+ *
36
+ * This class is loosely based on the Symfony UniversalClassLoader.
37
+ *
38
+ * @author Fabien Potencier <fabien@symfony.com>
39
+ * @author Jordi Boggiano <j.boggiano@seld.be>
40
+ * @see http://www.php-fig.org/psr/psr-0/
41
+ * @see http://www.php-fig.org/psr/psr-4/
42
+ */
43
+ class ClassLoader
44
+ {
45
+ // PSR-4
46
+ private $prefixLengthsPsr4 = array();
47
+ private $prefixDirsPsr4 = array();
48
+ private $fallbackDirsPsr4 = array();
49
+
50
+ // PSR-0
51
+ private $prefixesPsr0 = array();
52
+ private $fallbackDirsPsr0 = array();
53
+
54
+ private $useIncludePath = false;
55
+ private $classMap = array();
56
+
57
+ private $classMapAuthoritative = false;
58
+
59
+ public function getPrefixes()
60
+ {
61
+ if (!empty($this->prefixesPsr0)) {
62
+ return call_user_func_array('array_merge', $this->prefixesPsr0);
63
+ }
64
+
65
+ return array();
66
+ }
67
+
68
+ public function getPrefixesPsr4()
69
+ {
70
+ return $this->prefixDirsPsr4;
71
+ }
72
+
73
+ public function getFallbackDirs()
74
+ {
75
+ return $this->fallbackDirsPsr0;
76
+ }
77
+
78
+ public function getFallbackDirsPsr4()
79
+ {
80
+ return $this->fallbackDirsPsr4;
81
+ }
82
+
83
+ public function getClassMap()
84
+ {
85
+ return $this->classMap;
86
+ }
87
+
88
+ /**
89
+ * @param array $classMap Class to filename map
90
+ */
91
+ public function addClassMap(array $classMap)
92
+ {
93
+ if ($this->classMap) {
94
+ $this->classMap = array_merge($this->classMap, $classMap);
95
+ } else {
96
+ $this->classMap = $classMap;
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Registers a set of PSR-0 directories for a given prefix, either
102
+ * appending or prepending to the ones previously set for this prefix.
103
+ *
104
+ * @param string $prefix The prefix
105
+ * @param array|string $paths The PSR-0 root directories
106
+ * @param bool $prepend Whether to prepend the directories
107
+ */
108
+ public function add($prefix, $paths, $prepend = false)
109
+ {
110
+ if (!$prefix) {
111
+ if ($prepend) {
112
+ $this->fallbackDirsPsr0 = array_merge(
113
+ (array) $paths,
114
+ $this->fallbackDirsPsr0
115
+ );
116
+ } else {
117
+ $this->fallbackDirsPsr0 = array_merge(
118
+ $this->fallbackDirsPsr0,
119
+ (array) $paths
120
+ );
121
+ }
122
+
123
+ return;
124
+ }
125
+
126
+ $first = $prefix[0];
127
+ if (!isset($this->prefixesPsr0[$first][$prefix])) {
128
+ $this->prefixesPsr0[$first][$prefix] = (array) $paths;
129
+
130
+ return;
131
+ }
132
+ if ($prepend) {
133
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
134
+ (array) $paths,
135
+ $this->prefixesPsr0[$first][$prefix]
136
+ );
137
+ } else {
138
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
139
+ $this->prefixesPsr0[$first][$prefix],
140
+ (array) $paths
141
+ );
142
+ }
143
+ }
144
+
145
+ /**
146
+ * Registers a set of PSR-4 directories for a given namespace, either
147
+ * appending or prepending to the ones previously set for this namespace.
148
+ *
149
+ * @param string $prefix The prefix/namespace, with trailing '\\'
150
+ * @param array|string $paths The PSR-4 base directories
151
+ * @param bool $prepend Whether to prepend the directories
152
+ *
153
+ * @throws \InvalidArgumentException
154
+ */
155
+ public function addPsr4($prefix, $paths, $prepend = false)
156
+ {
157
+ if (!$prefix) {
158
+ // Register directories for the root namespace.
159
+ if ($prepend) {
160
+ $this->fallbackDirsPsr4 = array_merge(
161
+ (array) $paths,
162
+ $this->fallbackDirsPsr4
163
+ );
164
+ } else {
165
+ $this->fallbackDirsPsr4 = array_merge(
166
+ $this->fallbackDirsPsr4,
167
+ (array) $paths
168
+ );
169
+ }
170
+ } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
171
+ // Register directories for a new namespace.
172
+ $length = strlen($prefix);
173
+ if ('\\' !== $prefix[$length - 1]) {
174
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
175
+ }
176
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
177
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
178
+ } elseif ($prepend) {
179
+ // Prepend directories for an already registered namespace.
180
+ $this->prefixDirsPsr4[$prefix] = array_merge(
181
+ (array) $paths,
182
+ $this->prefixDirsPsr4[$prefix]
183
+ );
184
+ } else {
185
+ // Append directories for an already registered namespace.
186
+ $this->prefixDirsPsr4[$prefix] = array_merge(
187
+ $this->prefixDirsPsr4[$prefix],
188
+ (array) $paths
189
+ );
190
+ }
191
+ }
192
+
193
+ /**
194
+ * Registers a set of PSR-0 directories for a given prefix,
195
+ * replacing any others previously set for this prefix.
196
+ *
197
+ * @param string $prefix The prefix
198
+ * @param array|string $paths The PSR-0 base directories
199
+ */
200
+ public function set($prefix, $paths)
201
+ {
202
+ if (!$prefix) {
203
+ $this->fallbackDirsPsr0 = (array) $paths;
204
+ } else {
205
+ $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Registers a set of PSR-4 directories for a given namespace,
211
+ * replacing any others previously set for this namespace.
212
+ *
213
+ * @param string $prefix The prefix/namespace, with trailing '\\'
214
+ * @param array|string $paths The PSR-4 base directories
215
+ *
216
+ * @throws \InvalidArgumentException
217
+ */
218
+ public function setPsr4($prefix, $paths)
219
+ {
220
+ if (!$prefix) {
221
+ $this->fallbackDirsPsr4 = (array) $paths;
222
+ } else {
223
+ $length = strlen($prefix);
224
+ if ('\\' !== $prefix[$length - 1]) {
225
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
226
+ }
227
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
228
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
229
+ }
230
+ }
231
+
232
+ /**
233
+ * Turns on searching the include path for class files.
234
+ *
235
+ * @param bool $useIncludePath
236
+ */
237
+ public function setUseIncludePath($useIncludePath)
238
+ {
239
+ $this->useIncludePath = $useIncludePath;
240
+ }
241
+
242
+ /**
243
+ * Can be used to check if the autoloader uses the include path to check
244
+ * for classes.
245
+ *
246
+ * @return bool
247
+ */
248
+ public function getUseIncludePath()
249
+ {
250
+ return $this->useIncludePath;
251
+ }
252
+
253
+ /**
254
+ * Turns off searching the prefix and fallback directories for classes
255
+ * that have not been registered with the class map.
256
+ *
257
+ * @param bool $classMapAuthoritative
258
+ */
259
+ public function setClassMapAuthoritative($classMapAuthoritative)
260
+ {
261
+ $this->classMapAuthoritative = $classMapAuthoritative;
262
+ }
263
+
264
+ /**
265
+ * Should class lookup fail if not found in the current class map?
266
+ *
267
+ * @return bool
268
+ */
269
+ public function isClassMapAuthoritative()
270
+ {
271
+ return $this->classMapAuthoritative;
272
+ }
273
+
274
+ /**
275
+ * Registers this instance as an autoloader.
276
+ *
277
+ * @param bool $prepend Whether to prepend the autoloader or not
278
+ */
279
+ public function register($prepend = false)
280
+ {
281
+ spl_autoload_register(array($this, 'loadClass'), true, $prepend);
282
+ }
283
+
284
+ /**
285
+ * Unregisters this instance as an autoloader.
286
+ */
287
+ public function unregister()
288
+ {
289
+ spl_autoload_unregister(array($this, 'loadClass'));
290
+ }
291
+
292
+ /**
293
+ * Loads the given class or interface.
294
+ *
295
+ * @param string $class The name of the class
296
+ * @return bool|null True if loaded, null otherwise
297
+ */
298
+ public function loadClass($class)
299
+ {
300
+ if ($file = $this->findFile($class)) {
301
+ includeFile($file);
302
+
303
+ return true;
304
+ }
305
+ }
306
+
307
+ /**
308
+ * Finds the path to the file where the class is defined.
309
+ *
310
+ * @param string $class The name of the class
311
+ *
312
+ * @return string|false The path if found, false otherwise
313
+ */
314
+ public function findFile($class)
315
+ {
316
+ // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
317
+ if ('\\' == $class[0]) {
318
+ $class = substr($class, 1);
319
+ }
320
+
321
+ // class map lookup
322
+ if (isset($this->classMap[$class])) {
323
+ return $this->classMap[$class];
324
+ }
325
+ if ($this->classMapAuthoritative) {
326
+ return false;
327
+ }
328
+
329
+ $file = $this->findFileWithExtension($class, '.php');
330
+
331
+ // Search for Hack files if we are running on HHVM
332
+ if ($file === null && defined('HHVM_VERSION')) {
333
+ $file = $this->findFileWithExtension($class, '.hh');
334
+ }
335
+
336
+ if ($file === null) {
337
+ // Remember that this class does not exist.
338
+ return $this->classMap[$class] = false;
339
+ }
340
+
341
+ return $file;
342
+ }
343
+
344
+ private function findFileWithExtension($class, $ext)
345
+ {
346
+ // PSR-4 lookup
347
+ $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
348
+
349
+ $first = $class[0];
350
+ if (isset($this->prefixLengthsPsr4[$first])) {
351
+ foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) {
352
+ if (0 === strpos($class, $prefix)) {
353
+ foreach ($this->prefixDirsPsr4[$prefix] as $dir) {
354
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
355
+ return $file;
356
+ }
357
+ }
358
+ }
359
+ }
360
+ }
361
+
362
+ // PSR-4 fallback dirs
363
+ foreach ($this->fallbackDirsPsr4 as $dir) {
364
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
365
+ return $file;
366
+ }
367
+ }
368
+
369
+ // PSR-0 lookup
370
+ if (false !== $pos = strrpos($class, '\\')) {
371
+ // namespaced class name
372
+ $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
373
+ . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
374
+ } else {
375
+ // PEAR-like class name
376
+ $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
377
+ }
378
+
379
+ if (isset($this->prefixesPsr0[$first])) {
380
+ foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
381
+ if (0 === strpos($class, $prefix)) {
382
+ foreach ($dirs as $dir) {
383
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
384
+ return $file;
385
+ }
386
+ }
387
+ }
388
+ }
389
+ }
390
+
391
+ // PSR-0 fallback dirs
392
+ foreach ($this->fallbackDirsPsr0 as $dir) {
393
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
394
+ return $file;
395
+ }
396
+ }
397
+
398
+ // PSR-0 include paths.
399
+ if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
400
+ return $file;
401
+ }
402
+ }
403
+ }
404
+
405
+ /**
406
+ * Scope isolated include.
407
+ *
408
+ * Prevents access to $this/self from included files.
409
+ */
410
+ function includeFile($file)
411
+ {
412
+ include $file;
413
+ }
vendor/composer/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ Copyright (c) 2015 Nils Adermann, Jordi Boggiano
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is furnished
9
+ to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ THE SOFTWARE.
21
+
vendor/composer/autoload_classmap.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_classmap.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ 'Logger' => $vendorDir . '/apache/log4php/src/main/php/Logger.php',
10
+ 'LoggerAppender' => $vendorDir . '/apache/log4php/src/main/php/LoggerAppender.php',
11
+ 'LoggerAppenderConsole' => $vendorDir . '/apache/log4php/src/main/php/appenders/LoggerAppenderConsole.php',
12
+ 'LoggerAppenderDailyFile' => $vendorDir . '/apache/log4php/src/main/php/appenders/LoggerAppenderDailyFile.php',
13
+ 'LoggerAppenderEcho' => $vendorDir . '/apache/log4php/src/main/php/appenders/LoggerAppenderEcho.php',
14
+ 'LoggerAppenderFile' => $vendorDir . '/apache/log4php/src/main/php/appenders/LoggerAppenderFile.php',
15
+ 'LoggerAppenderFirePHP' => $vendorDir . '/apache/log4php/src/main/php/appenders/LoggerAppenderFirePHP.php',
16
+ 'LoggerAppenderMail' => $vendorDir . '/apache/log4php/src/main/php/appenders/LoggerAppenderMail.php',
17
+ 'LoggerAppenderMailEvent' => $vendorDir . '/apache/log4php/src/main/php/appenders/LoggerAppenderMailEvent.php',
18
+ 'LoggerAppenderMongoDB' => $vendorDir . '/apache/log4php/src/main/php/appenders/LoggerAppenderMongoDB.php',
19
+ 'LoggerAppenderNull' => $vendorDir . '/apache/log4php/src/main/php/appenders/LoggerAppenderNull.php',
20
+ 'LoggerAppenderPDO' => $vendorDir . '/apache/log4php/src/main/php/appenders/LoggerAppenderPDO.php',
21
+ 'LoggerAppenderPhp' => $vendorDir . '/apache/log4php/src/main/php/appenders/LoggerAppenderPhp.php',
22
+ 'LoggerAppenderPool' => $vendorDir . '/apache/log4php/src/main/php/LoggerAppenderPool.php',
23
+ 'LoggerAppenderRollingFile' => $vendorDir . '/apache/log4php/src/main/php/appenders/LoggerAppenderRollingFile.php',
24
+ 'LoggerAppenderSocket' => $vendorDir . '/apache/log4php/src/main/php/appenders/LoggerAppenderSocket.php',
25
+ 'LoggerAppenderSyslog' => $vendorDir . '/apache/log4php/src/main/php/appenders/LoggerAppenderSyslog.php',
26
+ 'LoggerAutoloader' => $vendorDir . '/apache/log4php/src/main/php/LoggerAutoloader.php',
27
+ 'LoggerConfigurable' => $vendorDir . '/apache/log4php/src/main/php/LoggerConfigurable.php',
28
+ 'LoggerConfigurationAdapter' => $vendorDir . '/apache/log4php/src/main/php/configurators/LoggerConfigurationAdapter.php',
29
+ 'LoggerConfigurationAdapterINI' => $vendorDir . '/apache/log4php/src/main/php/configurators/LoggerConfigurationAdapterINI.php',
30
+ 'LoggerConfigurationAdapterPHP' => $vendorDir . '/apache/log4php/src/main/php/configurators/LoggerConfigurationAdapterPHP.php',
31
+ 'LoggerConfigurationAdapterXML' => $vendorDir . '/apache/log4php/src/main/php/configurators/LoggerConfigurationAdapterXML.php',
32
+ 'LoggerConfigurator' => $vendorDir . '/apache/log4php/src/main/php/LoggerConfigurator.php',
33
+ 'LoggerConfiguratorDefault' => $vendorDir . '/apache/log4php/src/main/php/configurators/LoggerConfiguratorDefault.php',
34
+ 'LoggerException' => $vendorDir . '/apache/log4php/src/main/php/LoggerException.php',
35
+ 'LoggerFilter' => $vendorDir . '/apache/log4php/src/main/php/LoggerFilter.php',
36
+ 'LoggerFilterDenyAll' => $vendorDir . '/apache/log4php/src/main/php/filters/LoggerFilterDenyAll.php',
37
+ 'LoggerFilterLevelMatch' => $vendorDir . '/apache/log4php/src/main/php/filters/LoggerFilterLevelMatch.php',
38
+ 'LoggerFilterLevelRange' => $vendorDir . '/apache/log4php/src/main/php/filters/LoggerFilterLevelRange.php',
39
+ 'LoggerFilterStringMatch' => $vendorDir . '/apache/log4php/src/main/php/filters/LoggerFilterStringMatch.php',
40
+ 'LoggerFormattingInfo' => $vendorDir . '/apache/log4php/src/main/php/helpers/LoggerFormattingInfo.php',
41
+ 'LoggerHierarchy' => $vendorDir . '/apache/log4php/src/main/php/LoggerHierarchy.php',
42
+ 'LoggerLayout' => $vendorDir . '/apache/log4php/src/main/php/LoggerLayout.php',
43
+ 'LoggerLayoutHtml' => $vendorDir . '/apache/log4php/src/main/php/layouts/LoggerLayoutHtml.php',
44
+ 'LoggerLayoutPattern' => $vendorDir . '/apache/log4php/src/main/php/layouts/LoggerLayoutPattern.php',
45
+ 'LoggerLayoutSerialized' => $vendorDir . '/apache/log4php/src/main/php/layouts/LoggerLayoutSerialized.php',
46
+ 'LoggerLayoutSimple' => $vendorDir . '/apache/log4php/src/main/php/layouts/LoggerLayoutSimple.php',
47
+ 'LoggerLayoutTTCC' => $vendorDir . '/apache/log4php/src/main/php/layouts/LoggerLayoutTTCC.php',
48
+ 'LoggerLayoutXml' => $vendorDir . '/apache/log4php/src/main/php/layouts/LoggerLayoutXml.php',
49
+ 'LoggerLevel' => $vendorDir . '/apache/log4php/src/main/php/LoggerLevel.php',
50
+ 'LoggerLocationInfo' => $vendorDir . '/apache/log4php/src/main/php/LoggerLocationInfo.php',
51
+ 'LoggerLoggingEvent' => $vendorDir . '/apache/log4php/src/main/php/LoggerLoggingEvent.php',
52
+ 'LoggerMDC' => $vendorDir . '/apache/log4php/src/main/php/LoggerMDC.php',
53
+ 'LoggerNDC' => $vendorDir . '/apache/log4php/src/main/php/LoggerNDC.php',
54
+ 'LoggerOptionConverter' => $vendorDir . '/apache/log4php/src/main/php/helpers/LoggerOptionConverter.php',
55
+ 'LoggerPatternConverter' => $vendorDir . '/apache/log4php/src/main/php/pattern/LoggerPatternConverter.php',
56
+ 'LoggerPatternConverterClass' => $vendorDir . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterClass.php',
57
+ 'LoggerPatternConverterCookie' => $vendorDir . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterCookie.php',
58
+ 'LoggerPatternConverterDate' => $vendorDir . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterDate.php',
59
+ 'LoggerPatternConverterEnvironment' => $vendorDir . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterEnvironment.php',
60
+ 'LoggerPatternConverterFile' => $vendorDir . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterFile.php',
61
+ 'LoggerPatternConverterLevel' => $vendorDir . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterLevel.php',
62
+ 'LoggerPatternConverterLine' => $vendorDir . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterLine.php',
63
+ 'LoggerPatternConverterLiteral' => $vendorDir . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterLiteral.php',
64
+ 'LoggerPatternConverterLocation' => $vendorDir . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterLocation.php',
65
+ 'LoggerPatternConverterLogger' => $vendorDir . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterLogger.php',
66
+ 'LoggerPatternConverterMDC' => $vendorDir . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterMDC.php',
67
+ 'LoggerPatternConverterMessage' => $vendorDir . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterMessage.php',
68
+ 'LoggerPatternConverterMethod' => $vendorDir . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterMethod.php',
69
+ 'LoggerPatternConverterNDC' => $vendorDir . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterNDC.php',
70
+ 'LoggerPatternConverterNewLine' => $vendorDir . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterNewLine.php',
71
+ 'LoggerPatternConverterProcess' => $vendorDir . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterProcess.php',
72
+ 'LoggerPatternConverterRelative' => $vendorDir . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterRelative.php',
73
+ 'LoggerPatternConverterRequest' => $vendorDir . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterRequest.php',
74
+ 'LoggerPatternConverterServer' => $vendorDir . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterServer.php',
75
+ 'LoggerPatternConverterSession' => $vendorDir . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterSession.php',
76
+ 'LoggerPatternConverterSessionID' => $vendorDir . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterSessionID.php',
77
+ 'LoggerPatternConverterSuperglobal' => $vendorDir . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterSuperglobal.php',
78
+ 'LoggerPatternConverterThrowable' => $vendorDir . '/apache/log4php/src/main/php/pattern/LoggerPatternConverterThrowable.php',
79
+ 'LoggerPatternParser' => $vendorDir . '/apache/log4php/src/main/php/helpers/LoggerPatternParser.php',
80
+ 'LoggerReflectionUtils' => $vendorDir . '/apache/log4php/src/main/php/LoggerReflectionUtils.php',
81
+ 'LoggerRenderer' => $vendorDir . '/apache/log4php/src/main/php/renderers/LoggerRenderer.php',
82
+ 'LoggerRendererDefault' => $vendorDir . '/apache/log4php/src/main/php/renderers/LoggerRendererDefault.php',
83
+ 'LoggerRendererException' => $vendorDir . '/apache/log4php/src/main/php/renderers/LoggerRendererException.php',
84
+ 'LoggerRendererMap' => $vendorDir . '/apache/log4php/src/main/php/renderers/LoggerRendererMap.php',
85
+ 'LoggerRoot' => $vendorDir . '/apache/log4php/src/main/php/LoggerRoot.php',
86
+ 'LoggerThrowableInformation' => $vendorDir . '/apache/log4php/src/main/php/LoggerThrowableInformation.php',
87
+ 'LoggerUtils' => $vendorDir . '/apache/log4php/src/main/php/helpers/LoggerUtils.php',
88
+ );
vendor/composer/autoload_namespaces.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_namespaces.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ );
vendor/composer/autoload_psr4.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_psr4.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ 'Symfony\\Component\\CssSelector\\' => array($vendorDir . '/symfony/css-selector'),
10
+ 'Facebook\\InstantArticles\\' => array($vendorDir . '/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles'),
11
+ 'Facebook\\' => array($vendorDir . '/facebook/php-sdk-v4/src/Facebook'),
12
+ );
vendor/composer/autoload_real.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_real.php @generated by Composer
4
+
5
+ class ComposerAutoloaderInit3e565f617e78b30946ba0a1809aa93f8
6
+ {
7
+ private static $loader;
8
+
9
+ public static function loadClassLoader($class)
10
+ {
11
+ if ('Composer\Autoload\ClassLoader' === $class) {
12
+ require __DIR__ . '/ClassLoader.php';
13
+ }
14
+ }
15
+
16
+ public static function getLoader()
17
+ {
18
+ if (null !== self::$loader) {
19
+ return self::$loader;
20
+ }
21
+
22
+ spl_autoload_register(array('ComposerAutoloaderInit3e565f617e78b30946ba0a1809aa93f8', 'loadClassLoader'), true, true);
23
+ self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit3e565f617e78b30946ba0a1809aa93f8', '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
+ }
vendor/composer/installed.json ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "name": "apache/log4php",
4
+ "version": "2.3.0",
5
+ "version_normalized": "2.3.0.0",
6
+ "source": {
7
+ "type": "git",
8
+ "url": "https://git-wip-us.apache.org/repos/asf/logging-log4php.git",
9
+ "reference": "8c6df2481cd68d0d211d38f700406c5f0a9de0c2"
10
+ },
11
+ "require": {
12
+ "php": ">=5.2.7"
13
+ },
14
+ "time": "2012-10-26 09:13:25",
15
+ "type": "library",
16
+ "installation-source": "source",
17
+ "autoload": {
18
+ "classmap": [
19
+ "src/main/php/"
20
+ ]
21
+ },
22
+ "notification-url": "https://packagist.org/downloads/",
23
+ "license": [
24
+ "Apache-2.0"
25
+ ],
26
+ "description": "A versatile logging framework for PHP",
27
+ "homepage": "http://logging.apache.org/log4php/",
28
+ "keywords": [
29
+ "log",
30
+ "logging",
31
+ "php"
32
+ ]
33
+ },
34
+ {
35
+ "name": "facebook/php-sdk-v4",
36
+ "version": "5.1.2",
37
+ "version_normalized": "5.1.2.0",
38
+ "source": {
39
+ "type": "git",
40
+ "url": "https://github.com/facebook/facebook-php-sdk-v4.git",
41
+ "reference": "2c42fb3002953355f12d3c6e8003a9fd5af563d9"
42
+ },
43
+ "dist": {
44
+ "type": "zip",
45
+ "url": "https://api.github.com/repos/facebook/facebook-php-sdk-v4/zipball/2c42fb3002953355f12d3c6e8003a9fd5af563d9",
46
+ "reference": "2c42fb3002953355f12d3c6e8003a9fd5af563d9",
47
+ "shasum": ""
48
+ },
49
+ "require": {
50
+ "ext-mbstring": "*",
51
+ "php": ">=5.4.0"
52
+ },
53
+ "require-dev": {
54
+ "guzzlehttp/guzzle": "~5.0",
55
+ "mockery/mockery": "~0.8",
56
+ "phpunit/phpunit": "~4.0"
57
+ },
58
+ "suggest": {
59
+ "guzzlehttp/guzzle": "Allows for implementation of the Guzzle HTTP client"
60
+ },
61
+ "time": "2015-11-19 21:07:36",
62
+ "type": "library",
63
+ "extra": {
64
+ "branch-alias": {
65
+ "dev-master": "5.x-dev"
66
+ }
67
+ },
68
+ "installation-source": "dist",
69
+ "autoload": {
70
+ "psr-4": {
71
+ "Facebook\\": "src/Facebook/"
72
+ }
73
+ },
74
+ "notification-url": "https://packagist.org/downloads/",
75
+ "license": [
76
+ "Facebook Platform"
77
+ ],
78
+ "authors": [
79
+ {
80
+ "name": "Facebook",
81
+ "homepage": "https://github.com/facebook/facebook-php-sdk-v4/contributors"
82
+ }
83
+ ],
84
+ "description": "Facebook SDK for PHP",
85
+ "homepage": "https://github.com/facebook/facebook-php-sdk-v4",
86
+ "keywords": [
87
+ "facebook",
88
+ "sdk"
89
+ ]
90
+ },
91
+ {
92
+ "name": "symfony/css-selector",
93
+ "version": "v2.8.4",
94
+ "version_normalized": "2.8.4.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": {
113
+ "dev-master": "2.8-dev"
114
+ }
115
+ },
116
+ "installation-source": "dist",
117
+ "autoload": {
118
+ "psr-4": {
119
+ "Symfony\\Component\\CssSelector\\": ""
120
+ },
121
+ "exclude-from-classmap": [
122
+ "/Tests/"
123
+ ]
124
+ },
125
+ "notification-url": "https://packagist.org/downloads/",
126
+ "license": [
127
+ "MIT"
128
+ ],
129
+ "authors": [
130
+ {
131
+ "name": "Jean-François Simon",
132
+ "email": "jeanfrancois.simon@sensiolabs.com"
133
+ },
134
+ {
135
+ "name": "Fabien Potencier",
136
+ "email": "fabien@symfony.com"
137
+ },
138
+ {
139
+ "name": "Symfony Community",
140
+ "homepage": "https://symfony.com/contributors"
141
+ }
142
+ ],
143
+ "description": "Symfony CssSelector Component",
144
+ "homepage": "https://symfony.com"
145
+ },
146
+ {
147
+ "name": "facebook/facebook-instant-articles-sdk-php",
148
+ "version": "v1.0.0",
149
+ "version_normalized": "1.0.0.0",
150
+ "source": {
151
+ "type": "git",
152
+ "url": "https://github.com/facebook/facebook-instant-articles-sdk-php.git",
153
+ "reference": "d5a500c58aca210964912fac7193cfb659df0297"
154
+ },
155
+ "dist": {
156
+ "type": "zip",
157
+ "url": "https://api.github.com/repos/facebook/facebook-instant-articles-sdk-php/zipball/d5a500c58aca210964912fac7193cfb659df0297",
158
+ "reference": "d5a500c58aca210964912fac7193cfb659df0297",
159
+ "shasum": ""
160
+ },
161
+ "require": {
162
+ "apache/log4php": "2.3.0",
163
+ "facebook/php-sdk-v4": "~5.0",
164
+ "php": ">=5.4",
165
+ "symfony/css-selector": "2.8.*"
166
+ },
167
+ "require-dev": {
168
+ "phpunit/phpunit": "^4.8"
169
+ },
170
+ "time": "2016-04-10 17:15:06",
171
+ "type": "library",
172
+ "installation-source": "dist",
173
+ "autoload": {
174
+ "psr-4": {
175
+ "Facebook\\InstantArticles\\": [
176
+ "src/Facebook/InstantArticles/"
177
+ ]
178
+ }
179
+ },
180
+ "notification-url": "https://packagist.org/downloads/",
181
+ "license": [
182
+ "Facebook Platform"
183
+ ],
184
+ "authors": [
185
+ {
186
+ "name": "Facebook",
187
+ "homepage": "https://github.com/facebook/facebook-instant-articles-sdk-php/contributors"
188
+ }
189
+ ],
190
+ "description": "Facebook Instant Articles SDK for PHP",
191
+ "homepage": "https://github.com/facebook/facebook-instant-articles-sdk-php",
192
+ "keywords": [
193
+ "articles",
194
+ "facebook",
195
+ "instant",
196
+ "sdk"
197
+ ]
198
+ }
199
+ ]
vendor/facebook/facebook-instant-articles-sdk-php/.gitignore ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ composer.phar
2
+ /vendor/
3
+ *.ignored
4
+ **/IgnoredTest.php
vendor/facebook/facebook-instant-articles-sdk-php/CONTRIBUTING.md ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Contributing to Facebook Instant Articles PHP SDK
2
+ We want to make contributing to this project as easy and transparent as possible.
3
+
4
+ We accept contributions via pull requests on [GitHub](https://github.com/facebook/facebook-instant-articles-sdk-php).
5
+
6
+ ## Pull Requests
7
+ - **Sign the CLA** - In order to accept your pull request, we need you to submit a [Contributor License Agreement](https://code.facebook.com/cla). You only need to do this once to work on any of Facebook's open source projects.
8
+
9
+ - **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to run [PHP Code Sniffer](https://github.com/squizlabs/PHP_CodeSniffer) as you code.
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
+
17
+ - **Create topic branches** - Don't ask us to pull from your master branch.
18
+
19
+ - **One pull request per feature** - If you want to do more than one thing, send multiple pull requests.
20
+
21
+ - **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please squash them before submitting.
22
+
23
+ - **Ensure tests pass!** - Please [run the tests](https://github.com/facebook/facebook-instant-articles-sdk-php#testing-and-developing) before submitting your pull request, and make sure they pass. We won't accept a patch until all tests pass.
24
+
25
+ - **Ensure no coding standards violations** - Please run [PHP Code Sniffer](https://github.com/squizlabs/PHP_CodeSniffer) using the PSR-2 standard before submitting your pull request. A violation will cause the build to fail, so please make sure there are no violations. We can't accept a patch if the build fails.
26
+
27
+
28
+ ## Issues
29
+ We use GitHub issues to track public bugs. Please ensure your description is clear and has sufficient instructions to be able to reproduce the issue.
30
+
31
+
32
+ ## Running Tests
33
+
34
+ ``` bash
35
+ $ ./vendor/bin/phpunit
36
+ ```
37
+
38
+ When doing a pull request, consider if this diff has a testcase that was covered in a wrong way or if it needs a new test case.
39
+
40
+
41
+ ## Running PHP Code Sniffer
42
+
43
+ You can install [PHP Code Sniffer](https://github.com/squizlabs/PHP_CodeSniffer) globally with composer.
44
+
45
+ ``` bash
46
+ $ composer global require squizlabs/php_codesniffer
47
+ ```
48
+
49
+ Then you can `cd` into the Facebook Instant Articles PHP SDK folder and run Code Sniffer against the `src/` directory.
50
+
51
+ ``` bash
52
+ $ ~/.composer/vendor/bin/phpcs src --standard=psr2 -sp
53
+ $ ~/.composer/vendor/bin/phpcs tests --standard=psr2 -sp
54
+ ```
55
+
56
+ Give a try for the autofixer for code style
57
+
58
+ ``` bash
59
+ $ ~/.composer/vendor/bin/phpcbf src --standard=psr2 -sp
60
+ $ ~/.composer/vendor/bin/phpcbf tests --standard=psr2 -sp
61
+ ```
62
+ **Happy coding**!
vendor/facebook/facebook-instant-articles-sdk-php/LICENSE ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2016-present, Facebook, Inc. All rights reserved.
2
+
3
+ You are hereby granted a non-exclusive, worldwide, royalty-free license to
4
+ use, copy, modify, and distribute this software in source code or binary
5
+ form for use in connection with the web services and APIs provided by
6
+ Facebook.
7
+
8
+ As with any software that integrates with the Facebook platform, your use
9
+ of this software is subject to the Facebook Developer Principles and
10
+ Policies [http://developers.facebook.com/policy/]. This copyright notice
11
+ shall be included in all copies or substantial portions of the software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
16
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19
+ DEALINGS IN THE SOFTWARE.
vendor/facebook/facebook-instant-articles-sdk-php/README.md ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Facebook Instant Articles PHP SDK #
2
+
3
+ The Facebook Instant Articles SDK for PHP provides a native interface for creating and publishing Instant Articles. The SDK enables developers to more easily integrate Instant Articles into content management systems and in turn enables journalist and publishers to easily publish Instant Articles.
4
+
5
+ The SDK consists of three components:
6
+ - **Elements**: A domain-specific language for creating an Instant Articles structure that strictly follows the specification and can be automatically serialized into the subset of HTML5 markup used in the [Instant Articles format](https://developers.facebook.com/docs/instant-articles/reference). This language allows users to programmatically create Instant Articles that are guaranteed to be in compliance with the format.
7
+ - **Transformer**: An engine for transforming any markup into an Instant Article structure in the DSL. The engine runs a set of rules on the markup that will specify the selection and transformation of elements output by the CMS into their Instant Articles counterparts. The transformer ships with a base set of rules for common elements (such as a basic paragraph or an image) that can be extended and customized by developers utilizing the SDK.
8
+ - **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.
9
+
10
+ ## Quick Start
11
+ 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).
12
+
13
+ ## Installation
14
+
15
+ The Facebook Instant Articles PHP SDK can be installed with [Composer](https://getcomposer.org/). Run this command:
16
+
17
+ ```sh
18
+ composer require facebook/facebook-instant-articles-sdk-php
19
+ ```
20
+
21
+ ## Testing and Developing ##
22
+
23
+ [Composer](https://getcomposer.org/) is a prerequisite for testing and developing. [Install composer globally](https://getcomposer.org/doc/00-intro.md#globally), then install project dependencies by running this command in the project root directory:
24
+ ```sh
25
+ composer install
26
+ ```
27
+
28
+ To run the tests:
29
+ ```sh
30
+ ./vendor/bin/phpunit
31
+ ```
32
+
33
+ If you change structure, paths, namespaces, etc., make sure you run the [autoload generator](https://getcomposer.org/doc/03-cli.md#dump-autoload):
34
+ ```sh
35
+ composer dump-autoload
36
+ ```
37
+
38
+ ## Contributing
39
+
40
+ 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.
41
+
42
+ ## License
43
+
44
+ Please see the [license file](https://github.com/facebook/facebook-instant-articles-sdk-php/blob/master/LICENSE) for more information.
vendor/facebook/facebook-instant-articles-sdk-php/composer.json ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "facebook/facebook-instant-articles-sdk-php",
3
+ "description": "Facebook Instant Articles SDK for PHP",
4
+ "keywords": ["facebook", "sdk", "instant", "articles"],
5
+ "type": "library",
6
+ "homepage": "https://github.com/facebook/facebook-instant-articles-sdk-php",
7
+ "license": "Facebook Platform",
8
+ "authors": [{
9
+ "name": "Facebook",
10
+ "homepage": "https://github.com/facebook/facebook-instant-articles-sdk-php/contributors"
11
+ }],
12
+ "require": {
13
+ "php": ">=5.4",
14
+ "symfony/css-selector": "2.8.*",
15
+ "facebook/php-sdk-v4": "~5.0",
16
+ "apache/log4php": "2.3.0"
17
+ },
18
+ "require-dev": {
19
+ "phpunit/phpunit": "^4.8"
20
+ },
21
+ "autoload": {
22
+ "psr-4": {
23
+ "Facebook\\InstantArticles\\": ["src/Facebook/InstantArticles/"]
24
+ }
25
+ }
26
+ }
vendor/facebook/facebook-instant-articles-sdk-php/composer.lock ADDED
@@ -0,0 +1,1113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_readme": [
3
+ "This file locks the dependencies of your project to a known state",
4
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
5
+ "This file is @generated automatically"
6
+ ],
7
+ "hash": "27451258fbd10b198e79d95a28d003f6",
8
+ "content-hash": "d1a7e51f731a8e2756648dca0a386d0a",
9
+ "packages": [
10
+ {
11
+ "name": "apache/log4php",
12
+ "version": "2.3.0",
13
+ "source": {
14
+ "type": "git",
15
+ "url": "https://git-wip-us.apache.org/repos/asf/logging-log4php.git",
16
+ "reference": "8c6df2481cd68d0d211d38f700406c5f0a9de0c2"
17
+ },
18
+ "require": {
19
+ "php": ">=5.2.7"
20
+ },
21
+ "type": "library",
22
+ "autoload": {
23
+ "classmap": [
24
+ "src/main/php/"
25
+ ]
26
+ },
27
+ "notification-url": "https://packagist.org/downloads/",
28
+ "license": [
29
+ "Apache-2.0"
30
+ ],
31
+ "description": "A versatile logging framework for PHP",
32
+ "homepage": "http://logging.apache.org/log4php/",
33
+ "keywords": [
34
+ "log",
35
+ "logging",
36
+ "php"
37
+ ],
38
+ "time": "2012-10-26 09:13:25"
39
+ },
40
+ {
41
+ "name": "facebook/php-sdk-v4",
42
+ "version": "5.1.2",
43
+ "source": {
44
+ "type": "git",
45
+ "url": "https://github.com/facebook/facebook-php-sdk-v4.git",
46
+ "reference": "2c42fb3002953355f12d3c6e8003a9fd5af563d9"
47
+ },
48
+ "dist": {
49
+ "type": "zip",
50
+ "url": "https://api.github.com/repos/facebook/facebook-php-sdk-v4/zipball/2c42fb3002953355f12d3c6e8003a9fd5af563d9",
51
+ "reference": "2c42fb3002953355f12d3c6e8003a9fd5af563d9",
52
+ "shasum": ""
53
+ },
54
+ "require": {
55
+ "ext-mbstring": "*",
56
+ "php": ">=5.4.0"
57
+ },
58
+ "require-dev": {
59
+ "guzzlehttp/guzzle": "~5.0",
60
+ "mockery/mockery": "~0.8",
61
+ "phpunit/phpunit": "~4.0"
62
+ },
63
+ "suggest": {
64
+ "guzzlehttp/guzzle": "Allows for implementation of the Guzzle HTTP client"
65
+ },
66
+ "type": "library",
67
+ "extra": {
68
+ "branch-alias": {
69
+ "dev-master": "5.x-dev"
70
+ }
71
+ },
72
+ "autoload": {
73
+ "psr-4": {
74
+ "Facebook\\": "src/Facebook/"
75
+ }
76
+ },
77
+ "notification-url": "https://packagist.org/downloads/",
78
+ "license": [
79
+ "Facebook Platform"
80
+ ],
81
+ "authors": [
82
+ {
83
+ "name": "Facebook",
84
+ "homepage": "https://github.com/facebook/facebook-php-sdk-v4/contributors"
85
+ }
86
+ ],
87
+ "description": "Facebook SDK for PHP",
88
+ "homepage": "https://github.com/facebook/facebook-php-sdk-v4",
89
+ "keywords": [
90
+ "facebook",
91
+ "sdk"
92
+ ],
93
+ "time": "2015-11-19 21:07:36"
94
+ },
95
+ {
96
+ "name": "symfony/css-selector",
97
+ "version": "v2.8.4",
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": {
110
+ "php": ">=5.3.9"
111
+ },
112
+ "type": "library",
113
+ "extra": {
114
+ "branch-alias": {
115
+ "dev-master": "2.8-dev"
116
+ }
117
+ },
118
+ "autoload": {
119
+ "psr-4": {
120
+ "Symfony\\Component\\CssSelector\\": ""
121
+ },
122
+ "exclude-from-classmap": [
123
+ "/Tests/"
124
+ ]
125
+ },
126
+ "notification-url": "https://packagist.org/downloads/",
127
+ "license": [
128
+ "MIT"
129
+ ],
130
+ "authors": [
131
+ {
132
+ "name": "Jean-François Simon",
133
+ "email": "jeanfrancois.simon@sensiolabs.com"
134
+ },
135
+ {
136
+ "name": "Fabien Potencier",
137
+ "email": "fabien@symfony.com"
138
+ },
139
+ {
140
+ "name": "Symfony Community",
141
+ "homepage": "https://symfony.com/contributors"
142
+ }
143
+ ],
144
+ "description": "Symfony CssSelector Component",
145
+ "homepage": "https://symfony.com",
146
+ "time": "2016-03-04 07:54:35"
147
+ }
148
+ ],
149
+ "packages-dev": [
150
+ {
151
+ "name": "doctrine/instantiator",
152
+ "version": "1.0.5",
153
+ "source": {
154
+ "type": "git",
155
+ "url": "https://github.com/doctrine/instantiator.git",
156
+ "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d"
157
+ },
158
+ "dist": {
159
+ "type": "zip",
160
+ "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d",
161
+ "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d",
162
+ "shasum": ""
163
+ },
164
+ "require": {
165
+ "php": ">=5.3,<8.0-DEV"
166
+ },
167
+ "require-dev": {
168
+ "athletic/athletic": "~0.1.8",
169
+ "ext-pdo": "*",
170
+ "ext-phar": "*",
171
+ "phpunit/phpunit": "~4.0",
172
+ "squizlabs/php_codesniffer": "~2.0"
173
+ },
174
+ "type": "library",
175
+ "extra": {
176
+ "branch-alias": {
177
+ "dev-master": "1.0.x-dev"
178
+ }
179
+ },
180
+ "autoload": {
181
+ "psr-4": {
182
+ "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
183
+ }
184
+ },
185
+ "notification-url": "https://packagist.org/downloads/",
186
+ "license": [
187
+ "MIT"
188
+ ],
189
+ "authors": [
190
+ {
191
+ "name": "Marco Pivetta",
192
+ "email": "ocramius@gmail.com",
193
+ "homepage": "http://ocramius.github.com/"
194
+ }
195
+ ],
196
+ "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
197
+ "homepage": "https://github.com/doctrine/instantiator",
198
+ "keywords": [
199
+ "constructor",
200
+ "instantiate"
201
+ ],
202
+ "time": "2015-06-14 21:17:01"
203
+ },
204
+ {
205
+ "name": "phpdocumentor/reflection-docblock",
206
+ "version": "2.0.4",
207
+ "source": {
208
+ "type": "git",
209
+ "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
210
+ "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8"
211
+ },
212
+ "dist": {
213
+ "type": "zip",
214
+ "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8",
215
+ "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8",
216
+ "shasum": ""
217
+ },
218
+ "require": {
219
+ "php": ">=5.3.3"
220
+ },
221
+ "require-dev": {
222
+ "phpunit/phpunit": "~4.0"
223
+ },
224
+ "suggest": {
225
+ "dflydev/markdown": "~1.0",
226
+ "erusev/parsedown": "~1.0"
227
+ },
228
+ "type": "library",
229
+ "extra": {
230
+ "branch-alias": {
231
+ "dev-master": "2.0.x-dev"
232
+ }
233
+ },
234
+ "autoload": {
235
+ "psr-0": {
236
+ "phpDocumentor": [
237
+ "src/"
238
+ ]
239
+ }
240
+ },
241
+ "notification-url": "https://packagist.org/downloads/",
242
+ "license": [
243
+ "MIT"
244
+ ],
245
+ "authors": [
246
+ {
247
+ "name": "Mike van Riel",
248
+ "email": "mike.vanriel@naenius.com"
249
+ }
250
+ ],
251
+ "time": "2015-02-03 12:10:50"
252
+ },
253
+ {
254
+ "name": "phpspec/prophecy",
255
+ "version": "v1.6.0",
256
+ "source": {
257
+ "type": "git",
258
+ "url": "https://github.com/phpspec/prophecy.git",
259
+ "reference": "3c91bdf81797d725b14cb62906f9a4ce44235972"
260
+ },
261
+ "dist": {
262
+ "type": "zip",
263
+ "url": "https://api.github.com/repos/phpspec/prophecy/zipball/3c91bdf81797d725b14cb62906f9a4ce44235972",
264
+ "reference": "3c91bdf81797d725b14cb62906f9a4ce44235972",
265
+ "shasum": ""
266
+ },
267
+ "require": {
268
+ "doctrine/instantiator": "^1.0.2",
269
+ "php": "^5.3|^7.0",
270
+ "phpdocumentor/reflection-docblock": "~2.0",
271
+ "sebastian/comparator": "~1.1",
272
+ "sebastian/recursion-context": "~1.0"
273
+ },
274
+ "require-dev": {
275
+ "phpspec/phpspec": "~2.0"
276
+ },
277
+ "type": "library",
278
+ "extra": {
279
+ "branch-alias": {
280
+ "dev-master": "1.5.x-dev"
281
+ }
282
+ },
283
+ "autoload": {
284
+ "psr-0": {
285
+ "Prophecy\\": "src/"
286
+ }
287
+ },
288
+ "notification-url": "https://packagist.org/downloads/",
289
+ "license": [
290
+ "MIT"
291
+ ],
292
+ "authors": [
293
+ {
294
+ "name": "Konstantin Kudryashov",
295
+ "email": "ever.zet@gmail.com",
296
+ "homepage": "http://everzet.com"
297
+ },
298
+ {
299
+ "name": "Marcello Duarte",
300
+ "email": "marcello.duarte@gmail.com"
301
+ }
302
+ ],
303
+ "description": "Highly opinionated mocking framework for PHP 5.3+",
304
+ "homepage": "https://github.com/phpspec/prophecy",
305
+ "keywords": [
306
+ "Double",
307
+ "Dummy",
308
+ "fake",
309
+ "mock",
310
+ "spy",
311
+ "stub"
312
+ ],
313
+ "time": "2016-02-15 07:46:21"
314
+ },
315
+ {
316
+ "name": "phpunit/php-code-coverage",
317
+ "version": "2.2.4",
318
+ "source": {
319
+ "type": "git",
320
+ "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
321
+ "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979"
322
+ },
323
+ "dist": {
324
+ "type": "zip",
325
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979",
326
+ "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979",
327
+ "shasum": ""
328
+ },
329
+ "require": {
330
+ "php": ">=5.3.3",
331
+ "phpunit/php-file-iterator": "~1.3",
332
+ "phpunit/php-text-template": "~1.2",
333
+ "phpunit/php-token-stream": "~1.3",
334
+ "sebastian/environment": "^1.3.2",
335
+ "sebastian/version": "~1.0"
336
+ },
337
+ "require-dev": {
338
+ "ext-xdebug": ">=2.1.4",
339
+ "phpunit/phpunit": "~4"
340
+ },
341
+ "suggest": {
342
+ "ext-dom": "*",
343
+ "ext-xdebug": ">=2.2.1",
344
+ "ext-xmlwriter": "*"
345
+ },
346
+ "type": "library",
347
+ "extra": {
348
+ "branch-alias": {
349
+ "dev-master": "2.2.x-dev"
350
+ }
351
+ },
352
+ "autoload": {
353
+ "classmap": [
354
+ "src/"
355
+ ]
356
+ },
357
+ "notification-url": "https://packagist.org/downloads/",
358
+ "license": [
359
+ "BSD-3-Clause"
360
+ ],
361
+ "authors": [
362
+ {
363
+ "name": "Sebastian Bergmann",
364
+ "email": "sb@sebastian-bergmann.de",
365
+ "role": "lead"
366
+ }
367
+ ],
368
+ "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
369
+ "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
370
+ "keywords": [
371
+ "coverage",
372
+ "testing",
373
+ "xunit"
374
+ ],
375
+ "time": "2015-10-06 15:47:00"
376
+ },
377
+ {
378
+ "name": "phpunit/php-file-iterator",
379
+ "version": "1.4.1",
380
+ "source": {
381
+ "type": "git",
382
+ "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
383
+ "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0"
384
+ },
385
+ "dist": {
386
+ "type": "zip",
387
+ "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0",
388
+ "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0",
389
+ "shasum": ""
390
+ },
391
+ "require": {
392
+ "php": ">=5.3.3"
393
+ },
394
+ "type": "library",
395
+ "extra": {
396
+ "branch-alias": {
397
+ "dev-master": "1.4.x-dev"
398
+ }
399
+ },
400
+ "autoload": {
401
+ "classmap": [
402
+ "src/"
403
+ ]
404
+ },
405
+ "notification-url": "https://packagist.org/downloads/",
406
+ "license": [
407
+ "BSD-3-Clause"
408
+ ],
409
+ "authors": [
410
+ {
411
+ "name": "Sebastian Bergmann",
412
+ "email": "sb@sebastian-bergmann.de",
413
+ "role": "lead"
414
+ }
415
+ ],
416
+ "description": "FilterIterator implementation that filters files based on a list of suffixes.",
417
+ "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
418
+ "keywords": [
419
+ "filesystem",
420
+ "iterator"
421
+ ],
422
+ "time": "2015-06-21 13:08:43"
423
+ },
424
+ {
425
+ "name": "phpunit/php-text-template",
426
+ "version": "1.2.1",
427
+ "source": {
428
+ "type": "git",
429
+ "url": "https://github.com/sebastianbergmann/php-text-template.git",
430
+ "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
431
+ },
432
+ "dist": {
433
+ "type": "zip",
434
+ "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
435
+ "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
436
+ "shasum": ""
437
+ },
438
+ "require": {
439
+ "php": ">=5.3.3"
440
+ },
441
+ "type": "library",
442
+ "autoload": {
443
+ "classmap": [
444
+ "src/"
445
+ ]
446
+ },
447
+ "notification-url": "https://packagist.org/downloads/",
448
+ "license": [
449
+ "BSD-3-Clause"
450
+ ],
451
+ "authors": [
452
+ {
453
+ "name": "Sebastian Bergmann",
454
+ "email": "sebastian@phpunit.de",
455
+ "role": "lead"
456
+ }
457
+ ],
458
+ "description": "Simple template engine.",
459
+ "homepage": "https://github.com/sebastianbergmann/php-text-template/",
460
+ "keywords": [
461
+ "template"
462
+ ],
463
+ "time": "2015-06-21 13:50:34"
464
+ },
465
+ {
466
+ "name": "phpunit/php-timer",
467
+ "version": "1.0.7",
468
+ "source": {
469
+ "type": "git",
470
+ "url": "https://github.com/sebastianbergmann/php-timer.git",
471
+ "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b"
472
+ },
473
+ "dist": {
474
+ "type": "zip",
475
+ "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3e82f4e9fc92665fafd9157568e4dcb01d014e5b",
476
+ "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b",
477
+ "shasum": ""
478
+ },
479
+ "require": {
480
+ "php": ">=5.3.3"
481
+ },
482
+ "type": "library",
483
+ "autoload": {
484
+ "classmap": [
485
+ "src/"
486
+ ]
487
+ },
488
+ "notification-url": "https://packagist.org/downloads/",
489
+ "license": [
490
+ "BSD-3-Clause"
491
+ ],
492
+ "authors": [
493
+ {
494
+ "name": "Sebastian Bergmann",
495
+ "email": "sb@sebastian-bergmann.de",
496
+ "role": "lead"
497
+ }
498
+ ],
499
+ "description": "Utility class for timing",
500
+ "homepage": "https://github.com/sebastianbergmann/php-timer/",
501
+ "keywords": [
502
+ "timer"
503
+ ],
504
+ "time": "2015-06-21 08:01:12"
505
+ },
506
+ {
507
+ "name": "phpunit/php-token-stream",
508
+ "version": "1.4.8",
509
+ "source": {
510
+ "type": "git",
511
+ "url": "https://github.com/sebastianbergmann/php-token-stream.git",
512
+ "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da"
513
+ },
514
+ "dist": {
515
+ "type": "zip",
516
+ "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da",
517
+ "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da",
518
+ "shasum": ""
519
+ },
520
+ "require": {
521
+ "ext-tokenizer": "*",
522
+ "php": ">=5.3.3"
523
+ },
524
+ "require-dev": {
525
+ "phpunit/phpunit": "~4.2"
526
+ },
527
+ "type": "library",
528
+ "extra": {
529
+ "branch-alias": {
530
+ "dev-master": "1.4-dev"
531
+ }
532
+ },
533
+ "autoload": {
534
+ "classmap": [
535
+ "src/"
536
+ ]
537
+ },
538
+ "notification-url": "https://packagist.org/downloads/",
539
+ "license": [
540
+ "BSD-3-Clause"
541
+ ],
542
+ "authors": [
543
+ {
544
+ "name": "Sebastian Bergmann",
545
+ "email": "sebastian@phpunit.de"
546
+ }
547
+ ],
548
+ "description": "Wrapper around PHP's tokenizer extension.",
549
+ "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
550
+ "keywords": [
551
+ "tokenizer"
552
+ ],
553
+ "time": "2015-09-15 10:49:45"
554
+ },
555
+ {
556
+ "name": "phpunit/phpunit",
557
+ "version": "4.8.24",
558
+ "source": {
559
+ "type": "git",
560
+ "url": "https://github.com/sebastianbergmann/phpunit.git",
561
+ "reference": "a1066c562c52900a142a0e2bbf0582994671385e"
562
+ },
563
+ "dist": {
564
+ "type": "zip",
565
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a1066c562c52900a142a0e2bbf0582994671385e",
566
+ "reference": "a1066c562c52900a142a0e2bbf0582994671385e",
567
+ "shasum": ""
568
+ },
569
+ "require": {
570
+ "ext-dom": "*",
571
+ "ext-json": "*",
572
+ "ext-pcre": "*",
573
+ "ext-reflection": "*",
574
+ "ext-spl": "*",
575
+ "php": ">=5.3.3",
576
+ "phpspec/prophecy": "^1.3.1",
577
+ "phpunit/php-code-coverage": "~2.1",
578
+ "phpunit/php-file-iterator": "~1.4",
579
+ "phpunit/php-text-template": "~1.2",
580
+ "phpunit/php-timer": ">=1.0.6",
581
+ "phpunit/phpunit-mock-objects": "~2.3",
582
+ "sebastian/comparator": "~1.1",
583
+ "sebastian/diff": "~1.2",
584
+ "sebastian/environment": "~1.3",
585
+ "sebastian/exporter": "~1.2",
586
+ "sebastian/global-state": "~1.0",
587
+ "sebastian/version": "~1.0",
588
+ "symfony/yaml": "~2.1|~3.0"
589
+ },
590
+ "suggest": {
591
+ "phpunit/php-invoker": "~1.1"
592
+ },
593
+ "bin": [
594
+ "phpunit"
595
+ ],
596
+ "type": "library",
597
+ "extra": {
598
+ "branch-alias": {
599
+ "dev-master": "4.8.x-dev"
600
+ }
601
+ },
602
+ "autoload": {
603
+ "classmap": [
604
+ "src/"
605
+ ]
606
+ },
607
+ "notification-url": "https://packagist.org/downloads/",
608
+ "license": [
609
+ "BSD-3-Clause"
610
+ ],
611
+ "authors": [
612
+ {
613
+ "name": "Sebastian Bergmann",
614
+ "email": "sebastian@phpunit.de",
615
+ "role": "lead"
616
+ }
617
+ ],
618
+ "description": "The PHP Unit Testing framework.",
619
+ "homepage": "https://phpunit.de/",
620
+ "keywords": [
621
+ "phpunit",
622
+ "testing",
623
+ "xunit"
624
+ ],
625
+ "time": "2016-03-14 06:16:08"
626
+ },
627
+ {
628
+ "name": "phpunit/phpunit-mock-objects",
629
+ "version": "2.3.8",
630
+ "source": {
631
+ "type": "git",
632
+ "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
633
+ "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983"
634
+ },
635
+ "dist": {
636
+ "type": "zip",
637
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983",
638
+ "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983",
639
+ "shasum": ""
640
+ },
641
+ "require": {
642
+ "doctrine/instantiator": "^1.0.2",
643
+ "php": ">=5.3.3",
644
+ "phpunit/php-text-template": "~1.2",
645
+ "sebastian/exporter": "~1.2"
646
+ },
647
+ "require-dev": {
648
+ "phpunit/phpunit": "~4.4"
649
+ },
650
+ "suggest": {
651
+ "ext-soap": "*"
652
+ },
653
+ "type": "library",
654
+ "extra": {
655
+ "branch-alias": {
656
+ "dev-master": "2.3.x-dev"
657
+ }
658
+ },
659
+ "autoload": {
660
+ "classmap": [
661
+ "src/"
662
+ ]
663
+ },
664
+ "notification-url": "https://packagist.org/downloads/",
665
+ "license": [
666
+ "BSD-3-Clause"
667
+ ],
668
+ "authors": [
669
+ {
670
+ "name": "Sebastian Bergmann",
671
+ "email": "sb@sebastian-bergmann.de",
672
+ "role": "lead"
673
+ }
674
+ ],
675
+ "description": "Mock Object library for PHPUnit",
676
+ "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
677
+ "keywords": [
678
+ "mock",
679
+ "xunit"
680
+ ],
681
+ "time": "2015-10-02 06:51:40"
682
+ },
683
+ {
684
+ "name": "sebastian/comparator",
685
+ "version": "1.2.0",
686
+ "source": {
687
+ "type": "git",
688
+ "url": "https://github.com/sebastianbergmann/comparator.git",
689
+ "reference": "937efb279bd37a375bcadf584dec0726f84dbf22"
690
+ },
691
+ "dist": {
692
+ "type": "zip",
693
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22",
694
+ "reference": "937efb279bd37a375bcadf584dec0726f84dbf22",
695
+ "shasum": ""
696
+ },
697
+ "require": {
698
+ "php": ">=5.3.3",
699
+ "sebastian/diff": "~1.2",
700
+ "sebastian/exporter": "~1.2"
701
+ },
702
+ "require-dev": {
703
+ "phpunit/phpunit": "~4.4"
704
+ },
705
+ "type": "library",
706
+ "extra": {
707
+ "branch-alias": {
708
+ "dev-master": "1.2.x-dev"
709
+ }
710
+ },
711
+ "autoload": {
712
+ "classmap": [
713
+ "src/"
714
+ ]
715
+ },
716
+ "notification-url": "https://packagist.org/downloads/",
717
+ "license": [
718
+ "BSD-3-Clause"
719
+ ],
720
+ "authors": [
721
+ {
722
+ "name": "Jeff Welch",
723
+ "email": "whatthejeff@gmail.com"
724
+ },
725
+ {
726
+ "name": "Volker Dusch",
727
+ "email": "github@wallbash.com"
728
+ },
729
+ {
730
+ "name": "Bernhard Schussek",
731
+ "email": "bschussek@2bepublished.at"
732
+ },
733
+ {
734
+ "name": "Sebastian Bergmann",
735
+ "email": "sebastian@phpunit.de"
736
+ }
737
+ ],
738
+ "description": "Provides the functionality to compare PHP values for equality",
739
+ "homepage": "http://www.github.com/sebastianbergmann/comparator",
740
+ "keywords": [
741
+ "comparator",
742
+ "compare",
743
+ "equality"
744
+ ],
745
+ "time": "2015-07-26 15:48:44"
746
+ },
747
+ {
748
+ "name": "sebastian/diff",
749
+ "version": "1.4.1",
750
+ "source": {
751
+ "type": "git",
752
+ "url": "https://github.com/sebastianbergmann/diff.git",
753
+ "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e"
754
+ },
755
+ "dist": {
756
+ "type": "zip",
757
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e",
758
+ "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e",
759
+ "shasum": ""
760
+ },
761
+ "require": {
762
+ "php": ">=5.3.3"
763
+ },
764
+ "require-dev": {
765
+ "phpunit/phpunit": "~4.8"
766
+ },
767
+ "type": "library",
768
+ "extra": {
769
+ "branch-alias": {
770
+ "dev-master": "1.4-dev"
771
+ }
772
+ },
773
+ "autoload": {
774
+ "classmap": [
775
+ "src/"
776
+ ]
777
+ },
778
+ "notification-url": "https://packagist.org/downloads/",
779
+ "license": [
780
+ "BSD-3-Clause"
781
+ ],
782
+ "authors": [
783
+ {
784
+ "name": "Kore Nordmann",
785
+ "email": "mail@kore-nordmann.de"
786
+ },
787
+ {
788
+ "name": "Sebastian Bergmann",
789
+ "email": "sebastian@phpunit.de"
790
+ }
791
+ ],
792
+ "description": "Diff implementation",
793
+ "homepage": "https://github.com/sebastianbergmann/diff",
794
+ "keywords": [
795
+ "diff"
796
+ ],
797
+ "time": "2015-12-08 07:14:41"
798
+ },
799
+ {
800
+ "name": "sebastian/environment",
801
+ "version": "1.3.5",
802
+ "source": {
803
+ "type": "git",
804
+ "url": "https://github.com/sebastianbergmann/environment.git",
805
+ "reference": "dc7a29032cf72b54f36dac15a1ca5b3a1b6029bf"
806
+ },
807
+ "dist": {
808
+ "type": "zip",
809
+ "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/dc7a29032cf72b54f36dac15a1ca5b3a1b6029bf",
810
+ "reference": "dc7a29032cf72b54f36dac15a1ca5b3a1b6029bf",
811
+ "shasum": ""
812
+ },
813
+ "require": {
814
+ "php": ">=5.3.3"
815
+ },
816
+ "require-dev": {
817
+ "phpunit/phpunit": "~4.4"
818
+ },
819
+ "type": "library",
820
+ "extra": {
821
+ "branch-alias": {
822
+ "dev-master": "1.3.x-dev"
823
+ }
824
+ },
825
+ "autoload": {
826
+ "classmap": [
827
+ "src/"
828
+ ]
829
+ },
830
+ "notification-url": "https://packagist.org/downloads/",
831
+ "license": [
832
+ "BSD-3-Clause"
833
+ ],
834
+ "authors": [
835
+ {
836
+ "name": "Sebastian Bergmann",
837
+ "email": "sebastian@phpunit.de"
838
+ }
839
+ ],
840
+ "description": "Provides functionality to handle HHVM/PHP environments",
841
+ "homepage": "http://www.github.com/sebastianbergmann/environment",
842
+ "keywords": [
843
+ "Xdebug",
844
+ "environment",
845
+ "hhvm"
846
+ ],
847
+ "time": "2016-02-26 18:40:46"
848
+ },
849
+ {
850
+ "name": "sebastian/exporter",
851
+ "version": "1.2.1",
852
+ "source": {
853
+ "type": "git",
854
+ "url": "https://github.com/sebastianbergmann/exporter.git",
855
+ "reference": "7ae5513327cb536431847bcc0c10edba2701064e"
856
+ },
857
+ "dist": {
858
+ "type": "zip",
859
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e",
860
+ "reference": "7ae5513327cb536431847bcc0c10edba2701064e",
861
+ "shasum": ""
862
+ },
863
+ "require": {
864
+ "php": ">=5.3.3",
865
+ "sebastian/recursion-context": "~1.0"
866
+ },
867
+ "require-dev": {
868
+ "phpunit/phpunit": "~4.4"
869
+ },
870
+ "type": "library",
871
+ "extra": {
872
+ "branch-alias": {
873
+ "dev-master": "1.2.x-dev"
874
+ }
875
+ },
876
+ "autoload": {
877
+ "classmap": [
878
+ "src/"
879
+ ]
880
+ },
881
+ "notification-url": "https://packagist.org/downloads/",
882
+ "license": [
883
+ "BSD-3-Clause"
884
+ ],
885
+ "authors": [
886
+ {
887
+ "name": "Jeff Welch",
888
+ "email": "whatthejeff@gmail.com"
889
+ },
890
+ {
891
+ "name": "Volker Dusch",
892
+ "email": "github@wallbash.com"
893
+ },
894
+ {
895
+ "name": "Bernhard Schussek",
896
+ "email": "bschussek@2bepublished.at"
897
+ },
898
+ {
899
+ "name": "Sebastian Bergmann",
900
+ "email": "sebastian@phpunit.de"
901
+ },
902
+ {
903
+ "name": "Adam Harvey",
904
+ "email": "aharvey@php.net"
905
+ }
906
+ ],
907
+ "description": "Provides the functionality to export PHP variables for visualization",
908
+ "homepage": "http://www.github.com/sebastianbergmann/exporter",
909
+ "keywords": [
910
+ "export",
911
+ "exporter"
912
+ ],
913
+ "time": "2015-06-21 07:55:53"
914
+ },
915
+ {
916
+ "name": "sebastian/global-state",
917
+ "version": "1.1.1",
918
+ "source": {
919
+ "type": "git",
920
+ "url": "https://github.com/sebastianbergmann/global-state.git",
921
+ "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4"
922
+ },
923
+ "dist": {
924
+ "type": "zip",
925
+ "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4",
926
+ "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4",
927
+ "shasum": ""
928
+ },
929
+ "require": {
930
+ "php": ">=5.3.3"
931
+ },
932
+ "require-dev": {
933
+ "phpunit/phpunit": "~4.2"
934
+ },
935
+ "suggest": {
936
+ "ext-uopz": "*"
937
+ },
938
+ "type": "library",
939
+ "extra": {
940
+ "branch-alias": {
941
+ "dev-master": "1.0-dev"
942
+ }
943
+ },
944
+ "autoload": {
945
+ "classmap": [
946
+ "src/"
947
+ ]
948
+ },
949
+ "notification-url": "https://packagist.org/downloads/",
950
+ "license": [
951
+ "BSD-3-Clause"
952
+ ],
953
+ "authors": [
954
+ {
955
+ "name": "Sebastian Bergmann",
956
+ "email": "sebastian@phpunit.de"
957
+ }
958
+ ],
959
+ "description": "Snapshotting of global state",
960
+ "homepage": "http://www.github.com/sebastianbergmann/global-state",
961
+ "keywords": [
962
+ "global state"
963
+ ],
964
+ "time": "2015-10-12 03:26:01"
965
+ },
966
+ {
967
+ "name": "sebastian/recursion-context",
968
+ "version": "1.0.2",
969
+ "source": {
970
+ "type": "git",
971
+ "url": "https://github.com/sebastianbergmann/recursion-context.git",
972
+ "reference": "913401df809e99e4f47b27cdd781f4a258d58791"
973
+ },
974
+ "dist": {
975
+ "type": "zip",
976
+ "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791",
977
+ "reference": "913401df809e99e4f47b27cdd781f4a258d58791",
978
+ "shasum": ""
979
+ },
980
+ "require": {
981
+ "php": ">=5.3.3"
982
+ },
983
+ "require-dev": {
984
+ "phpunit/phpunit": "~4.4"
985
+ },
986
+ "type": "library",
987
+ "extra": {
988
+ "branch-alias": {
989
+ "dev-master": "1.0.x-dev"
990
+ }
991
+ },
992
+ "autoload": {
993
+ "classmap": [
994
+ "src/"
995
+ ]
996
+ },
997
+ "notification-url": "https://packagist.org/downloads/",
998
+ "license": [
999
+ "BSD-3-Clause"
1000
+ ],
1001
+ "authors": [
1002
+ {
1003
+ "name": "Jeff Welch",
1004
+ "email": "whatthejeff@gmail.com"
1005
+ },
1006
+ {
1007
+ "name": "Sebastian Bergmann",
1008
+ "email": "sebastian@phpunit.de"
1009
+ },
1010
+ {
1011
+ "name": "Adam Harvey",
1012
+ "email": "aharvey@php.net"
1013
+ }
1014
+ ],
1015
+ "description": "Provides functionality to recursively process PHP variables",
1016
+ "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
1017
+ "time": "2015-11-11 19:50:13"
1018
+ },
1019
+ {
1020
+ "name": "sebastian/version",
1021
+ "version": "1.0.6",
1022
+ "source": {
1023
+ "type": "git",
1024
+ "url": "https://github.com/sebastianbergmann/version.git",
1025
+ "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6"
1026
+ },
1027
+ "dist": {
1028
+ "type": "zip",
1029
+ "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
1030
+ "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
1031
+ "shasum": ""
1032
+ },
1033
+ "type": "library",
1034
+ "autoload": {
1035
+ "classmap": [
1036
+ "src/"
1037
+ ]
1038
+ },
1039
+ "notification-url": "https://packagist.org/downloads/",
1040
+ "license": [
1041
+ "BSD-3-Clause"
1042
+ ],
1043
+ "authors": [
1044
+ {
1045
+ "name": "Sebastian Bergmann",
1046
+ "email": "sebastian@phpunit.de",
1047
+ "role": "lead"
1048
+ }
1049
+ ],
1050
+ "description": "Library that helps with managing the version number of Git-hosted PHP projects",
1051
+ "homepage": "https://github.com/sebastianbergmann/version",
1052
+ "time": "2015-06-21 13:59:46"
1053
+ },
1054
+ {
1055
+ "name": "symfony/yaml",
1056
+ "version": "v2.8.4",
1057
+ "source": {
1058
+ "type": "git",
1059
+ "url": "https://github.com/symfony/yaml.git",
1060
+ "reference": "584e52cb8f788a887553ba82db6caacb1d6260bb"
1061
+ },
1062
+ "dist": {
1063
+ "type": "zip",
1064
+ "url": "https://api.github.com/repos/symfony/yaml/zipball/584e52cb8f788a887553ba82db6caacb1d6260bb",
1065
+ "reference": "584e52cb8f788a887553ba82db6caacb1d6260bb",
1066
+ "shasum": ""
1067
+ },
1068
+ "require": {
1069
+ "php": ">=5.3.9"
1070
+ },
1071
+ "type": "library",
1072
+ "extra": {
1073
+ "branch-alias": {
1074
+ "dev-master": "2.8-dev"
1075
+ }
1076
+ },
1077
+ "autoload": {
1078
+ "psr-4": {
1079
+ "Symfony\\Component\\Yaml\\": ""
1080
+ },
1081
+ "exclude-from-classmap": [
1082
+ "/Tests/"
1083
+ ]
1084
+ },
1085
+ "notification-url": "https://packagist.org/downloads/",
1086
+ "license": [
1087
+ "MIT"
1088
+ ],
1089
+ "authors": [
1090
+ {
1091
+ "name": "Fabien Potencier",
1092
+ "email": "fabien@symfony.com"
1093
+ },
1094
+ {
1095
+ "name": "Symfony Community",
1096
+ "homepage": "https://symfony.com/contributors"
1097
+ }
1098
+ ],
1099
+ "description": "Symfony Yaml Component",
1100
+ "homepage": "https://symfony.com",
1101
+ "time": "2016-03-04 07:54:35"
1102
+ }
1103
+ ],
1104
+ "aliases": [],
1105
+ "minimum-stability": "stable",
1106
+ "stability-flags": [],
1107
+ "prefer-stable": false,
1108
+ "prefer-lowest": false,
1109
+ "platform": {
1110
+ "php": ">=5.4"
1111
+ },
1112
+ "platform-dev": []
1113
+ }
vendor/facebook/facebook-instant-articles-sdk-php/docs/QuickStart.md ADDED
@@ -0,0 +1,498 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ ## Elements
9
+ `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.
10
+
11
+ ```php
12
+ $article =
13
+ InstantArticle::create()
14
+ ->withCanonicalUrl('http://foo.com/article.html')
15
+ ->withHeader(
16
+ Header::create()
17
+ ->withTitle('Big Top Title')
18
+ ->withSubTitle('Smaller SubTitle')
19
+ ->withPublishTime(
20
+ Time::create(Time::PUBLISHED)
21
+ ->withDatetime(
22
+ \DateTime::createFromFormat(
23
+ 'j-M-Y G:i:s',
24
+ '14-Aug-1984 19:30:00'
25
+ )
26
+ )
27
+ )
28
+ ->withModifyTime(
29
+ Time::create(Time::MODIFIED)
30
+ ->withDatetime(
31
+ \DateTime::createFromFormat(
32
+ 'j-M-Y G:i:s',
33
+ '10-Feb-2016 10:00:00'
34
+ )
35
+ )
36
+ )
37
+ ->addAuthor(
38
+ Author::create()
39
+ ->withName('Author Name')
40
+ ->withDescription('Author more detailed description')
41
+ )
42
+ ->addAuthor(
43
+ Author::create()
44
+ ->withName('Author in FB')
45
+ ->withDescription('Author user in facebook')
46
+ ->withURL('http://facebook.com/author')
47
+ )
48
+ ->withKicker('Some kicker of this article')
49
+ ->withCover(
50
+ Image::create()
51
+ ->withURL('https://jpeg.org/images/jpegls-home.jpg')
52
+ ->withCaption(
53
+ Caption::create()
54
+ ->appendText('Some caption to the image')
55
+ )
56
+ )
57
+ )
58
+ // Paragraph1
59
+ ->addChild(
60
+ Paragraph::create()
61
+ ->appendText('Some text to be within a paragraph for testing.')
62
+ )
63
+ // Paragraph2
64
+ ->addChild(
65
+ Paragraph::create()
66
+ ->appendText('Other text to be within a second paragraph for testing.')
67
+ )
68
+ // Slideshow
69
+ ->addChild(
70
+ SlideShow::create()
71
+ ->addImage(
72
+ Image::create()
73
+ ->withURL('https://jpeg.org/images/jpegls-home.jpg')
74
+ )
75
+ ->addImage(
76
+ Image::create()
77
+ ->withURL('https://jpeg.org/images/jpegls-home2.jpg')
78
+ )
79
+ ->addImage(
80
+ Image::create()
81
+ ->withURL('https://jpeg.org/images/jpegls-home3.jpg')
82
+ )
83
+ )
84
+ // Paragraph3
85
+ ->addChild(
86
+ Paragraph::create()
87
+ ->appendText('Some text to be within a paragraph for testing.')
88
+ )
89
+ // Ad
90
+ ->addChild(
91
+ Ad::create()
92
+ ->withSource('http://foo.com')
93
+ )
94
+ // Paragraph4
95
+ ->addChild(
96
+ Paragraph::create()
97
+ ->appendText('Other text to be within a second paragraph for testing.')
98
+ )
99
+ // Analytics
100
+ ->addChild(
101
+ Analytics::create()
102
+ ->withHTML(
103
+ <h1>Some custom code</h1>
104
+ <script>alert("test");</script>
105
+ )
106
+ )
107
+ // Footer
108
+ ->withFooter(
109
+ Footer::create()
110
+ ->withCredits('Some plaintext credits.')
111
+ );
112
+ ```
113
+
114
+ ### Rendering the `InstantArticle` Markup
115
+
116
+ 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:
117
+
118
+ ```php
119
+ $article->render('<!doctype html>');
120
+ ```
121
+
122
+ #### Rendered output of the `InstantArticle` object from above
123
+ ```xml
124
+ <!doctype html>
125
+ <html>
126
+ <head>
127
+ <link rel="canonical" href="http://foo.com/article.html"/>
128
+ <meta charset="utf-8"/>
129
+ <meta property="op:markup_version" content="v1.0"/>
130
+ <meta property="fb:use_automatic_ad_placement" content="true"/>
131
+ </head>
132
+ <body>
133
+ <article>
134
+ <header>
135
+ <figure>
136
+ <img src="https://jpeg.org/images/jpegls-home.jpg"/>
137
+ <figcaption>Some caption to the image</figcaption>
138
+ </figure>
139
+ <h1>Big Top Title</h1>
140
+ <h2>Smaller SubTitle</h2>
141
+ <time class="op-published" datetime="1984-08-14T19:30:00+00:00">August 14th, 7:30pm</time>
142
+ <time class="op-modified" datetime="2016-02-10T10:00:00+00:00">February 10th, 10:00am</time>
143
+ <address>
144
+ <a>Author Name</a>
145
+ Author more detailed description
146
+ </address>
147
+ <address>
148
+ <a href="http://facebook.com/author" rel="facebook">Author in FB</a>
149
+ 'Author user in facebook'.
150
+ </address>
151
+ <h3 class="op-kicker">Some kicker of this article</h3>
152
+ </header>
153
+ <p>Some text to be within a paragraph for testing.</p>
154
+ <p>Other text to be within a second paragraph for testing.</p>
155
+ <figure class="op-slideshow">
156
+ <figure>
157
+ <img src="https://jpeg.org/images/jpegls-home.jpg"/>
158
+ </figure>
159
+ <figure>
160
+ <img src="https://jpeg.org/images/jpegls-home2.jpg"/>
161
+ </figure>
162
+ <figure>
163
+ <img src="https://jpeg.org/images/jpegls-home3.jpg"/>
164
+ </figure>
165
+ </figure>
166
+ <p>Some text to be within a paragraph for testing.</p>
167
+ <figure class="op-ad">
168
+ <iframe src="http://foo.com"></iframe>
169
+ </figure>
170
+ <p>Other text to be within a second paragraph for testing.</p>
171
+ <figure class="op-tracker">
172
+ <iframe>
173
+ <h1>Some custom code</h1>
174
+ <script>alert("test");</script>
175
+ </iframe>
176
+ </figure>
177
+ <footer>
178
+ <aside>Some plaintext credits.</aside>
179
+ </footer>
180
+ </article>
181
+ </body>
182
+ </html>
183
+ ```
184
+
185
+ ## Transformer
186
+ 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.
187
+
188
+ ### Transformer Configuration
189
+
190
+ 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.
191
+
192
+ - Each rule in the configuration file should live in the `rules` array
193
+ - Each entry should have at least the `class` attribute set
194
+ - 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
195
+
196
+ The transformer pseudo-algorithm is:
197
+
198
+ ```php
199
+ $document = loadHTML($input_file);
200
+ foreach($document->childNodes as $node) {
201
+ foreach($rules as $rule) {
202
+ if ($rule->matches($context, $node)) {
203
+ // Apply rule...
204
+ }
205
+ }
206
+ }
207
+ ```
208
+
209
+ 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:
210
+
211
+ - Matches context
212
+ - Matches selector
213
+
214
+ #### Matching context
215
+ Context is the container element that is now in the pipe being processed. This is returned by the method:
216
+
217
+ ```php
218
+ public function getContextClass() {
219
+ return InstantArticle::getClassName();
220
+ }
221
+ ```
222
+
223
+ If the `Rule` will be handling more than one context, it is possible by returning an array of classes:
224
+
225
+ ```php
226
+ public function getContextClass() {
227
+ return array(InstantArticle::getClassName(), Header::getClassName());
228
+ }
229
+ ```
230
+
231
+ #### Matching selector
232
+ 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).
233
+
234
+ The selector field will be used as a *CSS selector*; or as an *Xpath selector* if beginning with `/`.
235
+
236
+ **Example: using a *CSS Selector* to match a rule**
237
+ ```javascript
238
+ {
239
+ "class": "HeaderRule",
240
+ "selector" : "div.header"
241
+ }
242
+ ```
243
+
244
+ **Example: using an *Xpath Selector* to match a rule**
245
+ ```javascript
246
+ {
247
+ "class": "HeaderRule",
248
+ "selector" : "//div[class=header]"
249
+ }
250
+ ```
251
+
252
+ ### Example
253
+
254
+ #### Input HTML
255
+ The following markup is a sample of what could be used as input to the Transformer:
256
+
257
+ ```html
258
+ <html>
259
+ <head>
260
+ <script type="text/javascript" href="http://domain.com/javascript.js" />
261
+ </head>
262
+ <body>
263
+ <div class="header">
264
+ <div class="title">
265
+ <h1>The article title</h1>
266
+ <h2>Sub Title</h2>
267
+ <span class="author">Author name</author>
268
+ </div>
269
+ <div class="hero-image">
270
+ <img src="http://domain.com/image.png" />
271
+ <div class="image-caption">
272
+ Some amazing moment captured by Photographer
273
+ </div>
274
+ </div>
275
+ </div>
276
+ <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>
277
+ <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>
278
+ <div class="image">
279
+ <img src="http://domain.com/image.png" />
280
+ <div class="image-caption">
281
+ Some amazing moment captured by Photographer
282
+ </div>
283
+ </div>
284
+ <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>
285
+ </body>
286
+ </html>
287
+ ```
288
+
289
+ #### Full rule configuration file for the HTML above
290
+
291
+ This rule configuration will:
292
+
293
+ - run bottom-up
294
+ - check if matches "class" (context)
295
+ - check if matches "selector" (css or xpath)
296
+ - Run the rule (calling the callback method `transform()`)
297
+
298
+ ```javascript
299
+ {
300
+ "rules" :
301
+ [
302
+ {
303
+ "class": "TextNodeRule"
304
+ },
305
+ {
306
+ "class": "PassThroughRule",
307
+ "selector" : "html"
308
+ },
309
+ {
310
+ "class": "PassThroughRule",
311
+ "selector" : "head"
312
+ },
313
+ {
314
+ "class": "PassThroughRule",
315
+ "selector" : "script"
316
+ },
317
+ {
318
+ "class": "PassThroughRule",
319
+ "selector" : "body"
320
+ },
321
+ {
322
+ "class": "ItalicRule",
323
+ "selector" : "i"
324
+ },
325
+ {
326
+ "class": "BoldRule",
327
+ "selector" : "b"
328
+ },
329
+ {
330
+ "class": "ParagraphRule",
331
+ "selector" : "p"
332
+ },
333
+ {
334
+ "class": "HeaderTitleRule",
335
+ "selector" : "div.title h1"
336
+ },
337
+ {
338
+ "class": "HeaderSubTitleRule",
339
+ "selector" : "div.title h2"
340
+ },
341
+ {
342
+ "class": "HeaderRule",
343
+ "selector" : "div.header"
344
+ },
345
+ {
346
+ "class": "AuthorRule",
347
+ "selector" : "span.author",
348
+ "properties" : {
349
+ "author.name" : {
350
+ "type" : "string",
351
+ "selector" : "span"
352
+ }
353
+ }
354
+ },
355
+ {
356
+ "class": "CaptionRule",
357
+ "selector" : "div.image-caption"
358
+ },
359
+ {
360
+ "class": "ImageRule",
361
+ "selector" : "div.image",
362
+ "properties" : {
363
+ "image.url" : {
364
+ "type" : "string",
365
+ "selector" : "img",
366
+ "attribute": "src"
367
+ },
368
+ "image.caption" : {
369
+ "type" : "element",
370
+ "selector" : "div.image-caption"
371
+ }
372
+ }
373
+ },
374
+ {
375
+ "class": "HeaderImageRule",
376
+ "selector" : "div.hero-image",
377
+ "properties" : {
378
+ "image.url" : {
379
+ "type" : "string",
380
+ "selector" : "img",
381
+ "attribute": "src"
382
+ },
383
+ "image.caption" : {
384
+ "type" : "element",
385
+ "selector" : "div.image-caption"
386
+ }
387
+ }
388
+ }
389
+ ]
390
+ }
391
+ ```
392
+
393
+ ### Creating Custom Rules
394
+ Each custom rule implemented should comply with full contract of the `Rule` abstract class.
395
+
396
+ ```php
397
+ class MyCustomRule extends Rule
398
+ {
399
+ public function matchesContext($context)
400
+ {}
401
+
402
+ public function matchesNode($node)
403
+ {}
404
+
405
+ public function apply($transformer, $container, $node)
406
+ {}
407
+ }
408
+ ```
409
+
410
+ 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.
411
+
412
+ ### Invoking Transformer
413
+
414
+ To transform your markup into InstantArticle markup, follow these steps:
415
+
416
+ - Create an `InstantArticle` instance
417
+ - Create a `Transformer` and load it with rules (programmatically or from a file)
418
+ - Load/retrieve the HTML content file in the original markup
419
+ - Run the Transformer
420
+ - Check for errors/warnings
421
+
422
+ #### Example
423
+ ```php
424
+ // Loads the rules content file
425
+ $rules_file_content = file_get_contents("simple-rules.json", true);
426
+
427
+ // Instantiate Instant article
428
+ $instant_article = InstantArticle::create();
429
+
430
+ // Creates the transformer and loads the rules
431
+ $transformer = new Transformer();
432
+ $transformer->loadRules($rules_file_content);
433
+
434
+ // Example loads the html from a file
435
+ $html_file = file_get_contents("simple.html", true);
436
+
437
+ // Ignores errors on HTML parsing
438
+ libxml_use_internal_errors(true);
439
+ $document = new \DOMDocument();
440
+ $document->loadHTML($html_file);
441
+ libxml_use_internal_errors(false);
442
+
443
+ // Invokes transformer
444
+ $transformer->transform($instant_article, $document);
445
+
446
+ // Get errors from transformer
447
+ $warnings = $transformer->getWarnings();
448
+
449
+ // Renders the InstantArticle markup format
450
+ $result = $instant_article->render();
451
+ ```
452
+
453
+ ## Client
454
+
455
+ 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:
456
+
457
+ ```php
458
+ $article = InstantArticle::create();
459
+ $transformer->transform($article, $someDocument);
460
+
461
+ // Instantiate an API client
462
+ $client = Client::create(
463
+ 'APP_ID'
464
+ 'APP_SECRET',
465
+ 'ACCESS_TOKEN',
466
+ 'PAGE_ID',
467
+ false // development envirorment?
468
+ );
469
+
470
+ // Import the article
471
+ try {
472
+ $client->importArticle($article, $take_live);
473
+ } catch (Exception $e) {
474
+ echo 'Could not import the article: '.$e->getMessage();
475
+ }
476
+ ```
477
+
478
+ ### `Helper` class
479
+
480
+ 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:
481
+
482
+ ```php
483
+ $userAccessToken = 'USER_ACCESS_TOKEN';
484
+
485
+ // Instantiate a client helper
486
+ $helper = Helper::create(
487
+ 'APP_ID',
488
+ 'APP_SECRET'
489
+ );
490
+
491
+ // Grab pages you are admin of and tokens
492
+ $pagesAndTokens = $helper->getPagesAndTokens($userAccessToken)->all();
493
+ foreach ($pagesAndTokens as $pageAndToken) {
494
+ echo 'Page ID: ' . $pageAndToken->getField('id');
495
+ echo 'Page name: ' . $pageAndToken->getField('name');
496
+ echo 'Page access token: ' . $pageAndToken->getField('access_token');
497
+ }
498
+ ```
vendor/facebook/facebook-instant-articles-sdk-php/phpunit.xml ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="utf-8" ?>
2
+ <phpunit bootstrap="./tests/bootstrap.php">
3
+ <testsuites>
4
+ <testsuite name="The project's test suite">
5
+ <directory>./tests</directory>
6
+ </testsuite>
7
+ </testsuites>
8
+ </phpunit>
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Client/Client.php ADDED
@@ -0,0 +1,175 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+
10
+ namespace Facebook\InstantArticles\Client;
11
+
12
+ use Facebook\Facebook;
13
+ use Facebook\InstantArticles\Elements\InstantArticle;
14
+ use Facebook\Authentication\AccessToken;
15
+ use Facebook\InstantArticles\Validators\Type;
16
+
17
+ class Client
18
+ {
19
+ const EDGE_NAME = '/instant_articles';
20
+
21
+ /**
22
+ * @var facebook The main Facebook service client.
23
+ */
24
+ private $facebook;
25
+
26
+ /**
27
+ * @var int ID of the Facebook Page we are using for Instant Articles
28
+ */
29
+ protected $pageID;
30
+
31
+ /**
32
+ * @var bool|false Are we using the Instant Articles development sandbox?
33
+ */
34
+ protected $developmentMode = false;
35
+
36
+ /**
37
+ * @param Facebook\Facebook $facebook the main Facebook service client
38
+ * @param string $pageID Specify the Facebook Page to use for Instant Articles
39
+ * @param bool $developmentMode|false Configure the service to use the Instant Articles development sandbox
40
+ */
41
+ public function __construct($facebook, $pageID, $developmentMode = false)
42
+ {
43
+ Type::enforce($facebook, 'Facebook\Facebook');
44
+ Type::enforce($pageID, Type::STRING);
45
+ Type::enforce($developmentMode, Type::BOOLEAN);
46
+
47
+ // TODO throw if $facebook doesn't have a default_access_token
48
+ $this->facebook = $facebook;
49
+ $this->pageID = $pageID;
50
+ $this->developmentMode = $developmentMode;
51
+ }
52
+
53
+ /**
54
+ * Creates a client with a proper Facebook client instance.
55
+ *
56
+ * @param string $app_id
57
+ * @param string $app_secret
58
+ * @param string $accessToken The page access token used to query the Facebook Graph API
59
+ * @param string $pageID Specify the Facebook Page to use for Instant Articles
60
+ * @param bool $developmentMode|false Configure the service to use the Instant Articles development sandbox
61
+ *
62
+ * @throws FacebookSDKException
63
+ */
64
+ public static function create($appID, $appSecret, $accessToken, $pageID, $developmentMode = false)
65
+ {
66
+ Type::enforce($appID, Type::STRING);
67
+ Type::enforce($appSecret, Type::STRING);
68
+ Type::enforce($accessToken, Type::STRING);
69
+
70
+ $facebook = new Facebook([
71
+ 'app_id' => $appID,
72
+ 'app_secret' => $appSecret,
73
+ 'default_access_token' => $accessToken,
74
+ ]);
75
+
76
+ return new static($facebook, $pageID, $developmentMode);
77
+ }
78
+
79
+ /**
80
+ * Import an article into your Instant Articles library.
81
+ *
82
+ * @param InstantArticle $article The article to import
83
+ * @param bool|false $take_live Specifies if this article should be taken live or not. Optional. Default: false.
84
+ */
85
+ public function importArticle($article, $takeLive = false)
86
+ {
87
+ Type::enforce($article, InstantArticle::getClassName());
88
+ Type::enforce($takeLive, Type::BOOLEAN);
89
+
90
+ // Never try to take live if we're in development (the API would throw an error if we tried)
91
+ $takeLive = $this->developmentMode ? false : $takeLive;
92
+
93
+ // Assume default access token is set on $this->facebook
94
+ $this->facebook->post($this->pageID . Client::EDGE_NAME, [
95
+ 'html_source' => $article->render(),
96
+ 'take_live' => $takeLive,
97
+ 'development_mode' => $this->developmentMode,
98
+ ]);
99
+ }
100
+
101
+ /**
102
+ * Removes an article from your Instant Articles library.
103
+ *
104
+ * @param string $canonicalURL The canonical URL of the article to delete.
105
+ * @return \Facebook\InstantArticles\Client\InstantArticleStatus
106
+ *
107
+ * @todo Consider returning the \Facebook\FacebookResponse object sent by
108
+ * \Facebook\Facebook::delete(). For now we trust that if an Instant
109
+ * Article ID exists for the Canonical URL the delete operation will work.
110
+ */
111
+ public function removeArticle($canonicalURL)
112
+ {
113
+ if (!$canonicalURL) {
114
+ return InstantArticleStatus::notFound(array('$canonicalURL param not passed to ' . __FUNCTION__ . '.'));
115
+ }
116
+
117
+ Type::enforce($canonicalURL, Type::STRING);
118
+
119
+ if ($articleID = $this->getArticleIDFromCanonicalURL($canonicalURL)) {
120
+ $this->facebook->delete($articleID);
121
+ return InstantArticleStatus::success();
122
+ }
123
+ return InstantArticleStatus::notFound(array('An Instant Article ID ' . $articleID . ' was not found for ' . $canonicalURL . ' in ' . __FUNCTION__ . '.'));
124
+ }
125
+
126
+ /**
127
+ * Get an Instant Article ID on its canonical URL.
128
+ *
129
+ * @param string $canonicalURL The canonical URL of the article to get the status for.
130
+ * @return int|null the article ID or null if not found
131
+ */
132
+ public function getArticleIDFromCanonicalURL($canonicalURL)
133
+ {
134
+ Type::enforce($canonicalURL, Type::STRING);
135
+
136
+ $response = $this->facebook->get('?id=' . $canonicalURL . '&fields=instant_article');
137
+ $instantArticle = $response->getGraphNode()->getField('instant_article');
138
+
139
+ if (!$instantArticle) {
140
+ return null;
141
+ }
142
+
143
+ $articleID = $instantArticle->getField('id');
144
+ return $articleID;
145
+ }
146
+
147
+
148
+ /**
149
+ * Get the last submission status of an Instant Article.
150
+ *
151
+ * @param string|null $articleID the article ID
152
+ * @return InstantArticleStatus
153
+ */
154
+ public function getLastSubmissionStatus($articleID)
155
+ {
156
+ if (!$articleID) {
157
+ return InstantArticleStatus::notFound();
158
+ }
159
+
160
+ Type::enforce($articleID, Type::STRING);
161
+
162
+ // Get the latest import status of this article
163
+ $response = $this->facebook->get($articleID . '?fields=most_recent_import_status');
164
+ $articleStatus = $response->getGraphNode()->getField('most_recent_import_status');
165
+
166
+ $messages = array();
167
+ if (isset($articleStatus['errors'])) {
168
+ foreach ($articleStatus['errors'] as $error) {
169
+ $messages[] = ServerMessage::fromLevel($error['level'], $error['message']);
170
+ }
171
+ }
172
+
173
+ return InstantArticleStatus::fromStatus($articleStatus['status'], $messages);
174
+ }
175
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Client/ClientException.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
+
10
+ namespace Facebook\InstantArticles\Client;
11
+
12
+ class ClientException extends Exception
13
+ {
14
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Client/Helper.php ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Client;
10
+
11
+ use Facebook\Facebook;
12
+ use Facebook\Exceptions\FacebookResponseException;
13
+ use Facebook\Exceptions\FacebookSDKException;
14
+ use Facebook\Authentication\AccessToken;
15
+ use Facebook\InstantArticles\Validators\Type;
16
+
17
+ class Helper
18
+ {
19
+ /**
20
+ * @var service The main Facebook service client.
21
+ */
22
+ protected $facebook;
23
+
24
+ /**
25
+ * @param Facebook\Facebook $facebook the main Facebook service client
26
+ */
27
+ public function __construct($facebook)
28
+ {
29
+ Type::enforce($facebook, 'Facebook\Facebook');
30
+
31
+ // TODO throw if $facebook doesn't have a default_access_token
32
+ $this->facebook = $facebook;
33
+ }
34
+
35
+ /**
36
+ * Instantiates a new Helper object.
37
+ *
38
+ * @param string $appID
39
+ * @param string $appSecret
40
+ *
41
+ * @throws FacebookSDKException
42
+ */
43
+ public static function create($appID, $appSecret)
44
+ {
45
+ Type::enforce($appID, Type::STRING);
46
+ Type::enforce($appSecret, Type::STRING);
47
+
48
+ $facebook = new Facebook([
49
+ 'app_id' => $appID,
50
+ 'app_secret' => $appSecret,
51
+ ]);
52
+
53
+ return new static($facebook);
54
+ }
55
+
56
+ /**
57
+ * Returns the set of pages and their associated tokens based on a
58
+ * short-lived user access token.
59
+ *
60
+ * @param AccessToken $accessToken A short-lived user access token.
61
+ *
62
+ * @return array
63
+ *
64
+ * @throws FacebookSDKException
65
+ */
66
+ public function getPagesAndTokens($accessToken)
67
+ {
68
+ Type::enforce($accessToken, 'Facebook\Authentication\AccessToken');
69
+
70
+ // If we don't have a long-lived user token, exchange for one
71
+ if (! $accessToken->isLongLived()) {
72
+ try {
73
+ // The OAuth 2.0 client handler helps us manage access tokens
74
+ $OAuth2Client = $this->facebook->getOAuth2Client();
75
+ $accessToken = $OAuth2Client->getLongLivedAccessToken($accessToken);
76
+ } catch (Facebook\Exceptions\FacebookResponseException $e) {
77
+ throw new FacebookSDKException(
78
+ "Failed to exchange short-lived access token for long-lived access token."
79
+ );
80
+ }
81
+ }
82
+
83
+ // Set this access token as the default
84
+ $this->facebook->setDefaultAccessToken($accessToken);
85
+
86
+ // Request the list of pages and associated page tokens that are
87
+ // connected to this user
88
+ try {
89
+ $response = $this->facebook->get('/me/accounts?fields=name,id,access_token,supports_instant_articles');
90
+ } catch (Facebook\Exceptions\FacebookResponseException $e) {
91
+ throw new FacebookSDKException('Graph API returned an error: ' . $e.getMessage());
92
+ }
93
+
94
+ // Return the array of page objects for this user
95
+ return $response->getGraphEdge();
96
+ }
97
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Client/InstantArticleStatus.php ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Client;
10
+
11
+ use Facebook\InstantArticles\Validators\Type;
12
+
13
+ class InstantArticleStatus
14
+ {
15
+ /**
16
+ * @var service The main Facebook service entity.
17
+ */
18
+ const SUCCESS = 'success';
19
+ const NOT_FOUND = 'not_found';
20
+ const IN_PROGRESS = 'in_progress';
21
+ const FAILED = 'failed';
22
+ const UNKNOWN = 'unknown';
23
+
24
+ private $messages = array();
25
+
26
+ /**
27
+ * Instantiates a new InstantArticleStatus object.
28
+ *
29
+ * @param string $app_id
30
+ * @param string $app_secret
31
+ *
32
+ * @throws FacebookSDKException
33
+ */
34
+ public function __construct($status, $messages = array())
35
+ {
36
+ Type::enforceWithin(
37
+ $status,
38
+ array(
39
+ self::SUCCESS,
40
+ self::NOT_FOUND,
41
+ self::IN_PROGRESS,
42
+ self::FAILED,
43
+ self::UNKNOWN
44
+ )
45
+ );
46
+ Type::enforceArrayOf(
47
+ $messages,
48
+ ServerMessage::getClassName()
49
+ );
50
+ $this->status = $status;
51
+ $this->messages = $messages;
52
+ }
53
+
54
+ /**
55
+ * Creates a instance from a status string,.
56
+ *
57
+ * @param string $status the status string, case insensitive.
58
+ * @param array $messages the message from the server
59
+ *
60
+ * @return InstantArticleStatus
61
+ */
62
+ public static function fromStatus($status, $messages)
63
+ {
64
+ $status = strtolower($status);
65
+ $validStatus = Type::isWithin(
66
+ $status,
67
+ array(
68
+ self::SUCCESS,
69
+ self::NOT_FOUND,
70
+ self::IN_PROGRESS,
71
+ self::FAILED
72
+ )
73
+ );
74
+ if ($validStatus) {
75
+ return new self($status, $messages);
76
+ } else {
77
+ \Logger::getLogger('facebook-instantarticles-client')
78
+ ->info("Unknown status '$status'. Are you using the last SDK version?");
79
+ return new self(self::UNKNOWN, $messages);
80
+ }
81
+ }
82
+
83
+ public static function success($messages = array())
84
+ {
85
+ return new self(self::SUCCESS, $messages);
86
+ }
87
+
88
+ public static function notFound($messages = array())
89
+ {
90
+ return new self(self::NOT_FOUND, $messages);
91
+ }
92
+
93
+ public static function inProgress($messages = array())
94
+ {
95
+ return new self(self::IN_PROGRESS, $messages);
96
+ }
97
+
98
+ public static function failed($messages = array())
99
+ {
100
+ return new self(self::FAILED, $messages);
101
+ }
102
+
103
+ public static function unknown($messages = array())
104
+ {
105
+ return new self(self::UNKNOWN, $messages);
106
+ }
107
+
108
+ public function addMessage($message)
109
+ {
110
+ Type::enforce(
111
+ $message,
112
+ ServerMessage::getClassName()
113
+ );
114
+ $this->messages[] = $message;
115
+ }
116
+
117
+ public function getMessages()
118
+ {
119
+ return $this->messages;
120
+ }
121
+
122
+ public function getStatus()
123
+ {
124
+ return $this->status;
125
+ }
126
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Client/ServerMessage.php ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Client;
10
+
11
+ use Facebook\InstantArticles\Validators\Type;
12
+
13
+ class ServerMessage
14
+ {
15
+ const FATAL = 'fatal';
16
+ const ERROR = 'error';
17
+ const WARNING = 'warning';
18
+ const INFO = 'info';
19
+
20
+ private $level;
21
+ private $message;
22
+
23
+ public function __construct($level, $message)
24
+ {
25
+ Type::enforceWithin(
26
+ $level,
27
+ array(
28
+ self::FATAL,
29
+ self::ERROR,
30
+ self::WARNING,
31
+ self::INFO
32
+ )
33
+ );
34
+ Type::enforce(
35
+ $message,
36
+ Type::STRING
37
+ );
38
+ $this->level = $level;
39
+ $this->message = $message;
40
+ }
41
+
42
+ /**
43
+ * Creates a message from a level string, using INFO if a invalid level string is provided.
44
+ *
45
+ * @param string $level the level string, case insensitive.
46
+ * @param string $message the message from the server
47
+ *
48
+ * @return ServerMessage the message with the proper level
49
+ */
50
+ public static function fromLevel($level, $message)
51
+ {
52
+ $level = strtolower($level);
53
+ $validLevel = Type::isWithin(
54
+ $level,
55
+ array(
56
+ self::FATAL,
57
+ self::ERROR,
58
+ self::WARNING,
59
+ self::INFO
60
+ )
61
+ );
62
+ if ($validLevel) {
63
+ return new self($level, $message);
64
+ } else {
65
+ \Logger::getLogger('facebook-instantarticles-client')
66
+ ->info('Unknown message level "$level". Are you using the last SDK version?');
67
+ return new self(self::INFO, $message);
68
+ }
69
+ }
70
+
71
+ public static function fatal($message)
72
+ {
73
+ return new self(self::FATAL, $message);
74
+ }
75
+
76
+ public static function error($message)
77
+ {
78
+ return new self(self::ERROR, $message);
79
+ }
80
+
81
+ public static function warning($message)
82
+ {
83
+ return new self(self::WARNING, $message);
84
+ }
85
+
86
+ public static function info($message)
87
+ {
88
+ return new self(self::INFO, $message);
89
+ }
90
+
91
+
92
+ public function getMessage()
93
+ {
94
+ return $this->message;
95
+ }
96
+
97
+ public function getLevel()
98
+ {
99
+ return $this->level;
100
+ }
101
+
102
+ /**
103
+ * Auxiliary method to extract full qualified class name.
104
+ * @return string The full qualified name of class
105
+ */
106
+ public static function getClassName() {
107
+ return get_called_class();
108
+ }
109
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Ad.php ADDED
@@ -0,0 +1,222 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ * An Ad within for the article.
15
+ *
16
+ * Example:
17
+ * <figure class="op-ad">
18
+ * <iframe height="50" width="320">
19
+ * <!-- Include full ad code here -->
20
+ * </iframe>
21
+ * </figure>
22
+ *
23
+ * @see {link:https://developers.intern.facebook.com/docs/instant-articles/reference/audio}
24
+ */
25
+ class Ad extends Element
26
+ {
27
+ /**
28
+ * @var int The height of your ad.
29
+ */
30
+ private $height;
31
+
32
+ /**
33
+ * @var string The source of the content for your ad.
34
+ */
35
+ private $source;
36
+
37
+ /**
38
+ * @var int The width of your ad.
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
+ }
50
+
51
+ public static function create()
52
+ {
53
+ return new self();
54
+ }
55
+
56
+ /**
57
+ * @var boolean Ad will be reused if additional placement slots are available. False by default.
58
+ */
59
+ private $isDefaultForReuse = false;
60
+
61
+ /**
62
+ * Ad will be reused in additional impression slots.
63
+ */
64
+ public function enableDefaultForReuse()
65
+ {
66
+ $this->isDefaultForReuse = true;
67
+ return $this;
68
+ }
69
+
70
+ /**
71
+ * Ad will not be used in additional impression slots.
72
+ */
73
+ public function disableDefaultForReuse()
74
+ {
75
+ $this->isDefaultForReuse = false;
76
+ return $this;
77
+ }
78
+
79
+ /**
80
+ * Sets the height of your ad.
81
+ *
82
+ * @param int The height of your ad.
83
+ */
84
+ public function withHeight($height)
85
+ {
86
+ Type::enforce($height, Type::INTEGER);
87
+ $this->height = $height;
88
+
89
+ return $this;
90
+ }
91
+
92
+ /**
93
+ * Sets the source for the ad.
94
+ *
95
+ * @param string The source of the content for your ad.
96
+ */
97
+ public function withSource($source)
98
+ {
99
+ Type::enforce($source, Type::STRING);
100
+ $this->source = $source;
101
+
102
+ return $this;
103
+ }
104
+
105
+ /**
106
+ * Sets the width of your ad.
107
+ *
108
+ * @param int The width of your ad.
109
+ */
110
+ public function withWidth($width)
111
+ {
112
+ Type::enforce($width, Type::INTEGER);
113
+ $this->width = $width;
114
+
115
+ return $this;
116
+ }
117
+
118
+ /**
119
+ * Sets the unescaped HTML of your ad.
120
+ *
121
+ * @param \DOMNode $html The unescaped HTML of your ad.
122
+ */
123
+ public function withHTML($html)
124
+ {
125
+ Type::enforce($html, 'DOMNode');
126
+ $this->html = $html;
127
+
128
+ return $this;
129
+ }
130
+
131
+ /**
132
+ * @return True if Ad has been set to reusable.
133
+ */
134
+ public function getIsDefaultForReuse()
135
+ {
136
+ return $this->isDefaultForReuse;
137
+ }
138
+
139
+ /**
140
+ * Gets the height of your ad.
141
+ *
142
+ * @return int The height of your ad.
143
+ */
144
+ public function getHeight()
145
+ {
146
+ return $this->height;
147
+ }
148
+
149
+ /**
150
+ * Gets the source for the ad.
151
+ *
152
+ * @return string The source of the content for your ad.
153
+ */
154
+ public function getSource()
155
+ {
156
+ return $this->source;
157
+ }
158
+
159
+ /**
160
+ * Gets the width of your ad.
161
+ *
162
+ * @return int The width of your ad.
163
+ */
164
+ public function getWidth()
165
+ {
166
+ return $this->width;
167
+ }
168
+
169
+ /**
170
+ * Gets the unescaped HTML of your ad.
171
+ *
172
+ * @return \DOMNode The unescaped HTML of your ad.
173
+ */
174
+ public function getHtml()
175
+ {
176
+ return $this->html;
177
+ }
178
+
179
+ /**
180
+ * Structure and create the full Ad in a DOMElement.
181
+ *
182
+ * @param DOMDocument $document - The document where this element will be appended (optional).
183
+ */
184
+ public function toDOMElement($document = null)
185
+ {
186
+ if (!$document) {
187
+ $document = new \DOMDocument();
188
+ }
189
+ $figure = $document->createElement('figure');
190
+ $iframe = $document->createElement('iframe');
191
+
192
+ $figure->appendChild($iframe);
193
+ $figure->setAttribute(
194
+ 'class',
195
+ 'op-ad'
196
+ .($this->isDefaultForReuse ? ' op-ad-default' : '')
197
+ );
198
+
199
+ if ($this->source) {
200
+ $iframe->setAttribute('src', $this->source);
201
+ }
202
+
203
+ if ($this->width) {
204
+ $iframe->setAttribute('width', $this->width);
205
+ }
206
+
207
+ if ($this->height) {
208
+ $iframe->setAttribute('height', $this->height);
209
+ }
210
+
211
+ // Ad markup
212
+ if ($this->html) {
213
+ // Here we do not care about what is inside the iframe
214
+ // because it'll be rendered in a sandboxed webview
215
+ $this->dangerouslyAppendUnescapedHTML($iframe, $this->html);
216
+ } else {
217
+ $iframe->appendChild($document->createTextNode(''));
218
+ }
219
+
220
+ return $figure;
221
+ }
222
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Analytics.php ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ * Tracking code for your article
15
+ *
16
+ * Example:
17
+ * <figure class="op-tracker">
18
+ * <iframe src="https://www.myserver.com/trackingcode"></iframe>
19
+ * </figure>
20
+ *
21
+ * or
22
+ *
23
+ * <figure class="op-tracker">
24
+ * <iframe>
25
+ * <!-- Include full analytics code here -->
26
+ * </iframe>
27
+ * </figure>
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
+ }
46
+
47
+ public static function create()
48
+ {
49
+ return new self();
50
+ }
51
+
52
+ /**
53
+ * Sets the source for the ad.
54
+ *
55
+ * @param string The source of the content for your ad.
56
+ */
57
+ public function withSource($source)
58
+ {
59
+ Type::enforce($source, Type::STRING);
60
+ $this->source = $source;
61
+
62
+ return $this;
63
+ }
64
+
65
+ /**
66
+ * Sets the unescaped HTML of your ad.
67
+ *
68
+ * @param \DOMNode The unescaped HTML of your ad.
69
+ */
70
+ public function withHTML($html)
71
+ {
72
+ Type::enforce($html, 'DOMNode');
73
+ $this->html = $html;
74
+
75
+ return $this;
76
+ }
77
+
78
+ /**
79
+ * Gets the source for the analytics.
80
+ *
81
+ * @return string The source of the content for your analytics.
82
+ */
83
+ public function getSource()
84
+ {
85
+ return $this->source;
86
+ }
87
+
88
+ /**
89
+ * Gets the unescaped HTML of your analytics.
90
+ *
91
+ * @return \DOMNode The unescaped HTML of your analytics.
92
+ */
93
+ public function getHtml()
94
+ {
95
+ return $this->html;
96
+ }
97
+
98
+ /**
99
+ * Structure and create the full ArticleAd in a DOMElement.
100
+ *
101
+ * @param DOMDocument $document - The document where this element will be appended (optional).
102
+ */
103
+ public function toDOMElement($document = null)
104
+ {
105
+ if (!$document) {
106
+ $document = new \DOMDocument();
107
+ }
108
+ $figure = $document->createElement('figure');
109
+ $iframe = $document->createElement('iframe');
110
+
111
+ $figure->appendChild($iframe);
112
+ $figure->setAttribute('class', 'op-tracker');
113
+
114
+ if ($this->source) {
115
+ $iframe->setAttribute('src', $this->source);
116
+ }
117
+
118
+ // Analytics markup
119
+ if ($this->html) {
120
+ // Here we do not care about what is inside the iframe
121
+ // because it'll be rendered in a sandboxed webview
122
+ $this->dangerouslyAppendUnescapedHTML($iframe, $this->html);
123
+ } else {
124
+ $iframe->appendChild($document->createTextNode(''));
125
+ }
126
+
127
+ return $figure;
128
+ }
129
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Anchor.php ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ /**
12
+ * An anchor.
13
+ *
14
+ * @see {link:https://developers.intern.facebook.com/docs/instant-articles/reference/body-text}
15
+ */
16
+ class Anchor extends FormattedText
17
+ {
18
+ /**
19
+ * @var string URL to link to.
20
+ */
21
+ private $href;
22
+
23
+ /**
24
+ * @var string rel.
25
+ */
26
+ private $rel;
27
+
28
+ /**
29
+ * @var string content.
30
+ */
31
+ private $content;
32
+
33
+ private function __construct()
34
+ {
35
+ }
36
+
37
+ public static function create()
38
+ {
39
+ return new self();
40
+ }
41
+
42
+ /**
43
+ * @param string the anchor link
44
+ */
45
+ public function withHref($href)
46
+ {
47
+ $this->href = $href;
48
+
49
+ return $this;
50
+ }
51
+
52
+ /**
53
+ * @param string the anchor rel attribute
54
+ */
55
+ public function withRel($rel)
56
+ {
57
+ $this->rel = $rel;
58
+
59
+ return $this;
60
+ }
61
+
62
+ /**
63
+ * @return string the anchor link
64
+ */
65
+ public function getHref()
66
+ {
67
+ return $this->href;
68
+ }
69
+
70
+ /**
71
+ * @return string the rel attribute
72
+ */
73
+ public function getRel()
74
+ {
75
+ return $this->rel;
76
+ }
77
+
78
+ /**
79
+ * Structure and create <a> node.
80
+ *
81
+ * @param DOMDocument $document - The document where this element will be appended (optional).
82
+ */
83
+ public function toDOMElement($document = null)
84
+ {
85
+ if (!$document) {
86
+ $document = new \DOMDocument();
87
+ }
88
+ $anchor = $document->createElement('a');
89
+
90
+ if ($this->href) {
91
+ $anchor->setAttribute('href', $this->href);
92
+ }
93
+ if ($this->rel) {
94
+ $anchor->setAttribute('rel', $this->rel);
95
+ }
96
+
97
+ $anchor->appendChild($this->textToDOMDocumentFragment($document));
98
+
99
+ return $anchor;
100
+ }
101
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/AnimatedGIF.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ /**
12
+ * An AnimatedGif
13
+ * Also consider to use one of the other media types for an article:
14
+ * <ul>
15
+ * <li>@see Audio</li>
16
+ * <li>@see Image</li>
17
+ * <li>@see Video</li>
18
+ * <li>@see SlideShow</li>
19
+ * <li>@see Map</li>
20
+ * </ul>.
21
+ *
22
+ * Example:
23
+ * <figure>
24
+ * <img src="http://mydomain.com/path/to/animated.gif" />
25
+ * <figcaption>This image is amazing</figcaption>
26
+ * </figure>
27
+ *
28
+ * @see {link:https://developers.intern.facebook.com/docs/instant-articles/reference/animated-gif}
29
+ */
30
+ class AnimatedGIF extends Image
31
+ {
32
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Audible.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ * Abstract class Audible
15
+ * This class represents all elements that can contain Audio
16
+ * <ul>
17
+ * <li>@see Image</li>
18
+ * <li>@see SlideShow</li>
19
+ * </ul>.
20
+ *
21
+ * Example:
22
+ * <audio>
23
+ * <source src="http://mydomain.com/path/to/audio.mp3" />
24
+ * </audio>
25
+ *
26
+ * @see {link:https://developers.intern.facebook.com/docs/instant-articles/reference/image}
27
+ */
28
+ abstract class Audible extends Element
29
+ {
30
+ /**
31
+ * Adds audio to this image.
32
+ *
33
+ * @param Audio The audio object
34
+ */
35
+ abstract public function withAudio($audio);
36
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Audio.php ADDED
@@ -0,0 +1,195 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ * An audio within for the article.
15
+ * Also consider to use one of the other media types for an article:
16
+ * <ul>
17
+ * <li>@see Image</li>
18
+ * <li>@see Video</li>
19
+ * <li>@see SlideShow</li>
20
+ * <li>@see Map</li>
21
+ * </ul>.
22
+ *
23
+ * Example:
24
+ * <audio title="audio title">
25
+ * <source src="http://foo.com/mp3">
26
+ * </audio>
27
+ *
28
+ * @see {link:https://developers.intern.facebook.com/docs/instant-articles/reference/audio}
29
+ */
30
+ class Audio extends Element
31
+ {
32
+ /**
33
+ * @var string The audio title
34
+ */
35
+ private $title;
36
+
37
+ /**
38
+ * @var string The string url for the audio file
39
+ */
40
+ private $url;
41
+
42
+ /**
43
+ * @var string Can be set with: empty ("") (Default), "muted" or "autoplay"
44
+ */
45
+ private $playback;
46
+
47
+ /**
48
+ * @var boolean stores the usage or not of autoplay for audio
49
+ */
50
+ private $autoplay;
51
+
52
+ /**
53
+ * @var boolean stores status of muted for this audio
54
+ */
55
+ private $muted;
56
+
57
+ private function __construct()
58
+ {
59
+ }
60
+
61
+ public static function create()
62
+ {
63
+ return new self();
64
+ }
65
+
66
+ /**
67
+ * Sets the URL for the audio. It is REQUIRED.
68
+ *
69
+ * @param string The url of image. Ie: http://domain.com/audiofile.mp3
70
+ */
71
+ public function withURL($url)
72
+ {
73
+ Type::enforce($url, Type::STRING);
74
+ $this->url = $url;
75
+
76
+ return $this;
77
+ }
78
+
79
+ /**
80
+ * The audio title.
81
+ *
82
+ * @param string the audio title that will be shown
83
+ */
84
+ public function withTitle($title)
85
+ {
86
+ Type::enforce($title, Type::STRING);
87
+ $this->title = $title;
88
+
89
+ return $this;
90
+ }
91
+
92
+ /**
93
+ * It will make audio start automatically.
94
+ */
95
+ public function enableAutoplay()
96
+ {
97
+ $this->autoplay = true;
98
+
99
+ return $this;
100
+ }
101
+
102
+ /**
103
+ * It will make audio *NOT* start automatically.
104
+ */
105
+ public function disableAutoplay()
106
+ {
107
+ $this->autoplay = false;
108
+
109
+ return $this;
110
+ }
111
+
112
+ /**
113
+ * It will make audio be muted initially.
114
+ */
115
+ public function enableMuted()
116
+ {
117
+ $this->muted = true;
118
+
119
+ return $this;
120
+ }
121
+
122
+ /**
123
+ * It will make audio laud.
124
+ */
125
+ public function disableMuted()
126
+ {
127
+ $this->muted = false;
128
+
129
+ return $this;
130
+ }
131
+
132
+ /**
133
+ * Gets the audio title
134
+ * @return string Audio title
135
+ */
136
+ public function getTitle()
137
+ {
138
+ return $this->title;
139
+ }
140
+
141
+ /**
142
+ * Gets the url for the audio
143
+ * @return string Audio url
144
+ */
145
+ public function getUrl()
146
+ {
147
+ return $this->url;
148
+ }
149
+
150
+ /**
151
+ * Gets the playback definition
152
+ * @return string playback definition
153
+ */
154
+ public function getPlayback()
155
+ {
156
+ return $this->playback;
157
+ }
158
+
159
+ /**
160
+ * Structure and create the full ArticleImage in a XML format DOMElement.
161
+ *
162
+ * @param $document DOMDocument where this element will be appended. Optional
163
+ */
164
+ public function toDOMElement($document = null)
165
+ {
166
+ if (!$document) {
167
+ $document = new \DOMDocument();
168
+ }
169
+ $element = $document->createElement('audio');
170
+
171
+ // title markup optional
172
+ if ($this->title) {
173
+ $element->setAttribute('title', $this->title);
174
+ }
175
+
176
+ // Autoplay mode markup optional
177
+ if ($this->autoplay) {
178
+ $element->setAttribute('autoplay', 'autoplay'); // TODO Confirm this will work
179
+ }
180
+
181
+ // Autoplay mode markup optional
182
+ if ($this->muted) {
183
+ $element->setAttribute('muted', 'muted'); // TODO Confirm this will work
184
+ }
185
+
186
+ // Audio URL markup. REQUIRED
187
+ if ($this->url) {
188
+ $source_element = $document->createElement('source');
189
+ $source_element->setAttribute('src', $this->url);
190
+ $element->appendChild($source_element);
191
+ }
192
+
193
+ return $element;
194
+ }
195
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Author.php ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ * Represents an author of the article.
15
+ *
16
+ * <addres>
17
+ * <a rel="facebook" href="http://facebook.com/everton.rosario">Everton</a>
18
+ * Everton Rosario is a passionate mountain biker on Facebook
19
+ * </address>
20
+ *
21
+ * or
22
+ *
23
+ * <addres>
24
+ * <a href="http://twitter.com/evertonrosario">Everton On Twitter</a>
25
+ * Everton Rosario is a passionate mountain biker on Twitter
26
+ * </address>
27
+ *
28
+ * or
29
+ *
30
+ * <addres>
31
+ * <a>Everton</a>
32
+ * Everton Rosario is a passionate mountain biker without Link
33
+ * </address>
34
+ */
35
+ class Author extends Element
36
+ {
37
+ /**
38
+ * @var string The author link
39
+ */
40
+ private $url;
41
+
42
+ /**
43
+ * @var string The author name
44
+ */
45
+ private $name;
46
+
47
+ /**
48
+ * @var string The author short description biography
49
+ */
50
+ private $description;
51
+
52
+ /**
53
+ * @var string Role or contribution of author
54
+ */
55
+ private $roleContribution;
56
+
57
+ /**
58
+ * Private constructor.
59
+ * @see ArticleTime::create();.
60
+ */
61
+ private function __construct()
62
+ {
63
+ }
64
+
65
+ /**
66
+ * Creates an Author instance.
67
+ */
68
+ public static function create()
69
+ {
70
+ return new self();
71
+ }
72
+
73
+ /**
74
+ * Defines the link URL for the author
75
+ * @param string the URL link for author. Ex: "http://facebook.com/everton.rosario"
76
+ */
77
+ public function withURL($url)
78
+ {
79
+ Type::enforce($url, Type::STRING);
80
+ $this->url = $url;
81
+
82
+ return $this;
83
+ }
84
+
85
+ /**
86
+ * Author name.
87
+ * @param string Author name. Ex: "Everton Rosario"
88
+ */
89
+ public function withName($name)
90
+ {
91
+ Type::enforce($name, Type::STRING);
92
+ $this->name = $name;
93
+
94
+ return $this;
95
+ }
96
+
97
+ /**
98
+ * Author short description biography
99
+ * @param string Describe the author biography.
100
+ */
101
+ public function withDescription($description)
102
+ {
103
+ Type::enforce($description, Type::STRING);
104
+ $this->description = $description;
105
+
106
+ return $this;
107
+ }
108
+
109
+ /**
110
+ * Author role/contribution
111
+ * @param string The author short text to caracterize role or contribution
112
+ */
113
+ public function withRoleContribution($role_contribution)
114
+ {
115
+ Type::enforce($role_contribution, Type::STRING);
116
+ $this->roleContribution = $role_contribution;
117
+
118
+ return $this;
119
+ }
120
+
121
+ /**
122
+ * @param string author link url profile
123
+ */
124
+ public function getUrl()
125
+ {
126
+ return $this->url;
127
+ }
128
+
129
+ /**
130
+ * @param string author name
131
+ */
132
+ public function getName()
133
+ {
134
+ return $this->name;
135
+ }
136
+
137
+ /**
138
+ * @param string author small introduction biography
139
+ */
140
+ public function getDescription()
141
+ {
142
+ return $this->description;
143
+ }
144
+
145
+ /**
146
+ * @param string author short text to define its contribution/role
147
+ */
148
+ public function getRoleContribution()
149
+ {
150
+ return $this->roleContribution;
151
+ }
152
+
153
+ /**
154
+ * Structure and create the full Author in a XML format DOMElement.
155
+ *
156
+ * @param $document DOMDocument where this element will be appended. Optional
157
+ */
158
+ public function toDOMElement($document = null)
159
+ {
160
+ if (!$document) {
161
+ $document = new \DOMDocument();
162
+ }
163
+
164
+ $author_url = $this->url ? $this->url : null;
165
+ $is_fb_author = strpos($author_url, 'facebook.com') !== false;
166
+
167
+ // Creates the root tag <address></address>
168
+ $element = $document->createElement('address');
169
+
170
+ // Creates the <a href...></> tag
171
+ $ahref = $document->createElement('a');
172
+ if ($author_url) {
173
+ $ahref->setAttribute('href', $author_url);
174
+ }
175
+ if ($is_fb_author) {
176
+ $ahref->setAttribute('rel', 'facebook');
177
+ }
178
+ if ($this->roleContribution) {
179
+ $ahref->setAttribute('title', $this->roleContribution);
180
+ }
181
+ $ahref->appendChild($document->createTextNode($this->name));
182
+ $element->appendChild($ahref);
183
+
184
+ // Appends author description
185
+ $element->appendChild($document->createTextNode($this->description));
186
+
187
+ return $element;
188
+ }
189
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Blockquote.php ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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
+ namespace Facebook\InstantArticles\Elements;
24
+
25
+ use Facebook\InstantArticles\Validators\Type;
26
+
27
+ /**
28
+ * Each blockquote of article should be an instance of this class.
29
+ *
30
+ * Example:
31
+ * <blockquote> This is the first blockquote of body text. </blockquote>
32
+ *
33
+ * or
34
+ *
35
+ * <blockquote> This is the <i>second</i> blockquote of <b>body text</b>. </blockquote>
36
+ *
37
+ * @see {link:https://developers.intern.facebook.com/docs/instant-articles/reference/blockquote}
38
+ */
39
+ class Blockquote extends TextContainer
40
+ {
41
+
42
+ /**
43
+ * @var string $text the text content for blockquote
44
+ */
45
+ private $text;
46
+
47
+ private function __construct()
48
+ {
49
+ }
50
+
51
+ public static function create()
52
+ {
53
+ return new self();
54
+ }
55
+
56
+ /**
57
+ * Sets the unescaped text within the blockquote.
58
+ *
59
+ * @param string The unescaped string.
60
+ */
61
+ public function withText($text)
62
+ {
63
+ Type::enforce($text, Type::STRING);
64
+ $this->text = $text;
65
+
66
+ return $this;
67
+ }
68
+
69
+ /**
70
+ * Structure and create the full Blockquote in a DOMElement.
71
+ *
72
+ * @param DOMDocument $document - The document where this element will be appended (optional).
73
+ */
74
+ public function toDOMElement($document = null)
75
+ {
76
+ if (!$document) {
77
+ $document = new \DOMDocument();
78
+ }
79
+ $element = $document->createElement('blockquote');
80
+
81
+ $element->appendChild($this->textToDOMDocumentFragment($document));
82
+
83
+ return $element;
84
+ }
85
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Bold.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ /**
12
+ * A bold text.
13
+ *
14
+ * @see {link:https://developers.intern.facebook.com/docs/instant-articles/reference/body-text}
15
+ */
16
+ class Bold extends FormattedText
17
+ {
18
+
19
+ private function __construct()
20
+ {
21
+ }
22
+
23
+ public static function create()
24
+ {
25
+ return new self();
26
+ }
27
+
28
+ /**
29
+ * Structure and create <b> node.
30
+ *
31
+ * @param DOMDocument $document - The document where this element will be appended (optional).
32
+ */
33
+ public function toDOMElement($document = null)
34
+ {
35
+ if (!$document) {
36
+ $document = new \DOMDocument();
37
+ }
38
+ $bold = $document->createElement('b');
39
+
40
+ $bold->appendChild($this->textToDOMDocumentFragment($document));
41
+
42
+ return $bold;
43
+ }
44
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Caption.php ADDED
@@ -0,0 +1,323 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ * A caption for any element.
15
+ * A caption can be included in any of the items:
16
+ * <ul>
17
+ * <li>@see Image</li>
18
+ * <li>@see Video</li>
19
+ * <li>@see SlideShow</li>
20
+ * <li>@see Map</li>
21
+ * <li>@see SocialEmbed</li>
22
+ * </ul>.
23
+ *
24
+ * Example:
25
+ * <figcaption class="op-vertical-below">
26
+ * <h1>Caption Title</h1>
27
+ * <h2>Caption SubTitle</h2>
28
+ * </figcaption>
29
+ *
30
+ * @see {link:https://developers.intern.facebook.com/docs/instant-articles/reference/caption}
31
+ */
32
+ class Caption extends FormattedText
33
+ {
34
+ // Font size
35
+ const SIZE_MEDIUM = 'op-medium';
36
+ const SIZE_LARGE = 'op-large';
37
+ const SIZE_XLARGE = 'op-extra-large';
38
+
39
+ // Text alignment (horizontal)
40
+ const ALIGN_LEFT = 'op-left';
41
+ const ALIGN_CENTER = 'op-center';
42
+ const ALIGN_RIGHT = 'op-right';
43
+
44
+ // Vertical position of the block
45
+ const POSITION_BELOW = 'op-vertical-below';
46
+ const POSITION_ABOVE = 'op-vertical-above';
47
+ const POSITION_CENTER = 'op-vertical-center';
48
+
49
+ /**
50
+ * @var H1 The caption title. REQUIRED
51
+ */
52
+ private $title;
53
+
54
+ /**
55
+ * @var H2 The caption subtitle. optional
56
+ */
57
+ private $subTitle;
58
+
59
+ /**
60
+ * @var Cite The credit text. optional
61
+ */
62
+ private $credit;
63
+
64
+ /**
65
+ * @var string A free text not contained in the tags
66
+ */
67
+ private $text;
68
+
69
+ /**
70
+ * @var string text Size. Values: "op-medium"|"op-large"|"op-extra-large"
71
+ */
72
+ private $fontSize;
73
+
74
+ /**
75
+ * @var string text align. Values: "op-left"|"op-center"|"op-right"
76
+ */
77
+ private $textAlignment;
78
+
79
+ /**
80
+ * @var string text position. Values: "op-vertical-below"|"op-vertical-above"|"op-vertical-center"
81
+ */
82
+ private $position;
83
+
84
+ private function __construct()
85
+ {
86
+ }
87
+
88
+ public static function create()
89
+ {
90
+ return new self();
91
+ }
92
+
93
+ /**
94
+ * The caption title. REQUIRED.
95
+ *
96
+ * @param H1|string the caption text that will be shown
97
+ */
98
+ public function withTitle($title)
99
+ {
100
+ Type::enforce($title, array(Type::STRING, H1::getClassName()));
101
+
102
+ if (Type::is($title, Type::STRING)) {
103
+ $title = H1::create()->appendText($title);
104
+ }
105
+ $this->title = $title;
106
+
107
+ return $this;
108
+ }
109
+
110
+ /**
111
+ * The caption sub title. optional.
112
+ *
113
+ * @param string the caption sub title text that will be shown
114
+ */
115
+ public function withSubTitle($sub_title)
116
+ {
117
+ Type::enforce($sub_title, array(Type::STRING, H2::getClassName()));
118
+ if (Type::is($sub_title, Type::STRING)) {
119
+ $sub_title = H2::create()->appendText($sub_title);
120
+ }
121
+ $this->subTitle = $sub_title;
122
+
123
+ return $this;
124
+ }
125
+
126
+ /**
127
+ * The caption credit. optional.
128
+ *
129
+ * @param string the caption credit text that will be shown
130
+ */
131
+ public function withCredit($credit)
132
+ {
133
+ Type::enforce($credit, array(Type::STRING, Cite::getClassName()));
134
+ if (Type::is($credit, Type::STRING)) {
135
+ $credit = Cite::create()->appendText($credit);
136
+ }
137
+ $this->credit = $credit;
138
+
139
+ return $this;
140
+ }
141
+
142
+ /**
143
+ * The Fontsize that will be used.
144
+ *
145
+ * @see Caption::SIZE_MEDIUM
146
+ * @see Caption::SIZE_LARGE
147
+ * @see Caption::SIZE_XLARGE
148
+ *
149
+ * @param string the caption font size that will be used.
150
+ */
151
+ public function withFontsize($font_size)
152
+ {
153
+ Type::enforceWithin(
154
+ $font_size,
155
+ array(
156
+ Caption::SIZE_XLARGE,
157
+ Caption::SIZE_LARGE,
158
+ Caption::SIZE_MEDIUM
159
+ )
160
+ );
161
+ $this->fontSize = $font_size;
162
+
163
+ return $this;
164
+ }
165
+
166
+ /**
167
+ * The Text alignment that will be used.
168
+ *
169
+ * @see Caption::ALIGN_RIGHT
170
+ * @see Caption::ALIGN_LEFT
171
+ * @see Caption::ALIGN_CENTER
172
+ *
173
+ * @param string alignment option that will be used.
174
+ */
175
+ public function withTextAlignment($text_alignment)
176
+ {
177
+ Type::enforceWithin(
178
+ $text_alignment,
179
+ array(
180
+ Caption::ALIGN_RIGHT,
181
+ Caption::ALIGN_LEFT,
182
+ Caption::ALIGN_CENTER
183
+ )
184
+ );
185
+ $this->textAlignment = $text_alignment;
186
+
187
+ return $this;
188
+ }
189
+
190
+ /**
191
+ * The Text position that will be used.
192
+ *
193
+ * @see Caption::POSITION_ABOVE
194
+ * @see Caption::POSITION_BELOW
195
+ * @see Caption::POSITION_CENTER
196
+ *
197
+ * @param string position that will be used.
198
+ */
199
+ public function withPostion($position)
200
+ {
201
+ Type::enforceWithin(
202
+ $position,
203
+ array(
204
+ Caption::POSITION_ABOVE,
205
+ Caption::POSITION_BELOW,
206
+ Caption::POSITION_CENTER
207
+ )
208
+ );
209
+ $this->position = $position;
210
+
211
+ return $this;
212
+ }
213
+
214
+ /**
215
+ * @return string the caption text title
216
+ */
217
+ public function getTitle()
218
+ {
219
+ return $this->title;
220
+ }
221
+
222
+ /**
223
+ * @return string the caption text subtitle
224
+ */
225
+ public function getSubTitle()
226
+ {
227
+ return $this->subTitle;
228
+ }
229
+
230
+ /**
231
+ * @return string the credit text
232
+ */
233
+ public function getCredit()
234
+ {
235
+ return $this->credit;
236
+ }
237
+
238
+ /**
239
+ * @return string the Font size.
240
+ *
241
+ * @see Caption::SIZE_MEDIUM
242
+ * @see Caption::SIZE_LARGE
243
+ * @see Caption::SIZE_XLARGE
244
+ */
245
+ public function getFontSize()
246
+ {
247
+ return $this->fontSize;
248
+ }
249
+
250
+ /**
251
+ * @return string the Font size.
252
+ *
253
+ * @see Caption::ALIGN_RIGHT
254
+ * @see Caption::ALIGN_LEFT
255
+ * @see Caption::ALIGN_CENTER
256
+ */
257
+ public function getTextAlignment()
258
+ {
259
+ return $this->textAlignment;
260
+ }
261
+
262
+ /**
263
+ * @return string the Font size.
264
+ *
265
+ *
266
+ * @see Caption::POSITION_ABOVE
267
+ * @see Caption::POSITION_BELOW
268
+ * @see Caption::POSITION_CENTER
269
+ */
270
+ public function getPosition()
271
+ {
272
+ return $this->position;
273
+ }
274
+
275
+ /**
276
+ * Structure and create the full ArticleImage in a XML format DOMElement.
277
+ *
278
+ * @param $document DOMDocument where this element will be appended. Optional
279
+ */
280
+ public function toDOMElement($document = null)
281
+ {
282
+ if (!$document) {
283
+ $document = new \DOMDocument();
284
+ }
285
+ $element = $document->createElement('figcaption');
286
+
287
+ // title markup REQUIRED
288
+ if ($this->title && (!$this->subTitle && !$this->credit)) {
289
+ $element->appendChild($this->title->textToDOMDocumentFragment($document));
290
+ } elseif ($this->title) {
291
+ $element->appendChild($this->title->toDOMElement($document));
292
+ }
293
+
294
+ // subtitle markup optional
295
+ if ($this->subTitle) {
296
+ $element->appendChild($this->subTitle->toDOMElement($document));
297
+ }
298
+
299
+ $element->appendChild($this->textToDOMDocumentFragment($document));
300
+
301
+ // credit markup optional
302
+ if ($this->credit) {
303
+ $element->appendChild($this->credit->toDOMElement($document));
304
+ }
305
+
306
+ // Formating markup
307
+ if ($this->textAlignment || $this->fontSize || $this->position) {
308
+ $classes = array();
309
+ if ($this->textAlignment) {
310
+ $classes[] = $this->textAlignment;
311
+ }
312
+ if ($this->fontSize) {
313
+ $classes[] = $this->fontSize;
314
+ }
315
+ if ($this->position) {
316
+ $classes[] = $this->position;
317
+ }
318
+ $element->setAttribute('class', implode(' ', $classes));
319
+ }
320
+
321
+ return $element;
322
+ }
323
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Cite.php ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ * Title for the Document
15
+ *
16
+ * Example:
17
+ * <cite> This is the first Instant Article</cite>
18
+ * or
19
+ * <cite> This is the <b>first</b> Instant Article</cite>
20
+ */
21
+ class Cite extends TextContainer
22
+ {
23
+ /**
24
+ * @var string text align. Values: "op-left"|"op-center"|"op-right"
25
+ */
26
+ private $textAlignment;
27
+
28
+ /**
29
+ * @var string text position. Values: "op-vertical-below"|"op-vertical-above"|"op-vertical-center"
30
+ */
31
+ private $position;
32
+
33
+ private function __construct()
34
+ {
35
+ }
36
+
37
+ public static function create()
38
+ {
39
+ return new self();
40
+ }
41
+
42
+ /**
43
+ * The Text alignment that will be used.
44
+ *
45
+ * @see Caption::ALIGN_RIGHT
46
+ * @see Caption::ALIGN_LEFT
47
+ * @see Caption::ALIGN_CENTER
48
+ *
49
+ * @param string alignment option that will be used.
50
+ */
51
+ public function withTextAlignment($text_alignment)
52
+ {
53
+ Type::enforceWithin(
54
+ $text_alignment,
55
+ array(
56
+ Caption::ALIGN_RIGHT,
57
+ Caption::ALIGN_LEFT,
58
+ Caption::ALIGN_CENTER
59
+ )
60
+ );
61
+ $this->textAlignment = $text_alignment;
62
+
63
+ return $this;
64
+ }
65
+
66
+ /**
67
+ * The Text position that will be used.
68
+ *
69
+ * @see Caption::POSITION_ABOVE
70
+ * @see Caption::POSITION_BELOW
71
+ * @see Caption::POSITION_CENTER
72
+ *
73
+ * @param string position that will be used.
74
+ */
75
+ public function withPostion($position)
76
+ {
77
+ Type::enforceWithin(
78
+ $position,
79
+ array(
80
+ Caption::POSITION_ABOVE,
81
+ Caption::POSITION_BELOW,
82
+ Caption::POSITION_CENTER
83
+ )
84
+ );
85
+ $this->position = $position;
86
+
87
+ return $this;
88
+ }
89
+
90
+ /**
91
+ * Structure and create the <cite> in a DOMElement.
92
+ *
93
+ * @param DOMDocument $document - The document where this element will be appended (optional).
94
+ */
95
+ public function toDOMElement($document = null)
96
+ {
97
+ if (!$document) {
98
+ $document = new \DOMDocument();
99
+ }
100
+ $cite = $document->createElement('cite');
101
+
102
+ $classes = array();
103
+ if ($this->position) {
104
+ $classes[] = $this->position;
105
+ }
106
+ if ($this->textAlignment) {
107
+ $classes[] = $this->textAlignment;
108
+ }
109
+ if (!empty($classes)) {
110
+ $cite->setAttribute('class', implode(' ', $classes));
111
+ }
112
+ $cite->appendChild($this->textToDOMDocumentFragment($document));
113
+
114
+ return $cite;
115
+ }
116
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Div.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ /**
12
+ * A div Text container.
13
+ *
14
+ * @see {link:https://developers.intern.facebook.com/docs/instant-articles/reference/body-text}
15
+ */
16
+ class Div extends TextContainer
17
+ {
18
+
19
+ private function __construct()
20
+ {
21
+ }
22
+
23
+ public static function create()
24
+ {
25
+ return new self();
26
+ }
27
+
28
+ /**
29
+ * Structure and create <div> node.
30
+ *
31
+ * @param DOMDocument $document - The document where this element will be appended (optional).
32
+ */
33
+ public function toDOMElement($document = null)
34
+ {
35
+ if (!$document) {
36
+ $document = new \DOMDocument();
37
+ }
38
+ $div = $document->createElement('div');
39
+
40
+ $div->appendChild($this->textToDOMDocumentFragment($document));
41
+
42
+ return $div;
43
+ }
44
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Element.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Element
15
+ * This class is the meta each tag element that contains rendering code for the
16
+ * tags
17
+ *
18
+ */
19
+ abstract class Element
20
+ {
21
+ abstract public function toDOMElement();
22
+
23
+ /**
24
+ * Renders the Element content
25
+ * @param string $doctype the doctype will be applied to document. I.e.: '<!doctype html>'
26
+ * @return string with the content rendered
27
+ */
28
+ public function render($doctype = '', $formated = false)
29
+ {
30
+ $document = new \DOMDocument();
31
+ $document->preserveWhiteSpace = !$formated;
32
+ $document->formatOutput = $formated;
33
+ $element = $this->toDOMElement($document);
34
+ $document->appendChild($element);
35
+ return $doctype.$document->saveXML($element);
36
+ }
37
+
38
+ /**
39
+ * Appends unescaped HTML to a element using the right strategy.
40
+ * @param DOMNode $element - The element to append the HTML to
41
+ * @param DOMNode $content - The unescaped HTML to append
42
+ */
43
+ protected function dangerouslyAppendUnescapedHTML($element, $content)
44
+ {
45
+ Type::enforce($content, 'DOMNode');
46
+ Type::enforce($element, 'DOMNode');
47
+ $imported = $element->ownerDocument->importNode($content, true);
48
+ $element->appendChild($imported);
49
+ }
50
+
51
+ /**
52
+ * Auxiliary method to extract all Elements full qualified class name.
53
+ * @return string The full qualified name of class
54
+ */
55
+ public static function getClassName() {
56
+ return get_called_class();
57
+ }
58
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Footer.php ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ * Footer of the article.
15
+ *
16
+ * Example:
17
+ * <body>
18
+ * <article>
19
+ * <footer>
20
+ * <aside>
21
+ * <p>The magazine thanks <a rel="facebook" href="...">The Rockefeller Foundation</a></p>
22
+ * <p>The magazine would also like to thank its readers.</p>
23
+ * </aside>
24
+ * </footer>
25
+ * </article>
26
+ * </body>
27
+ *
28
+ * @see {link:https://developers.intern.facebook.com/docs/instant-articles/reference/footer}
29
+ */
30
+ class Footer extends Element
31
+ {
32
+ /**
33
+ * @var string|Paragraph[] The text content of the credits
34
+ */
35
+ private $credits = array();
36
+
37
+ /**
38
+ * @var string Copyright information of the article
39
+ */
40
+ private $copyright;
41
+
42
+ /**
43
+ * @var RelatedArticles the related articles to be added to this footer. Optional
44
+ */
45
+ private $relatedArticles;
46
+
47
+ private function __construct()
48
+ {
49
+ }
50
+
51
+ public static function create()
52
+ {
53
+ return new self();
54
+ }
55
+
56
+ /**
57
+ * Sets the text content of the credits
58
+ *
59
+ * @param string|array<paragrah> $credits - A list of paragraphs or a single string for the content of the credit.
60
+ */
61
+ public function withCredits($credits)
62
+ {
63
+ Type::enforce($credits, array(Type::ARRAY_TYPE, Paragraph::getClassName(), Type::STRING));
64
+ $this->credits = $credits;
65
+
66
+ return $this;
67
+ }
68
+
69
+ /**
70
+ * Adds a new Paragraph to the credits
71
+ *
72
+ * @param Paragrah $credit - One Paragraph to be added as a credit.
73
+ */
74
+ public function addCredit($credit)
75
+ {
76
+ Type::enforce($credit, Paragraph::getClassName());
77
+ $this->credits[] = $credit;
78
+
79
+ return $this;
80
+ }
81
+
82
+ /**
83
+ * Sets the copyright information for the article.
84
+ *
85
+ * @param string $copyright - The copyright information.
86
+ */
87
+ public function withCopyright($copyright)
88
+ {
89
+ Type::enforce($copyright, Type::STRING);
90
+ $this->copyright = $copyright;
91
+
92
+ return $this;
93
+ }
94
+
95
+ /**
96
+ * Sets the related articles within the footer of the article.
97
+ *
98
+ * @param RelatedArticles $related_articles - The related articles
99
+ */
100
+ public function withRelatedArticles($related_articles)
101
+ {
102
+ Type::enforce($related_articles, RelatedArticles::getClassName());
103
+ $this->relatedArticles = $related_articles;
104
+
105
+ return $this;
106
+ }
107
+
108
+ /**
109
+ * Gets the text content of the credits
110
+ *
111
+ * @return string|array<paragrah> $credits - A list of paragraphs or a single string for the content of the credit.
112
+ */
113
+ public function getCredits()
114
+ {
115
+ return $this->credits;
116
+ }
117
+
118
+ /**
119
+ * Gets the copyright information for the article.
120
+ *
121
+ * @return string $copyright - The copyright information.
122
+ */
123
+ public function getCopyright()
124
+ {
125
+ return $this->copyright;
126
+ }
127
+
128
+ /**
129
+ * Gets the related articles within the footer of the article.
130
+ *
131
+ * @return RelatedArticles $related_articles - The related articles
132
+ */
133
+ public function getRelatedArticles()
134
+ {
135
+ return $this->relatedArticles;
136
+ }
137
+
138
+ /**
139
+ * Structure and create the full Footer in a DOMElement.
140
+ *
141
+ * @param DOMDocument $document - The document where this element will be appended (optional).
142
+ */
143
+ public function toDOMElement($document = null)
144
+ {
145
+ if (!$document) {
146
+ $document = new \DOMDocument();
147
+ }
148
+ $footer = $document->createElement('footer');
149
+
150
+ // Footer markup
151
+ if ($this->credits) {
152
+ $aside = $document->createElement('aside');
153
+ if (is_array($this->credits)) {
154
+ foreach ($this->credits as $paragraph) {
155
+ $aside->appendChild($paragraph->toDOMElement($document));
156
+ }
157
+ } else {
158
+ $aside->appendChild($document->createTextNode($this->credits));
159
+ }
160
+ $footer->appendChild($aside);
161
+ }
162
+
163
+ if ($this->copyright) {
164
+ $small = $document->createElement('small');
165
+ $small->appendChild($document->createTextNode($this->copyright));
166
+ $footer->appendChild($small);
167
+ }
168
+
169
+ if ($this->relatedArticles) {
170
+ $footer->appendChild($this->relatedArticles->toDOMElement($document));
171
+ }
172
+
173
+ if (!$this->credits && !$this->copyright && !$this->relatedArticles) {
174
+ $footer->appendChild($document->createTextNode(''));
175
+ }
176
+
177
+ return $footer;
178
+ }
179
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/FormattedText.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ /**
12
+ * Base class for text formatting elements.
13
+ * It has exactly the same behavior as TextContainer, but TextContainer cannot be nested,
14
+ * as it only accepts FormattedText children. Because of that you can freely nest FormattedText.
15
+ *
16
+ * Examples:
17
+ * - <b>bold</b>
18
+ * - <i>italic</i>
19
+ * - <a href="https://foo.com">link</a>
20
+ *
21
+ * @see {link:https://developers.intern.facebook.com/docs/instant-articles/reference/body-text}
22
+ */
23
+ abstract class FormattedText extends TextContainer
24
+ {
25
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/GeoTag.php ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Map
15
+ * This element Class holds map content for the articles.
16
+ *
17
+ * Example:
18
+ * <figure class="op-map">
19
+ * <script type="application/json" class="op-geotag">
20
+ * {
21
+ * "type": "Feature",
22
+ * "geometry": {
23
+ * "type": "Point",
24
+ * "coordinates": [23.166667, 89.216667]
25
+ * },
26
+ * "properties": {
27
+ * "title": "Jessore, Bangladesh",
28
+ * "radius": 750000,
29
+ * "pivot": true,
30
+ * "style": "satellite",
31
+ * }
32
+ * }
33
+ * </script>
34
+ * </figure>
35
+ *
36
+ */
37
+ class GeoTag extends Element
38
+ {
39
+ /**
40
+ * @var string The json geotag content inside the script geotag
41
+ */
42
+ private $script;
43
+
44
+ /**
45
+ * Private constructor.
46
+ * @see GeoTag::create();.
47
+ */
48
+ private function __construct()
49
+ {
50
+ }
51
+
52
+ /**
53
+ * Factory method for the Map
54
+ * @return GeoTag the new instance
55
+ */
56
+ public static function create()
57
+ {
58
+ return new self();
59
+ }
60
+
61
+ /**
62
+ * Sets the geotag on the image.
63
+ *
64
+ * @see {link:http://geojson.org/}
65
+ */
66
+ public function withScript($script)
67
+ {
68
+ Type::enforce($script, Type::STRING);
69
+ $this->script = $script; // TODO Validate the json informed
70
+
71
+ return $this;
72
+ }
73
+
74
+ /**
75
+ * @return string Geotag json content unescaped
76
+ */
77
+ public function getScript()
78
+ {
79
+ return $this->script;
80
+ }
81
+
82
+ /**
83
+ * Structure and create the full Map in a XML format DOMElement.
84
+ *
85
+ * @param $document DOMDocument where this element will be appended. Optional
86
+ */
87
+ public function toDOMElement($document = null)
88
+ {
89
+ if (!$document) {
90
+ $document = new \DOMDocument();
91
+ }
92
+ $element = $document->createElement('script');
93
+ $element->setAttribute('type', 'application/json');
94
+ $element->setAttribute('class', 'op-geotag');
95
+
96
+ // Required script field
97
+ if ($this->script) {
98
+ $element->appendChild($document->createTextNode($this->script));
99
+ }
100
+
101
+ return $element;
102
+ }
103
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/H1.php ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ * Title for the Document
15
+ *
16
+ * Example:
17
+ * <h1> This is the first Instant Article</h1>
18
+ * or
19
+ * <h1> This is the <b>first</b> Instant Article</h1>
20
+ */
21
+ class H1 extends TextContainer
22
+ {
23
+ /**
24
+ * @var string text align. Values: "op-left"|"op-center"|"op-right"
25
+ */
26
+ private $textAlignment;
27
+
28
+ /**
29
+ * @var string text position. Values: "op-vertical-below"|"op-vertical-above"|"op-vertical-center"
30
+ */
31
+ private $position;
32
+
33
+ private function __construct()
34
+ {
35
+ }
36
+
37
+ public static function create()
38
+ {
39
+ return new self();
40
+ }
41
+
42
+ /**
43
+ * The Text alignment that will be used.
44
+ *
45
+ * @see Caption::ALIGN_RIGHT
46
+ * @see Caption::ALIGN_LEFT
47
+ * @see Caption::ALIGN_CENTER
48
+ *
49
+ * @param string alignment option that will be used.
50
+ */
51
+ public function withTextAlignment($text_alignment)
52
+ {
53
+ Type::enforceWithin(
54
+ $text_alignment,
55
+ array(
56
+ Caption::ALIGN_RIGHT,
57
+ Caption::ALIGN_LEFT,
58
+ Caption::ALIGN_CENTER
59
+ )
60
+ );
61
+ $this->textAlignment = $text_alignment;
62
+
63
+ return $this;
64
+ }
65
+
66
+ /**
67
+ * The Text position that will be used.
68
+ *
69
+ * @see Caption::POSITION_ABOVE
70
+ * @see Caption::POSITION_BELOW
71
+ * @see Caption::POSITION_CENTER
72
+ *
73
+ * @param string position that will be used.
74
+ */
75
+ public function withPostion($position)
76
+ {
77
+ Type::enforceWithin(
78
+ $position,
79
+ array(
80
+ Caption::POSITION_ABOVE,
81
+ Caption::POSITION_BELOW,
82
+ Caption::POSITION_CENTER
83
+ )
84
+ );
85
+ $this->position = $position;
86
+
87
+ return $this;
88
+ }
89
+
90
+ /**
91
+ * Structure and create the H1 in a DOMElement.
92
+ *
93
+ * @param DOMDocument $document - The document where this element will be appended (optional).
94
+ */
95
+ public function toDOMElement($document = null)
96
+ {
97
+ if (!$document) {
98
+ $document = new \DOMDocument();
99
+ }
100
+ $h1 = $document->createElement('h1');
101
+
102
+ $classes = array();
103
+ if ($this->position) {
104
+ $classes[] = $this->position;
105
+ }
106
+ if ($this->textAlignment) {
107
+ $classes[] = $this->textAlignment;
108
+ }
109
+ if (!empty($classes)) {
110
+ $h1->setAttribute('class', implode(' ', $classes));
111
+ }
112
+
113
+ $h1->appendChild($this->textToDOMDocumentFragment($document));
114
+
115
+ return $h1;
116
+ }
117
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/H2.php ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ * Title for the Document
15
+ *
16
+ * Example:
17
+ * <h2> This is the first Instant Article</h2>
18
+ * or
19
+ * <h2> This is the <b>first</b> Instant Article</h2>
20
+ */
21
+ class H2 extends TextContainer
22
+ {
23
+ /**
24
+ * @var string text align. Values: "op-left"|"op-center"|"op-right"
25
+ */
26
+ private $textAlignment;
27
+
28
+ /**
29
+ * @var string text position. Values: "op-vertical-below"|"op-vertical-above"|"op-vertical-center"
30
+ */
31
+ private $position;
32
+
33
+ private function __construct()
34
+ {
35
+ }
36
+
37
+ public static function create()
38
+ {
39
+ return new self();
40
+ }
41
+
42
+
43
+ /**
44
+ * The Text alignment that will be used.
45
+ *
46
+ * @see Caption::ALIGN_RIGHT
47
+ * @see Caption::ALIGN_LEFT
48
+ * @see Caption::ALIGN_CENTER
49
+ *
50
+ * @param string alignment option that will be used.
51
+ */
52
+ public function withTextAlignment($text_alignment)
53
+ {
54
+ Type::enforceWithin(
55
+ $text_alignment,
56
+ array(
57
+ Caption::ALIGN_RIGHT,
58
+ Caption::ALIGN_LEFT,
59
+ Caption::ALIGN_CENTER
60
+ )
61
+ );
62
+ $this->textAlignment = $text_alignment;
63
+
64
+ return $this;
65
+ }
66
+
67
+ /**
68
+ * The Text position that will be used.
69
+ *
70
+ * @see Caption::POSITION_ABOVE
71
+ * @see Caption::POSITION_BELOW
72
+ * @see Caption::POSITION_CENTER
73
+ *
74
+ * @param string position that will be used.
75
+ */
76
+ public function withPostion($position)
77
+ {
78
+ Type::enforceWithin(
79
+ $position,
80
+ array(
81
+ Caption::POSITION_ABOVE,
82
+ Caption::POSITION_BELOW,
83
+ Caption::POSITION_CENTER
84
+ )
85
+ );
86
+ $this->position = $position;
87
+
88
+ return $this;
89
+ }
90
+
91
+ /**
92
+ * Structure and create the H2 in a DOMElement.
93
+ *
94
+ * @param DOMDocument $document - The document where this element will be appended (optional).
95
+ */
96
+ public function toDOMElement($document = null)
97
+ {
98
+ if (!$document) {
99
+ $document = new \DOMDocument();
100
+ }
101
+ $h2 = $document->createElement('h2');
102
+
103
+ $classes = array();
104
+ if ($this->position) {
105
+ $classes[] = $this->position;
106
+ }
107
+ if ($this->textAlignment) {
108
+ $classes[] = $this->textAlignment;
109
+ }
110
+ if (!empty($classes)) {
111
+ $h2->setAttribute('class', implode(' ', $classes));
112
+ }
113
+
114
+ $h2->appendChild($this->textToDOMDocumentFragment($document));
115
+
116
+ return $h2;
117
+ }
118
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Header.php ADDED
@@ -0,0 +1,368 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ * The header of the article. A header can hold an Image,
15
+ * Title, Authors and Dates for publishing and modification of the article.
16
+ *
17
+ * <header>
18
+ * <figure>
19
+ * <ui:image src={$this->getHeroBackground()} />
20
+ * </figure>
21
+ * <h1>{$this->name}</h1>
22
+ * <addres>
23
+ * <a rel="facebook" href="http://facebook.com/everton.rosario">Everton</a>
24
+ * Everton Rosario is a passionate mountain biker on Facebook
25
+ * </address>
26
+ * <time
27
+ * class="op-published"
28
+ * datetime={date('c', $this->time)}>
29
+ * {date('F jS, g:ia', $this->time)}
30
+ * </time>
31
+ * <time
32
+ * class="op-modified"
33
+ * datetime={date('c', $last_update)}>
34
+ * {date('F jS, g:ia', $last_update)}
35
+ * </time>
36
+ * </header>
37
+ */
38
+ class Header extends Element
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;
47
+
48
+ /**
49
+ * string The title of the Article that will be displayed on header.
50
+ */
51
+ private $title;
52
+
53
+ /**
54
+ * string The subtitle of the Article that will be displayed on header.
55
+ */
56
+ private $subtitle;
57
+
58
+ /**
59
+ * @var Author[] Authors of the article.
60
+ */
61
+ private $authors = array();
62
+
63
+ /**
64
+ * @var Time of publishing for the article
65
+ */
66
+ private $published;
67
+
68
+ /**
69
+ * @var Time of modification of the article, if it has
70
+ * updated.
71
+ */
72
+ private $modified;
73
+
74
+ /**
75
+ * @var string Header kicker
76
+ */
77
+ private $kicker;
78
+
79
+ /**
80
+ * @var Ad[] Ads of the article.
81
+ */
82
+ private $ads = array();
83
+
84
+ private function __construct()
85
+ {
86
+ }
87
+
88
+ public static function create()
89
+ {
90
+ return new self();
91
+ }
92
+
93
+ /**
94
+ * Sets the cover of InstantArticle with Image or Video
95
+ * @param Image|Video $cover The cover for the header of the InstantArticle
96
+ */
97
+ public function withCover($cover)
98
+ {
99
+ Type::enforce($cover, array(Image::getClassName(), Video::getClassName()));
100
+ $this->cover = $cover;
101
+
102
+ return $this;
103
+ }
104
+
105
+ /**
106
+ * Sets the title of InstantArticle
107
+ * @param string $title The title of the InstantArticle
108
+ */
109
+ public function withTitle($title)
110
+ {
111
+ Type::enforce($title, Type::STRING);
112
+ $this->title = $title;
113
+
114
+ return $this;
115
+ }
116
+
117
+ /**
118
+ * Sets the subtitle of InstantArticle
119
+ * @param string $subtitle The subtitle of the InstantArticle
120
+ */
121
+ public function withSubTitle($subtitle)
122
+ {
123
+ Type::enforce($subtitle, Type::STRING);
124
+ $this->subtitle = $subtitle;
125
+
126
+ return $this;
127
+ }
128
+
129
+ /**
130
+ * Append another author to the article
131
+ * @param Author $author The author name
132
+ */
133
+ public function addAuthor($author)
134
+ {
135
+ Type::enforce($author, Author::getClassName());
136
+ $this->authors[] = $author;
137
+
138
+ return $this;
139
+ }
140
+
141
+ /**
142
+ * Replace all authors within this Article
143
+ * @param array<Author> $authors All the authors
144
+ */
145
+ public function withAuthors($authors)
146
+ {
147
+ Type::enforceArrayOf($authors, Author::getClassName());
148
+ $this->authors = $authors;
149
+
150
+ return $this;
151
+ }
152
+
153
+ /**
154
+ * Sets the publish Time for this article. REQUIRED
155
+ * @param Time $published The timedate of publishing of this article. REQUIRED
156
+ */
157
+ public function withPublishTime($published)
158
+ {
159
+ Type::enforce($published, Time::getClassName());
160
+ $this->published = $published;
161
+
162
+ return $this;
163
+ }
164
+
165
+ /**
166
+ * Sets the update Time for this article. Optional
167
+ * @param Time $modified The timedate that this article was modified. Optional
168
+ */
169
+ public function withModifyTime($modified)
170
+ {
171
+ Type::enforce($modified, Time::getClassName());
172
+ $this->modified = $modified;
173
+
174
+ return $this;
175
+ }
176
+
177
+ /**
178
+ * Sets the update Time for this article. Optional
179
+ * @param Time $modified The timedate that this article was modified. Optional
180
+ */
181
+ public function withTime($time)
182
+ {
183
+ Type::enforce($time, Time::getClassName());
184
+ if ($time->getType() === Time::MODIFIED) {
185
+ $this->withModifyTime($time);
186
+ } else {
187
+ $this->withPublishTime($time);
188
+ }
189
+
190
+ return $this;
191
+ }
192
+
193
+ /**
194
+ * Kicker text for the article header.
195
+ * @param string The kicker text to be set
196
+ */
197
+ public function withKicker($kicker)
198
+ {
199
+ Type::enforce($kicker, Type::STRING);
200
+ $this->kicker = $kicker;
201
+
202
+ return $this;
203
+ }
204
+
205
+ /**
206
+ * Append another ad to the article
207
+ * @param Ad $ad Code for displaying an ad
208
+ */
209
+ public function addAd($ad)
210
+ {
211
+ Type::enforce($ad, Ad::getClassName());
212
+ $this->ads[] = $ad;
213
+
214
+ return $this;
215
+ }
216
+
217
+ /**
218
+ * Replace all ads within this Article
219
+ * @param array<Ad> $ads All the ads
220
+ */
221
+ public function withAds($ads)
222
+ {
223
+ Type::enforceArrayOf($ads, Ad::getClassName());
224
+ $this->ads = $ads;
225
+
226
+ return $this;
227
+ }
228
+
229
+ /**
230
+ * @return Image|Video $cover The cover for the header of the InstantArticle
231
+ */
232
+ public function getCover()
233
+ {
234
+ return $this->cover;
235
+ }
236
+
237
+ /**
238
+ * @return string $title The title of the InstantArticle
239
+ */
240
+ public function getTitle()
241
+ {
242
+ return $this->title;
243
+ }
244
+
245
+ /**
246
+ * @return string $subtitle The subtitle of the InstantArticle
247
+ */
248
+ public function getSubtitle()
249
+ {
250
+ return $this->subtitle;
251
+ }
252
+
253
+ /**
254
+ * @return array<Author> $authors All the authors
255
+ */
256
+ public function getAuthors()
257
+ {
258
+ return $this->authors;
259
+ }
260
+
261
+ /**
262
+ * @return Time $published The timedate of publishing of this article
263
+ */
264
+ public function getPublished()
265
+ {
266
+ return $this->published;
267
+ }
268
+
269
+ /**
270
+ * @return Time $modified The timedate that this article was modified.
271
+ */
272
+ public function getModified()
273
+ {
274
+ return $this->modified;
275
+ }
276
+
277
+ /**
278
+ * @return string The kicker text to be set
279
+ */
280
+ public function getKicker()
281
+ {
282
+ return $this->kicker;
283
+ }
284
+
285
+ /**
286
+ * @return array<Ad> $ads All the ads
287
+ */
288
+ public function getAds()
289
+ {
290
+ return $this->ads;
291
+ }
292
+
293
+ /**
294
+ * Structure and create the full ArticleImage in a XML format DOMElement.
295
+ *
296
+ * @param $document DOMDocument where this element will be appended. Optional
297
+ */
298
+ public function toDOMElement($document = null)
299
+ {
300
+ if (!$document) {
301
+ $document = new \DOMDocument();
302
+ }
303
+ $element = $document->createElement('header');
304
+
305
+ if ($this->cover) {
306
+ $element->appendChild($this->cover->toDOMElement($document));
307
+ }
308
+
309
+ if ($this->title) {
310
+ $title_element = $document->createElement('h1');
311
+ $title_element->appendChild($document->createTextNode($this->title));
312
+ $element->appendChild($title_element);
313
+ }
314
+
315
+ if ($this->subtitle) {
316
+ $sub_title_element = $document->createElement('h2');
317
+ $sub_title_element->appendChild($document->createTextNode($this->subtitle));
318
+ $element->appendChild($sub_title_element);
319
+ }
320
+
321
+ if ($this->published) {
322
+ $published_element = $this->published->toDOMElement($document);
323
+ $element->appendChild($published_element);
324
+ }
325
+
326
+ if ($this->modified) {
327
+ $modified_element = $this->modified->toDOMElement($document);
328
+ $element->appendChild($modified_element);
329
+ }
330
+
331
+ if ($this->authors) {
332
+ foreach ($this->authors as $author) {
333
+ $element->appendChild($author->toDOMElement($document));
334
+ }
335
+ }
336
+
337
+ if ($this->kicker) {
338
+ $kicker_element = $document->createElement('h3');
339
+ $kicker_element->setAttribute('class', 'op-kicker');
340
+ $kicker_element->appendChild($document->createTextNode($this->kicker));
341
+ $element->appendChild($kicker_element);
342
+ }
343
+
344
+ if (count($this->ads) === 1) {
345
+ $this->ads[0]->disableDefaultForReuse();
346
+ $element->appendChild($this->ads[0]->toDOMElement($document));
347
+ } elseif (count($this->ads) >= 2) {
348
+ $ads_container = $document->createElement('section');
349
+ $ads_container->setAttribute('class', 'op-ad-template');
350
+
351
+ $default_is_set = false;
352
+ foreach ($this->ads as $ad) {
353
+ if ($default_is_set) {
354
+ $ad->disableDefaultForReuse();
355
+ }
356
+
357
+ if ($ad->getIsDefaultForReuse()) {
358
+ $default_is_set = true;
359
+ }
360
+
361
+ $ads_container->appendChild($ad->toDOMElement($document));
362
+ }
363
+ $element->appendChild($ads_container);
364
+ }
365
+
366
+ return $element;
367
+ }
368
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Image.php ADDED
@@ -0,0 +1,330 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Image
15
+ * This element Class is the image for the article.
16
+ * Also consider to use one of the other media types for an article:
17
+ * <ul>
18
+ * <li>@see Audio</li>
19
+ * <li>@see Video</li>
20
+ * <li>@see SlideShow</li>
21
+ * <li>@see Map</li>
22
+ * </ul>.
23
+ *
24
+ * Example:
25
+ * <figure>
26
+ * <img src="http://mydomain.com/path/to/img.jpg" />
27
+ * <figcaption>This image is amazing</figcaption>
28
+ * </figure>
29
+ *
30
+ * @see {link:https://developers.intern.facebook.com/docs/instant-articles/reference/image}
31
+ */
32
+ class Image extends Audible
33
+ {
34
+ const ASPECT_FIT = 'aspect-fit';
35
+ const ASPECT_FIT_ONLY = 'aspect-fit-only';
36
+ const FULLSCREEN = 'fullscreen';
37
+ const NON_INTERACTIVE = 'non-interactive';
38
+
39
+ /**
40
+ * @var Caption The caption for Image
41
+ */
42
+ private $caption;
43
+
44
+ /**
45
+ * @var string The string url for the image hosted on web that will be shown
46
+ * on the article
47
+ */
48
+ private $url;
49
+
50
+ /**
51
+ * @var bool Tells if like is enabled. Default: false
52
+ */
53
+ private $isLikeEnabled;
54
+
55
+ /**
56
+ * @var bool Tells if comments are enabled. Default: false
57
+ */
58
+ private $isCommentsEnabled;
59
+
60
+ /**
61
+ * @var string The picture size for the video.
62
+ * @see Image::ASPECT_FIT
63
+ * @see Image::ASPECT_FIT_ONLY
64
+ * @see Image::FULLSCREEN
65
+ * @see Image::NON_INTERACTIVE
66
+ */
67
+ private $presentation;
68
+
69
+ /**
70
+ * @var GeoTag The Map object
71
+ */
72
+ private $geoTag;
73
+
74
+ /**
75
+ * @var Audio The audio file for this Image
76
+ */
77
+ private $audio;
78
+
79
+ /**
80
+ * Private constructor.
81
+ * @see Image::create();.
82
+ */
83
+ private function __construct()
84
+ {
85
+ }
86
+
87
+ /**
88
+ * Factory method for the Image
89
+ * @return Image the new instance
90
+ */
91
+ public static function create()
92
+ {
93
+ return new self();
94
+ }
95
+
96
+ /**
97
+ * This sets figcaption tag as documentation. It overrides all sets
98
+ * made with @see Caption.
99
+ *
100
+ * @param Caption the caption the image will have
101
+ */
102
+ public function withCaption($caption)
103
+ {
104
+ Type::enforce($caption, Caption::getClassName());
105
+ $this->caption = $caption;
106
+
107
+ return $this;
108
+ }
109
+
110
+ /**
111
+ * Sets the URL for the image. It is REQUIRED.
112
+ *
113
+ * @param string The url of image. Ie: http://domain.com/img.png
114
+ */
115
+ public function withURL($url)
116
+ {
117
+ Type::enforce($url, Type::STRING);
118
+ $this->url = $url;
119
+
120
+ return $this;
121
+ }
122
+
123
+ /**
124
+ * Sets the aspect ration presentation for the video.
125
+ *
126
+ * @param string one of the constants ASPECT_FIT, ASPECT_FIT_ONLY, FULLSCREEN or NON_INTERACTIVE
127
+ * @see Image::ASPECT_FIT
128
+ * @see Image::ASPECT_FIT_ONLY
129
+ * @see Image::FULLSCREEN
130
+ * @see Image::NON_INTERACTIVE
131
+ */
132
+ public function withPresentation($presentation)
133
+ {
134
+ Type::enforceWithin(
135
+ $presentation,
136
+ array(
137
+ Image::ASPECT_FIT,
138
+ Image::ASPECT_FIT_ONLY,
139
+ Image::FULLSCREEN,
140
+ Image::NON_INTERACTIVE
141
+ )
142
+ );
143
+ $this->presentation = $presentation;
144
+
145
+ return $this;
146
+ }
147
+
148
+ /**
149
+ * Makes like enabled for this image.
150
+ */
151
+ public function enableLike()
152
+ {
153
+ $this->isLikeEnabled = true;
154
+
155
+ return $this;
156
+ }
157
+
158
+ /**
159
+ * Makes like disabled for this image.
160
+ */
161
+ public function disableLike()
162
+ {
163
+ $this->isLikeEnabled = false;
164
+
165
+ return $this;
166
+ }
167
+
168
+ /**
169
+ * Makes comments enabled for this image.
170
+ */
171
+ public function enableComments()
172
+ {
173
+ $this->isCommentsEnabled = true;
174
+
175
+ return $this;
176
+ }
177
+
178
+ /**
179
+ * Makes comments disabled for this image.
180
+ */
181
+ public function disableComments()
182
+ {
183
+ $this->isCommentsEnabled = false;
184
+
185
+ return $this;
186
+ }
187
+
188
+ /**
189
+ * Sets the geotag on the image.
190
+ *
191
+ * @see {link:http://geojson.org/}
192
+ */
193
+ public function withGeoTag($geo_tag)
194
+ {
195
+ Type::enforce($geo_tag, array(Type::STRING, GeoTag::getClassName()));
196
+ if (Type::is($geo_tag, Type::STRING)) {
197
+ $this->geoTag = GeoTag::create()->withScript($geo_tag);
198
+ } elseif (Type::is($geo_tag, GeoTag::getClassName())) {
199
+ $this->geoTag = $geo_tag;
200
+ }
201
+
202
+ return $this;
203
+ }
204
+
205
+ /**
206
+ * Adds audio to this image.
207
+ *
208
+ * @param Audio The audio object
209
+ */
210
+ public function withAudio($audio)
211
+ {
212
+ Type::enforce($audio, Audio::getClassName());
213
+ $this->audio = $audio;
214
+
215
+ return $this;
216
+ }
217
+
218
+ /**
219
+ * @return Caption gets the caption obj
220
+ */
221
+ public function getCaption()
222
+ {
223
+ return $this->caption;
224
+ }
225
+
226
+ /**
227
+ * @return string URL gets the image url
228
+ */
229
+ public function getUrl()
230
+ {
231
+ return $this->url;
232
+ }
233
+
234
+ /**
235
+ * @return boolean tells if the like button is enabled
236
+ */
237
+ public function isLikeEnabled()
238
+ {
239
+ return $this->isLikeEnabled;
240
+ }
241
+
242
+ /**
243
+ * @return boolean tells if the comments widget is enabled
244
+ */
245
+ public function isCommentsEnabled()
246
+ {
247
+ return $this->isCommentsEnabled;
248
+ }
249
+
250
+ /**
251
+ * @return string one of the constants ASPECT_FIT, ASPECT_FIT_ONLY, FULLSCREEN or NON_INTERACTIVE
252
+ * @see Image::ASPECT_FIT
253
+ * @see Image::ASPECT_FIT_ONLY
254
+ * @see Image::FULLSCREEN
255
+ * @see Image::NON_INTERACTIVE
256
+ */
257
+ public function getPresentation()
258
+ {
259
+ return $this->presentation;
260
+ }
261
+
262
+ /**
263
+ * @return Map The json geotag content inside the script geotag
264
+ */
265
+ public function getGeotag()
266
+ {
267
+ return $this->geoTag;
268
+ }
269
+
270
+ /**
271
+ * @return Audio the audio object
272
+ */
273
+ public function getAudio()
274
+ {
275
+ return $this->audio;
276
+ }
277
+
278
+ /**
279
+ * Structure and create the full Image in a XML format DOMElement.
280
+ *
281
+ * @param $document DOMDocument where this element will be appended. Optional
282
+ */
283
+ public function toDOMElement($document = null)
284
+ {
285
+ if (!$document) {
286
+ $document = new \DOMDocument();
287
+ }
288
+ $element = $document->createElement('figure');
289
+
290
+ // Like/comments markup optional
291
+ if ($this->isLikeEnabled || $this->isCommentsEnabled) {
292
+ if ($this->isLikeEnabled && $this->isCommentsEnabled) {
293
+ $element->setAttribute('data-feedback', 'fb:likes,fb:comments');
294
+ } elseif ($this->isLikeEnabled) {
295
+ $element->setAttribute('data-feedback', 'fb:likes');
296
+ } else {
297
+ $element->setAttribute('data-feedback', 'fb:comments');
298
+ }
299
+ }
300
+
301
+ // Presentation
302
+ if ($this->presentation) {
303
+ $element->setAttribute('data-mode', $this->presentation);
304
+ }
305
+
306
+ // URL markup required
307
+ if ($this->url) {
308
+ $image_element = $document->createElement('img');
309
+ $image_element->setAttribute('src', $this->url);
310
+ $element->appendChild($image_element);
311
+ }
312
+
313
+ // Caption markup optional
314
+ if ($this->caption) {
315
+ $element->appendChild($this->caption->toDOMElement($document));
316
+ }
317
+
318
+ // Geotag markup optional
319
+ if ($this->geoTag) {
320
+ $element->appendChild($this->geoTag->toDOMElement($document));
321
+ }
322
+
323
+ // Audio markup optional
324
+ if ($this->audio) {
325
+ $element->appendChild($this->audio->toDOMElement($document));
326
+ }
327
+
328
+ return $element;
329
+ }
330
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/InstantArticle.php ADDED
@@ -0,0 +1,329 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 InstantArticle
15
+ * This class holds the content of one InstantArticle and is children
16
+ *
17
+ * <html>
18
+ * <head>
19
+ * ...
20
+ * </head>
21
+ * <body>
22
+ * <article>
23
+ * <header>
24
+ * <figure>...</figure>
25
+ * <h1>...</h1>
26
+ * <time>...</time>
27
+ * </header>
28
+ * <contents...>
29
+ * </article>
30
+ * </body>
31
+ * </html>
32
+ *
33
+ */
34
+ class InstantArticle extends Element
35
+ {
36
+ const CURRENT_VERSION = '1.0.0';
37
+
38
+ /**
39
+ * The meta properties that are used on <head>
40
+ */
41
+ private $metaProperties = array();
42
+
43
+ /**
44
+ * @var string The canonical URL for the Instant Article
45
+ */
46
+ private $canonicalURL;
47
+
48
+ /**
49
+ * @var string The markup version for this InstantArticle
50
+ */
51
+ private $markupVersion = 'v1.0';
52
+
53
+ /**
54
+ * @var boolean The ad strategy that will be used. True by default
55
+ */
56
+ private $isAutomaticAdPlaced = true;
57
+
58
+ /**
59
+ * @var string The charset that will be used. "utf-8" by default.
60
+ */
61
+ private $charset = 'utf-8';
62
+
63
+ /**
64
+ * @var string|null The style that will be applied to the article. Optional.
65
+ */
66
+ private $style;
67
+
68
+ /**
69
+ * @var ArticleHeader element to hold header content, like images etc
70
+ */
71
+ private $header;
72
+
73
+ /**
74
+ * @var ArticleFooter element to hold footer content.
75
+ */
76
+ private $footer;
77
+
78
+ /**
79
+ * @var Element[] of all elements an article can have.
80
+ */
81
+ private $children = array();
82
+
83
+ /**
84
+ * Factory method
85
+ * @return InstantArticle object.
86
+ */
87
+ public static function create()
88
+ {
89
+ return new InstantArticle();
90
+ }
91
+
92
+ /**
93
+ * Private constructor. It must be used the Factory method
94
+ * @see InstantArticle#create() For building objects
95
+ * @return InstantArticle object.
96
+ */
97
+ private function __construct()
98
+ {
99
+ $this->header = Header::create();
100
+ $this->addMetaProperty('op:generator', 'facebook-instant-articles-sdk-php');
101
+ $this->addMetaProperty('op:generator:version', self::CURRENT_VERSION);
102
+ }
103
+
104
+ /**
105
+ * Sets the canonical URL for the Instant Article. It is REQUIRED.
106
+ *
107
+ * @param string The canonical url of article. Ie: http://domain.com/article.html
108
+ */
109
+ public function withCanonicalURL($url)
110
+ {
111
+ Type::enforce($url, Type::STRING);
112
+ $this->canonicalURL = $url;
113
+
114
+ return $this;
115
+ }
116
+
117
+ /**
118
+ * Sets the charset for the Instant Article. utf-8 by default.
119
+ *
120
+ * @param string The charset of article. Ie: "iso-8859-1"
121
+ */
122
+ public function withCharset($charset)
123
+ {
124
+ Type::enforce($charset, Type::STRING);
125
+ $this->charset = $charset;
126
+
127
+ return $this;
128
+ }
129
+
130
+ /**
131
+ * Sets the style to be applied to this Instant Article
132
+ *
133
+ * @param string Name of the style
134
+ */
135
+ public function withStyle($style)
136
+ {
137
+ Type::enforce($style, Type::STRING);
138
+ $this->style = $style;
139
+
140
+ return $this;
141
+ }
142
+
143
+ /**
144
+ * Use the strategy of auto ad placement
145
+ */
146
+ public function enableAutomaticAdPlacement()
147
+ {
148
+ $this->isAutomaticAdPlaced = true;
149
+ return $this;
150
+ }
151
+
152
+ /**
153
+ * Use the strategy of manual ad placement
154
+ */
155
+ public function disableAutomaticAdPlacement()
156
+ {
157
+ $this->isAutomaticAdPlaced = false;
158
+ return $this;
159
+ }
160
+
161
+ /**
162
+ * Sets the header content to this InstantArticle
163
+ * @param Header to be added to this Article.
164
+ */
165
+ public function withHeader($header)
166
+ {
167
+ Type::enforce($header, Header::getClassName());
168
+ $this->header = $header;
169
+
170
+ return $this;
171
+ }
172
+
173
+ /**
174
+ * Sets the footer content to this InstantArticle
175
+ * @param Footer to be added to this Article.
176
+ */
177
+ public function withFooter($footer)
178
+ {
179
+ Type::enforce($footer, Footer::getClassName());
180
+ $this->footer = $footer;
181
+
182
+ return $this;
183
+ }
184
+
185
+ /**
186
+ * Adds new child elements to this InstantArticle
187
+ * @param Element to be added to this Article.
188
+ */
189
+ public function addChild($child)
190
+ {
191
+ Type::enforce(
192
+ $child,
193
+ array(
194
+ Ad::getClassName(),
195
+ Analytics::getClassName(),
196
+ AnimatedGif::getClassName(),
197
+ Audio::getClassName(),
198
+ Blockquote::getClassName(),
199
+ Image::getClassName(),
200
+ H1::getClassName(),
201
+ H2::getClassName(),
202
+ Interactive::getClassName(),
203
+ ListElement::getClassName(),
204
+ Map::getClassName(),
205
+ Paragraph::getClassName(),
206
+ Pullquote::getClassName(),
207
+ RelatedArticles::getClassName(),
208
+ Slideshow::getClassName(),
209
+ SocialEmbed::getClassName(),
210
+ Video::getClassName()
211
+ )
212
+ );
213
+ $this->children[] = $child;
214
+
215
+ return $this;
216
+ }
217
+
218
+ /**
219
+ * @return Header header element from the InstantArticle
220
+ */
221
+ public function getHeader()
222
+ {
223
+ return $this->header;
224
+ }
225
+
226
+ /**
227
+ * @return Footer footer element from the InstantArticle
228
+ */
229
+ public function getFooter()
230
+ {
231
+ return $this->footer;
232
+ }
233
+
234
+ /**
235
+ * @return array<Element> the elements this article contains
236
+ */
237
+ public function getChildren()
238
+ {
239
+ return $this->children;
240
+ }
241
+
242
+ /**
243
+ * Adds a meta property for the <head> of Instant Article.
244
+ * @param string $property_name name of meta attribute
245
+ * @param string $property_content content of meta attribute
246
+ * @return $this for builder pattern
247
+ */
248
+ public function addMetaProperty($property_name, $property_content)
249
+ {
250
+ $this->metaProperties[$property_name] = $property_content;
251
+ return $this;
252
+ }
253
+
254
+ public function render($doctype = '<!doctype html>', $format = false)
255
+ {
256
+ return parent::render($doctype, $format);
257
+ }
258
+
259
+ public function toDOMElement($document = null)
260
+ {
261
+ if (!$document) {
262
+ $document = new \DOMDocument();
263
+ }
264
+
265
+ // Builds and appends head to the HTML document
266
+ $html = $document->createElement('html');
267
+ $head = $document->createElement('head');
268
+ $html->appendChild($head);
269
+
270
+ $link = $document->createElement('link');
271
+ $link->setAttribute('rel', 'canonical');
272
+ $link->setAttribute('href', $this->canonicalURL);
273
+ $head->appendChild($link);
274
+
275
+ $charset = $document->createElement('meta');
276
+ $charset->setAttribute('charset', $this->charset);
277
+ $head->appendChild($charset);
278
+
279
+ $this->addMetaProperty('op:markup_version', $this->markupVersion);
280
+ $this->addMetaProperty(
281
+ 'fb:use_automatic_ad_placement',
282
+ $this->isAutomaticAdPlaced ? 'true' : 'false'
283
+ );
284
+
285
+ if ($this->style) {
286
+ $this->addMetaProperty('fb:article_style', $this->style);
287
+ }
288
+
289
+ // Adds all meta properties
290
+ foreach ($this->metaProperties as $property_name => $property_content) {
291
+ $head->appendChild(
292
+ $this->createMetaElement(
293
+ $document,
294
+ $property_name,
295
+ $property_content
296
+ )
297
+ );
298
+ }
299
+
300
+ // Build and append body and article tags to the HTML document
301
+ $body = $document->createElement('body');
302
+ $article = $document->createElement('article');
303
+ $body->appendChild($article);
304
+ $html->appendChild($body);
305
+ if ($this->header) {
306
+ $article->appendChild($this->header->toDOMElement($document));
307
+ }
308
+ if ($this->children) {
309
+ foreach ($this->children as $child) {
310
+ $article->appendChild($child->toDOMElement($document));
311
+ }
312
+ if ($this->footer) {
313
+ $article->appendChild($this->footer->toDOMElement($document));
314
+ }
315
+ } else {
316
+ $article->appendChild($document->createTextNode(''));
317
+ }
318
+
319
+ return $html;
320
+ }
321
+
322
+ private function createMetaElement($document, $property_name, $property_content)
323
+ {
324
+ $element = $document->createElement('meta');
325
+ $element->setAttribute('property', $property_name);
326
+ $element->setAttribute('content', $property_content);
327
+ return $element;
328
+ }
329
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Interactive.php ADDED
@@ -0,0 +1,222 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ * An Interactive graphic.
15
+ *
16
+ * Example:
17
+ * <figure class="op-interactive">
18
+ * <iframe class="no-margin" src="http://example.com/custom-interactive" height="60"></iframe>
19
+ * <figcaption>This graphic is awesome.</figcaption>
20
+ * </figure>
21
+ *
22
+ * @see {link:https://developers.intern.facebook.com/docs/instant-articles/reference/interactive}
23
+ */
24
+ class Interactive extends Element
25
+ {
26
+ const NO_MARGIN = 'no-margin';
27
+ const COLUMN_WIDTH = 'column-width';
28
+
29
+ /**
30
+ * @var Caption Descriptive text for your social embed.
31
+ */
32
+ private $caption;
33
+
34
+ /**
35
+ * @var int The height of your interactive graphic.
36
+ */
37
+ private $height;
38
+
39
+ /**
40
+ * @var string The source of the content for your interactive graphic.
41
+ */
42
+ private $source;
43
+
44
+ /**
45
+ * @var string The width setting for the interactive graphic.
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
+ {
58
+ }
59
+
60
+ public static function create()
61
+ {
62
+ return new self();
63
+ }
64
+
65
+ /**
66
+ * Sets the caption for the social embed.
67
+ *
68
+ * @param Caption $caption - Descriptive text for your social embed.
69
+ */
70
+ public function withCaption($caption)
71
+ {
72
+ Type::enforce($caption, Caption::getClassName());
73
+ $this->caption = $caption;
74
+
75
+ return $this;
76
+ }
77
+
78
+ /**
79
+ * Sets the height of your interactive graphic.
80
+ *
81
+ * @param int The height of your interactive graphic.
82
+ */
83
+ public function withHeight($height)
84
+ {
85
+ Type::enforce($height, Type::INTEGER);
86
+ $this->height = $height;
87
+
88
+ return $this;
89
+ }
90
+
91
+ /**
92
+ * Sets the source for the interactive graphic.
93
+ *
94
+ * @param string The source of the content for your interactive graphic.
95
+ */
96
+ public function withSource($source)
97
+ {
98
+ Type::enforce($source, Type::STRING);
99
+ $this->source = $source;
100
+
101
+ return $this;
102
+ }
103
+
104
+ /**
105
+ * Sets the width setting of your interactive graphic.
106
+ *
107
+ * @param string The width setting of your interactive graphic.
108
+ * @see Interactive::NO_MARGIN
109
+ * @see Interactive::COLUMN_WIDTH
110
+ */
111
+ public function withWidth($width)
112
+ {
113
+ Type::enforceWithin(
114
+ $width,
115
+ array(
116
+ Interactive::NO_MARGIN,
117
+ Interactive::COLUMN_WIDTH
118
+ )
119
+ );
120
+ $this->width = $width;
121
+
122
+ return $this;
123
+ }
124
+
125
+ /**
126
+ * Sets the unescaped HTML of your interactive graphic.
127
+ *
128
+ * @param \DOMNode The unescaped HTML of your interactive graphic.
129
+ */
130
+ public function withHTML($html)
131
+ {
132
+ Type::enforce($html, 'DOMNode');
133
+ $this->html = $html;
134
+
135
+ return $this;
136
+ }
137
+
138
+ /**
139
+ * @return Caption the caption element
140
+ */
141
+ public function getCaption()
142
+ {
143
+ return $this->caption;
144
+ }
145
+
146
+ /**
147
+ * @return int the height
148
+ */
149
+ public function getHeight()
150
+ {
151
+ return $this->height;
152
+ }
153
+
154
+ /**
155
+ * @return string url source
156
+ */
157
+ public function getSource()
158
+ {
159
+ return $this->source;
160
+ }
161
+
162
+ /**
163
+ * @return int the width
164
+ */
165
+ public function getWidth()
166
+ {
167
+ return $this->width;
168
+ }
169
+
170
+ /**
171
+ * @return \DOMNode unescaped html
172
+ */
173
+ public function getHtml()
174
+ {
175
+ return $this->html;
176
+ }
177
+
178
+ /**
179
+ * Structure and create the full Interactive in a DOMElement.
180
+ *
181
+ * @param DOMDocument $document - The document where this element will be appended (optional).
182
+ */
183
+ public function toDOMElement($document = null)
184
+ {
185
+ if (!$document) {
186
+ $document = new \DOMDocument();
187
+ }
188
+ $figure = $document->createElement('figure');
189
+ $iframe = $document->createElement('iframe');
190
+
191
+ $figure->appendChild($iframe);
192
+ $figure->setAttribute('class', 'op-interactive');
193
+
194
+ // Caption markup optional
195
+ if ($this->caption) {
196
+ $figure->appendChild($this->caption->toDOMElement($document));
197
+ }
198
+
199
+ if ($this->source) {
200
+ $iframe->setAttribute('src', $this->source);
201
+ }
202
+
203
+ if ($this->width) {
204
+ $iframe->setAttribute('class', $this->width);
205
+ }
206
+
207
+ if ($this->height) {
208
+ $iframe->setAttribute('height', $this->height);
209
+ }
210
+
211
+ // Ad markup
212
+ if ($this->html) {
213
+ // Here we do not care about what is inside the iframe
214
+ // because it'll be rendered in a sandboxed webview
215
+ $this->dangerouslyAppendUnescapedHTML($iframe, $this->html);
216
+ } else {
217
+ $iframe->appendChild($document->createTextNode(''));
218
+ }
219
+
220
+ return $figure;
221
+ }
222
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Italic.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ /**
12
+ * An italic text.
13
+ *
14
+ * @see {link:https://developers.intern.facebook.com/docs/instant-articles/reference/body-text}
15
+ */
16
+ class Italic extends FormattedText
17
+ {
18
+
19
+ private function __construct()
20
+ {
21
+ }
22
+
23
+ public static function create()
24
+ {
25
+ return new self();
26
+ }
27
+
28
+ /**
29
+ * Structure and create <i> node.
30
+ *
31
+ * @param DOMDocument $document - The document where this element will be appended (optional).
32
+ */
33
+ public function toDOMElement($document = null)
34
+ {
35
+ if (!$document) {
36
+ $document = new \DOMDocument();
37
+ }
38
+ $italic = $document->createElement('i');
39
+
40
+ $italic->appendChild($this->textToDOMDocumentFragment($document));
41
+
42
+ return $italic;
43
+ }
44
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/LineBreak.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ /**
12
+ * A line break.
13
+ *
14
+ * @see {link:https://developers.intern.facebook.com/docs/instant-articles/reference/body-text}
15
+ */
16
+ class LineBreak extends FormattedText
17
+ {
18
+
19
+ private function __construct()
20
+ {
21
+ }
22
+
23
+ public static function create()
24
+ {
25
+ return new self();
26
+ }
27
+
28
+ public function appendText($text)
29
+ {
30
+ throw new BadMethodCallException('Cannot append text to a line break');
31
+ }
32
+
33
+ /**
34
+ * Structure and create <b> node.
35
+ *
36
+ * @param DOMDocument $document - The document where this element will be appended (optional).
37
+ */
38
+ public function toDOMElement($document = null)
39
+ {
40
+ if (!$document) {
41
+ $document = new \DOMDocument();
42
+ }
43
+ $br = $document->createElement('br');
44
+
45
+ return $br;
46
+ }
47
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/ListElement.php ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 List that represents a simple HTML list
15
+ *
16
+ * Example Unordered:
17
+ * <ul>
18
+ * <li>Dog</li>
19
+ * <li>Cat</li>
20
+ * <li>Fox</li>
21
+ * </ul>
22
+ *
23
+ * Example Ordered:
24
+ * <ol>
25
+ * <li>Groceries</li>
26
+ * <li>School</li>
27
+ * <li>Sleep</li>
28
+ * </ol>
29
+ */
30
+ class ListElement extends Element
31
+ {
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 = array();
41
+
42
+ /**
43
+ * Private constructor.
44
+ * @see List::createOrdered() and @see List::createUnordered().
45
+ */
46
+ private function __construct()
47
+ {
48
+ }
49
+
50
+ /**
51
+ * Factory method for an Ordered list
52
+ * @return ListElement the new instance List as an ordered list
53
+ */
54
+ public static function createOrdered()
55
+ {
56
+ $list = new self();
57
+ $list->enableOrdered();
58
+
59
+ return $list;
60
+ }
61
+
62
+ /**
63
+ * Factory method for an unrdered list
64
+ * @return ListElement the new instance List as an unordered list
65
+ */
66
+ public static function createUnordered()
67
+ {
68
+ $list = new self();
69
+ $list->disableOrdered();
70
+
71
+ return $list;
72
+ }
73
+
74
+ /**
75
+ * Adds a new item to the List
76
+ *
77
+ * @param ListItem The new item that will be pushed to the end of the list
78
+ */
79
+ public function addItem($new_item)
80
+ {
81
+ Type::enforce($new_item, array(ListItem::getClassName(), Type::STRING));
82
+ if (Type::is($new_item, Type::STRING)) {
83
+ $new_item = ListItem::create()->withText($new_item);
84
+ }
85
+ $this->items[] = $new_item;
86
+
87
+ return $this;
88
+ }
89
+
90
+ /**
91
+ * Sets all items of the list as the array on the parameter
92
+ *
93
+ * @param ListItem[] The new items. Replaces all items from the list
94
+ */
95
+ public function withItems($new_items)
96
+ {
97
+ Type::enforceArrayOf($new_items, array(ListItem::getClassName(), Type::STRING));
98
+ foreach ($new_items as $new_item) {
99
+ $this->addItem($new_item);
100
+ }
101
+
102
+ return $this;
103
+ }
104
+
105
+ /**
106
+ * Makes the list become ordered
107
+ */
108
+ public function enableOrdered()
109
+ {
110
+ $this->isOrdered = true;
111
+
112
+ return $this;
113
+ }
114
+
115
+ /**
116
+ * Makes the list become unordered
117
+ */
118
+ public function disableOrdered()
119
+ {
120
+ $this->isOrdered = false;
121
+
122
+ return $this;
123
+ }
124
+
125
+ /**
126
+ * Auxiliary method to find the starting string
127
+ */
128
+ private static function startsWith($haystack, $needle)
129
+ {
130
+ return substr($haystack, 0, strlen($needle)) === $needle;
131
+ }
132
+
133
+ /**
134
+ * @return string[] the list text items
135
+ */
136
+ public function getItems()
137
+ {
138
+ return $this->items;
139
+ }
140
+
141
+ /**
142
+ * @return boolean if the list is ordered
143
+ */
144
+ public function isOrdered()
145
+ {
146
+ return $this->isOrdered;
147
+ }
148
+
149
+ /**
150
+ * Structure and create the full Video in a XML format DOMElement.
151
+ *
152
+ * @param $document DOMDocument where this element will be appended. Optional
153
+ */
154
+ public function toDOMElement($document = null)
155
+ {
156
+ if (!$document) {
157
+ $document = new \DOMDocument();
158
+ }
159
+
160
+ if ($this->isOrdered) {
161
+ $element = $document->createElement('ol');
162
+ } else {
163
+ $element = $document->createElement('ul');
164
+ }
165
+
166
+ if ($this->items) {
167
+ foreach ($this->items as $item) {
168
+ if ($item) {
169
+ $element->appendChild($item->toDOMElement($document));
170
+ }
171
+ }
172
+ }
173
+
174
+ return $element;
175
+ }
176
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/ListItem.php ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 List that represents a simple HTML list
15
+ *
16
+ * Example:
17
+ * <li>Dog</li>
18
+ */
19
+ class ListItem extends TextContainer
20
+ {
21
+ /**
22
+ * @var TextContainer
23
+ */
24
+ private $text;
25
+
26
+ private function __construct()
27
+ {
28
+ }
29
+
30
+ public static function create()
31
+ {
32
+ return new self();
33
+ }
34
+
35
+ /**
36
+ * @param string|TextContainer $text the text that will be added to <li>
37
+ */
38
+ public function withText($text)
39
+ {
40
+ Type::enforce($text, array(TextContainer::getClassName(), Type::STRING));
41
+ $this->text = $text;
42
+
43
+ return $this;
44
+ }
45
+
46
+ /**
47
+ * Overrides the appendText to make sure only one child will be setted on this ListItem.
48
+ * If appendText is called multiple times, it will store only the last one.
49
+ * @see ListItem::withText()
50
+ *
51
+ * @param string|TextContainer The content can be a string or a TextContainer.
52
+ */
53
+ public function appendText($child)
54
+ {
55
+ return $this->withText($child);
56
+ }
57
+
58
+
59
+ /**
60
+ * @return string|TextContainer The text that was added thru @see ListItem::withText()
61
+ */
62
+ public function getText()
63
+ {
64
+ return $this->text;
65
+ }
66
+
67
+ /**
68
+ * Structure and create the full ListItem in a DOMElement.
69
+ *
70
+ * @param DOMDocument $document - The document where this element will be appended (optional).
71
+ */
72
+ public function toDOMElement($document = null)
73
+ {
74
+ if (!$document) {
75
+ $document = new \DOMDocument();
76
+ }
77
+ $list_item = $document->createElement('li');
78
+
79
+ if ($this->text) {
80
+ if (Type::is($this->text, Type::STRING)) {
81
+ $list_item->appendChild($document->createTextNode($this->text));
82
+ } else {
83
+ $list_item->appendChild($this->text->toDOMElement($document));
84
+ }
85
+ }
86
+
87
+ return $list_item;
88
+ }
89
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Map.php ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Map
15
+ * This element Class holds map content for the articles.
16
+ *
17
+ * Example:
18
+ * <figure class="op-map">
19
+ * <script type="application/json" class="op-geoTag">
20
+ * {
21
+ * "type": "Feature",
22
+ * "geometry": {
23
+ * "type": "Point",
24
+ * "coordinates": [23.166667, 89.216667]
25
+ * },
26
+ * "properties": {
27
+ * "title": "Jessore, Bangladesh",
28
+ * "radius": 750000,
29
+ * "pivot": true,
30
+ * "style": "satellite",
31
+ * }
32
+ * }
33
+ * </script>
34
+ * </figure>
35
+ *
36
+ */
37
+ class Map extends Audible
38
+ {
39
+ /**
40
+ * @var ArticleCaption The caption for Image
41
+ */
42
+ private $caption;
43
+
44
+ /**
45
+ * @var GeoTag The json geoTag content inside the script geoTag
46
+ */
47
+ private $geoTag;
48
+
49
+ /**
50
+ * @var Audio The audio file for this Image
51
+ */
52
+ private $audio;
53
+
54
+ /**
55
+ * Private constructor.
56
+ * @see Map::create();.
57
+ */
58
+ private function __construct()
59
+ {
60
+ }
61
+
62
+ /**
63
+ * Factory method for the Map
64
+ * @return Map the new instance
65
+ */
66
+ public static function create()
67
+ {
68
+ return new self();
69
+ }
70
+
71
+ /**
72
+ * This sets figcaption tag as documentation. It overrides all sets
73
+ * made with @see Caption.
74
+ *
75
+ * @param Caption the caption the map will have
76
+ */
77
+ public function withCaption($caption)
78
+ {
79
+ Type::enforce($caption, Caption::getClassName());
80
+ $this->caption = $caption;
81
+
82
+ return $this;
83
+ }
84
+
85
+ /**
86
+ * Sets the geoTag on the image.
87
+ * @param GeoTag The tag to be set on the map object
88
+ * @see {link:http://geojson.org/}
89
+ */
90
+ public function withGeoTag($geo_tag)
91
+ {
92
+ Type::enforce($geo_tag, GeoTag::getClassName());
93
+ $this->geoTag = $geo_tag;
94
+
95
+ return $this;
96
+ }
97
+
98
+ /**
99
+ * Adds audio to this image.
100
+ *
101
+ * @param Audio The audio object
102
+ */
103
+ public function withAudio($audio)
104
+ {
105
+ Type::enforce($audio, Audio::getClassName());
106
+ $this->audio = $audio;
107
+
108
+ return $this;
109
+ }
110
+
111
+ /**
112
+ * @return Caption the caption for the Map
113
+ */
114
+ public function getCaption()
115
+ {
116
+ return $this->caption;
117
+ }
118
+
119
+ /**
120
+ * @return string Geotag json content unescaped
121
+ */
122
+ public function getGeotag()
123
+ {
124
+ return $this->geoTag;
125
+ }
126
+
127
+ /**
128
+ * @return Audio the audio object
129
+ */
130
+ public function getAudio()
131
+ {
132
+ return $this->audio;
133
+ }
134
+
135
+ /**
136
+ * Structure and create the full Map in a XML format DOMElement.
137
+ *
138
+ * @param $document DOMDocument where this element will be appended. Optional
139
+ */
140
+ public function toDOMElement($document = null)
141
+ {
142
+ if (!$document) {
143
+ $document = new \DOMDocument();
144
+ }
145
+ $element = $document->createElement('figure');
146
+ $element->setAttribute('class', 'op-map');
147
+
148
+ // Geotag markup REQUIRED
149
+ if ($this->geoTag) {
150
+ $element->appendChild($this->geoTag->toDOMElement($document));
151
+ }
152
+ // $script_element = $document->createElement('script');
153
+ // $script_element->setAttribute('type', 'application/json');
154
+ // $script_element->setAttribute('class', 'op-geoTag');
155
+ // $script_element->appendChild($document->createTextNode($this->geoTag));
156
+ // $element->appendChild($script_element);
157
+
158
+
159
+ // Caption markup optional
160
+ if ($this->caption) {
161
+ $element->appendChild($this->caption->toDOMElement($document));
162
+ }
163
+
164
+ // Audio markup optional
165
+ if ($this->audio) {
166
+ $element->appendChild($this->audio->toDOMElement($document));
167
+ }
168
+
169
+ return $element;
170
+ }
171
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Paragraph.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ /**
12
+ * Each paragraph of article should be an instance of this class.
13
+ *
14
+ * Example:
15
+ * <p> This is the first paragraph of body text. </p>
16
+ *
17
+ * or
18
+ *
19
+ * <p> This is the <i>second</i> paragraph of <b>body text</b>. </p>
20
+ *
21
+ * @see {link:https://developers.intern.facebook.com/docs/instant-articles/reference/body-text}
22
+ */
23
+ class Paragraph extends TextContainer
24
+ {
25
+
26
+ private function __construct()
27
+ {
28
+ }
29
+
30
+ public static function create()
31
+ {
32
+ return new self();
33
+ }
34
+
35
+ /**
36
+ * Structure and create the full Paragraph in a DOMElement.
37
+ *
38
+ * @param DOMDocument $document - The document where this element will be appended (optional).
39
+ */
40
+ public function toDOMElement($document = null)
41
+ {
42
+ if (!$document) {
43
+ $document = new \DOMDocument();
44
+ }
45
+ $paragraph = $document->createElement('p');
46
+
47
+ $paragraph->appendChild($this->textToDOMDocumentFragment($document));
48
+
49
+ return $paragraph;
50
+ }
51
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Pullquote.php ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ * Each paragraph of article should be an instance of this class.
15
+ *
16
+ * Example:
17
+ * <aside> This is the pullquote </p>
18
+ *
19
+ * or
20
+ *
21
+ * <aside>
22
+ * Long life, pull quote will have.
23
+ * <cite>Unknown Jedi</cite>
24
+ * </aside>
25
+ *
26
+ * @see {link:https://developers.intern.facebook.com/docs/instant-articles/reference/body-text}
27
+ */
28
+ class Pullquote extends TextContainer
29
+ {
30
+
31
+ /**
32
+ * @var Cite Content that will be shown on <cite>...</cite> tags.
33
+ */
34
+ private $attribution;
35
+
36
+ private function __construct()
37
+ {
38
+ }
39
+
40
+ public static function create()
41
+ {
42
+ return new self();
43
+ }
44
+
45
+ /**
46
+ * Sets the attribution string
47
+ *
48
+ * @param The attribution text
49
+ */
50
+ public function withAttribution($attribution)
51
+ {
52
+ Type::enforce($attribution, array(Type::STRING, Cite::getClassName()));
53
+ if (Type::is($attribution, Type::STRING)) {
54
+ $this->attribution = Cite::create()->appendText($attribution);
55
+ } else {
56
+ $this->attribution = $attribution;
57
+ }
58
+
59
+ return $this;
60
+ }
61
+
62
+ /**
63
+ * @return Cite The attribution
64
+ */
65
+ public function getAttribution()
66
+ {
67
+ return $this->attribution;
68
+ }
69
+
70
+ /**
71
+ * Structure and create the full Pullquote in a DOMElement.
72
+ *
73
+ * @param DOMDocument $document - The document where this element will be appended (optional).
74
+ */
75
+ public function toDOMElement($document = null)
76
+ {
77
+ if (!$document) {
78
+ $document = new \DOMDocument();
79
+ }
80
+ $element = $document->createElement('aside');
81
+
82
+ $element->appendChild($this->textToDOMDocumentFragment($document));
83
+
84
+ // Attribution Citation
85
+ if ($this->attribution) {
86
+ $element->appendChild($this->attribution->toDOMElement($document));
87
+ }
88
+
89
+ return $element;
90
+ }
91
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/RelatedArticles.php ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 List that represents a simple HTML list
15
+ *
16
+ * Example Unordered:
17
+ * <ul>
18
+ * <li>Dog</li>
19
+ * <li>Cat</li>
20
+ * <li>Fox</li>
21
+ * </ul>
22
+ *
23
+ * Example Ordered:
24
+ * <ol>
25
+ * <li>Groceries</li>
26
+ * <li>School</li>
27
+ * <li>Sleep</li>
28
+ * </ol>
29
+ */
30
+ class RelatedArticles extends Element
31
+ {
32
+ /**
33
+ * @var RelatedItem[] The related Articles
34
+ */
35
+ private $items = array();
36
+
37
+ /**
38
+ * @var string The title of the Related Articles content
39
+ */
40
+ private $title;
41
+
42
+ /**
43
+ * Private constructor.
44
+ * @see List::create()
45
+ */
46
+ private function __construct()
47
+ {
48
+ }
49
+
50
+ /**
51
+ * Factory method for the RelatedArticles list
52
+ * @return RelatedArticles the new instance of RelatedArticles
53
+ */
54
+ public static function create()
55
+ {
56
+ return new self();
57
+ }
58
+
59
+ /**
60
+ * Adds a new related article item
61
+ * @param string The related article URL
62
+ */
63
+ public function addRelated($item)
64
+ {
65
+ Type::enforce($item, RelatedItem::getClassName());
66
+ $this->items[] = $item;
67
+
68
+ return $this;
69
+ }
70
+
71
+ /**
72
+ * Sets the title of Related articles content block
73
+ *
74
+ * @param string the name of related articles block
75
+ */
76
+ public function withTitle($title)
77
+ {
78
+ Type::enforce($title, Type::STRING);
79
+ $this->title = $title;
80
+
81
+ return $this;
82
+ }
83
+
84
+ /**
85
+ * @return RelatedItem[] The RelatedItem's
86
+ */
87
+ public function getItems()
88
+ {
89
+ return $this->items;
90
+ }
91
+
92
+ /**
93
+ * @param string the name of related articles block
94
+ */
95
+ public function getTitle()
96
+ {
97
+ return $this->title;
98
+ }
99
+
100
+ /**
101
+ * Structure and create the full ArticleVideo in a XML format DOMElement.
102
+ *
103
+ * @param $document DOMDocument where this element will be appended. Optional
104
+ */
105
+ public function toDOMElement($document = null)
106
+ {
107
+ if (!$document) {
108
+ $document = new \DOMDocument();
109
+ }
110
+
111
+ $element = $document->createElement('ul');
112
+ $element->setAttribute('class', 'op-related-articles');
113
+ if ($this->title) {
114
+ $element->setAttribute('title', $this->title);
115
+ }
116
+
117
+ if ($this->items) {
118
+ foreach ($this->items as $item) {
119
+ $element->appendChild($item->toDOMElement($document));
120
+ }
121
+ }
122
+
123
+ return $element;
124
+ }
125
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/RelatedItem.php ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 RelatedItem to represent each of the @see RelatedArticles
15
+ */
16
+ class RelatedItem extends Element
17
+ {
18
+ /**
19
+ * @var string The related Article URL
20
+ */
21
+ private $url;
22
+
23
+ /**
24
+ * @var boolean If the article is sponsored
25
+ */
26
+ private $sponsored;
27
+
28
+ /**
29
+ * Private constructor.
30
+ */
31
+ private function __construct()
32
+ {
33
+ }
34
+
35
+ /**
36
+ * Factory method for the RelatedItem
37
+ */
38
+ public static function create()
39
+ {
40
+ return new self();
41
+ }
42
+
43
+ /**
44
+ * Sets the article URL
45
+ * @param string The related article URL
46
+ */
47
+ public function withURL($url)
48
+ {
49
+ Type::enforce($url, Type::STRING);
50
+ $this->url = $url;
51
+
52
+ return $this;
53
+ }
54
+
55
+ /**
56
+ * Makes this item to be an sponsored one
57
+ */
58
+ public function enableSponsored()
59
+ {
60
+ $this->sponsored = true;
61
+
62
+ return $this;
63
+ }
64
+
65
+ /**
66
+ * Makes this item to *NOT* be an sponsored one
67
+ */
68
+ public function disableSponsored()
69
+ {
70
+ $this->sponsored = false;
71
+
72
+ return $this;
73
+ }
74
+
75
+ /**
76
+ * @return string The RelatedItem url
77
+ */
78
+ public function getURL()
79
+ {
80
+ return $this->url;
81
+ }
82
+
83
+ /**
84
+ * @return boolean true if it is sponsored, false otherwise.
85
+ */
86
+ public function isSponsored()
87
+ {
88
+ return $this->sponsored;
89
+ }
90
+
91
+ /**
92
+ * Structure and create the full ArticleVideo in a XML format DOMElement.
93
+ *
94
+ * @param $document DOMDocument where this element will be appended. Optional
95
+ */
96
+ public function toDOMElement($document = null)
97
+ {
98
+ if (!$document) {
99
+ $document = new \DOMDocument();
100
+ }
101
+
102
+ $element = $document->createElement('li');
103
+ if ($this->sponsored) {
104
+ $element->setAttribute('data-sponsored', 'true');
105
+ }
106
+ $element->appendChild(
107
+ Anchor::create()->withHref($this->url)->toDOMElement($document)
108
+ );
109
+
110
+
111
+ return $element;
112
+ }
113
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Slideshow.php ADDED
@@ -0,0 +1,224 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 SlideShow
15
+ * This element Class is the slideshow for the article.
16
+ *
17
+ * Example:
18
+ * <figure class="op-slideshow">
19
+ * <figure>
20
+ * <img src="http://mydomain.com/path/to/img1.jpg" />
21
+ * </figure>
22
+ * <figure>
23
+ * <img src="http://mydomain.com/path/to/img2.jpg" />
24
+ * </figure>
25
+ * <figure>
26
+ * <img src="http://mydomain.com/path/to/img3.jpg" />
27
+ * </figure>
28
+ * </figure>
29
+ *
30
+ * @see {link:https://developers.intern.facebook.com/docs/instant-articles/reference/image}
31
+ */
32
+ class Slideshow extends Audible
33
+ {
34
+ /**
35
+ * @var Caption The caption for the Slideshow
36
+ */
37
+ private $caption;
38
+
39
+ /**
40
+ * @var Image[] the images hosted on web that will be shown on the slideshow
41
+ */
42
+ private $article_images = array();
43
+
44
+ /**
45
+ * @var string The json geotag content inside the script geotag
46
+ */
47
+ private $geotag;
48
+
49
+ /**
50
+ * @var Audio The audio if the Slideshow uses audio
51
+ */
52
+ private $audio;
53
+
54
+ /**
55
+ * @var string The attribution citation text in the <cite>...</cite> tags.
56
+ */
57
+ private $attribution;
58
+
59
+ /**
60
+ * Private constructor.
61
+ * @see Slideshow::create();.
62
+ */
63
+ private function __construct()
64
+ {
65
+ }
66
+
67
+ /**
68
+ * Factory method for the Slideshow
69
+ * @return Slideshow the new instance
70
+ */
71
+ public static function create()
72
+ {
73
+ return new self();
74
+ }
75
+
76
+ /**
77
+ * This sets figcaption tag as documentation. It overrides all sets
78
+ * made with @see Caption.
79
+ *
80
+ * @param Caption the caption the slideshow will have
81
+ */
82
+ public function withCaption($caption)
83
+ {
84
+ Type::enforce($caption, Caption::getClassName());
85
+ $this->caption = $caption;
86
+
87
+ return $this;
88
+ }
89
+
90
+ /**
91
+ * Sets the Image list of images for the slideshow. It is REQUIRED.
92
+ *
93
+ * @param Image[] The images. Ie: http://domain.com/img.png
94
+ */
95
+ public function withImages($article_images)
96
+ {
97
+ Type::enforceArrayOf($article_images, Image::getClassName());
98
+ $this->article_images = $article_images;
99
+
100
+ return $this;
101
+ }
102
+
103
+ /**
104
+ * Adds a new image to the slideshow. It is REQUIRED.
105
+ *
106
+ * @param string[] The url of image. Ie: http://domain.com/img.png
107
+ */
108
+ public function addImage($article_image)
109
+ {
110
+ Type::enforce($article_image, Image::getClassName());
111
+ $this->article_images[] = $article_image;
112
+
113
+ return $this;
114
+ }
115
+
116
+ /**
117
+ * Sets the geotag on the slideshow.
118
+ *
119
+ * @see {link:http://geojson.org/}
120
+ */
121
+ public function withMapGeoTag($json)
122
+ {
123
+ Type::enforce($json, Type::STRING);
124
+ $this->geotag = $json; // TODO Validate the json informed
125
+
126
+ return $this;
127
+ }
128
+
129
+ /**
130
+ * Adds audio to this slideshow.
131
+ *
132
+ * @param Audio The audio object
133
+ */
134
+ public function withAudio($audio)
135
+ {
136
+ Type::enforce($audio, Audio::getClassName());
137
+ $this->audio = $audio;
138
+
139
+ return $this;
140
+ }
141
+
142
+ /**
143
+ * @return Caption The caption object
144
+ */
145
+ public function getCaption()
146
+ {
147
+ return $this->caption;
148
+ }
149
+
150
+ /**
151
+ * @return Image[] The ArticleImages content of the slideshow
152
+ */
153
+ public function getArticleImages()
154
+ {
155
+ return $this->article_images;
156
+ }
157
+
158
+ /**
159
+ * @return string the json for geotag unescaped content
160
+ */
161
+ public function getGeotag()
162
+ {
163
+ return $this->geotag;
164
+ }
165
+
166
+ /**
167
+ * @return Audio The audio object
168
+ */
169
+ public function getAudio()
170
+ {
171
+ return $this->audio;
172
+ }
173
+
174
+ /**
175
+ * @return string the <cite> content
176
+ */
177
+ public function getAttribution()
178
+ {
179
+ return $this->attribution;
180
+ }
181
+
182
+ /**
183
+ * Structure and create the full Slideshow in a XML format DOMElement.
184
+ *
185
+ * @param $document DOMDocument where this element will be appended. Optional
186
+ */
187
+ public function toDOMElement($document = null)
188
+ {
189
+ if (!$document) {
190
+ $document = new \DOMDocument();
191
+ }
192
+ $element = $document->createElement('figure');
193
+ $element->setAttribute('class', 'op-slideshow');
194
+
195
+ // URL markup required
196
+ if ($this->article_images) {
197
+ foreach ($this->article_images as $article_image) {
198
+ $article_image_element = $article_image->toDOMElement($document);
199
+ $element->appendChild($article_image_element);
200
+ }
201
+ }
202
+
203
+ // Caption markup optional
204
+ if ($this->caption) {
205
+ $element->appendChild($this->caption->toDOMElement($document));
206
+ }
207
+
208
+ // Geotag markup optional
209
+ if ($this->geotag) {
210
+ $script_element = $document->createElement('script');
211
+ $script_element->setAttribute('type', 'application/json');
212
+ $script_element->setAttribute('class', 'op-geotag');
213
+ $script_element->appendChild($document->createTextNode($this->geotag));
214
+ $element->appendChild($script_element);
215
+ }
216
+
217
+ // Audio markup optional
218
+ if ($this->audio) {
219
+ $element->appendChild($this->audio->toDOMElement($document));
220
+ }
221
+
222
+ return $element;
223
+ }
224
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/SocialEmbed.php ADDED
@@ -0,0 +1,151 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ * 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
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
+ private function __construct()
43
+ {
44
+ }
45
+
46
+ public static function create()
47
+ {
48
+ return new self();
49
+ }
50
+
51
+ /**
52
+ * Sets the caption for the social embed.
53
+ *
54
+ * @param Caption $caption - Descriptive text for your social embed.
55
+ */
56
+ public function withCaption($caption)
57
+ {
58
+ Type::enforce($caption, Caption::getClassName());
59
+ $this->caption = $caption;
60
+
61
+ return $this;
62
+ }
63
+
64
+ /**
65
+ * Sets the source for the social embed.
66
+ *
67
+ * @param string $source - The source of the content for your social embed.
68
+ */
69
+ public function withSource($source)
70
+ {
71
+ Type::enforce($source, Type::STRING);
72
+ $this->source = $source;
73
+
74
+ return $this;
75
+ }
76
+
77
+ /**
78
+ * Sets the unescaped HTML of your social embed.
79
+ *
80
+ * @param \DOMNode $html - The unescaped HTML of your social embed.
81
+ */
82
+ public function withHTML($html)
83
+ {
84
+ Type::enforce($html, 'DOMNode');
85
+ $this->html = $html;
86
+
87
+ return $this;
88
+ }
89
+
90
+ /**
91
+ * @return Caption - The caption for social embed block
92
+ */
93
+ public function getCaption()
94
+ {
95
+ return $this->caption;
96
+ }
97
+
98
+ /**
99
+ * @return \DOMNode $html - The unescaped HTML of your social embed.
100
+ */
101
+ public function getHtml()
102
+ {
103
+ return $this->html;
104
+ }
105
+
106
+ /**
107
+ * @return string $source - The source of the content for your social embed.
108
+ */
109
+ public function getSource()
110
+ {
111
+ return $this->source;
112
+ }
113
+
114
+ /**
115
+ * Structure and create the full SocialEmbed in a DOMElement.
116
+ *
117
+ * @param DOMDocument $document - The document where this element will be appended (optional).
118
+ */
119
+ public function toDOMElement($document = null)
120
+ {
121
+ if (!$document) {
122
+ $document = new \DOMDocument();
123
+ }
124
+ $figure = $document->createElement('figure');
125
+ $iframe = $document->createElement('iframe');
126
+
127
+ $figure->appendChild($iframe);
128
+
129
+ // Caption markup optional
130
+ if ($this->caption) {
131
+ $figure->appendChild($this->caption->toDOMElement($document));
132
+ }
133
+
134
+ if ($this->source) {
135
+ $iframe->setAttribute('src', $this->source);
136
+ }
137
+
138
+ $figure->setAttribute('class', 'op-social');
139
+
140
+ // SocialEmbed markup
141
+ if ($this->html) {
142
+ // Here we do not care about what is inside the iframe
143
+ // because it'll be rendered in a sandboxed webview
144
+ $this->dangerouslyAppendUnescapedHTML($iframe, $this->html);
145
+ } else {
146
+ $iframe->appendChild($document->createTextNode(''));
147
+ }
148
+
149
+ return $figure;
150
+ }
151
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Span.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ /**
12
+ * A span Text container.
13
+ *
14
+ * @see {link:https://developers.intern.facebook.com/docs/instant-articles/reference/body-text}
15
+ */
16
+ class Span extends TextContainer
17
+ {
18
+
19
+ private function __construct()
20
+ {
21
+ }
22
+
23
+ public static function create()
24
+ {
25
+ return new self();
26
+ }
27
+
28
+ /**
29
+ * Structure and create <span> node.
30
+ *
31
+ * @param DOMDocument $document - The document where this element will be appended (optional).
32
+ */
33
+ public function toDOMElement($document = null)
34
+ {
35
+ if (!$document) {
36
+ $document = new \DOMDocument();
37
+ }
38
+ $span = $document->createElement('span');
39
+
40
+ $span->appendChild($this->textToDOMDocumentFragment($document));
41
+
42
+ return $span;
43
+ }
44
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/TextContainer.php ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 components accepting formatted text. It can contain bold, italic and links.
15
+ *
16
+ * Example:
17
+ * This is a <b>formatted</b> <i>text</i> for <a href="https://foo.com">your article</a>.
18
+ *
19
+ * @see {link:https://developers.intern.facebook.com/docs/instant-articles/reference/body-text}
20
+ */
21
+ abstract class TextContainer extends Element
22
+ {
23
+ /**
24
+ * @var array The content is a list of strings and FormattingElements
25
+ */
26
+ private $textChildren = array();
27
+
28
+ /**
29
+ * Adds content to the formatted text.
30
+ *
31
+ * @param string|FormattedText The content can be a string or a FormattedText.
32
+ */
33
+ public function appendText($child)
34
+ {
35
+ Type::enforce($child, array(Type::STRING, FormattedText::getClassName()));
36
+ $this->textChildren[] = $child;
37
+
38
+ return $this;
39
+ }
40
+
41
+ /**
42
+ * @return array<string|FormattedText> All text token for this text container.
43
+ */
44
+ public function getTextChildren()
45
+ {
46
+ return $this->textChildren;
47
+ }
48
+
49
+ /**
50
+ * Structure and create the full text in a DOMDocumentFragment.
51
+ *
52
+ * @param DOMDocument $document - The document where this element will be appended (optional).
53
+ */
54
+ public function textToDOMDocumentFragment($document = null)
55
+ {
56
+ if (!$document) {
57
+ $document = new \DOMDocument();
58
+ }
59
+
60
+ $fragment = $document->createDocumentFragment();
61
+
62
+ // Generate markup
63
+ foreach ($this->textChildren as $content) {
64
+ if (Type::is($content, Type::STRING)) {
65
+ $text = $document->createTextNode($content);
66
+ $fragment->appendChild($text);
67
+ } else {
68
+ $fragment->appendChild($content->toDOMElement($document));
69
+ }
70
+ }
71
+
72
+ if (!$fragment->hasChildNodes()) {
73
+ $fragment->appendChild($document->createTextNode(''));
74
+ }
75
+
76
+ return $fragment;
77
+ }
78
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Time.php ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Time
15
+ * This represents time of publishing (@see const PUBLISHED) or time of update
16
+ * (@see const MODIFIED).
17
+ *
18
+ *
19
+ * <time
20
+ * class="op-published"
21
+ * datetime={date('c', $this->time)}>
22
+ * {date('F jS, g:ia', $this->time)}
23
+ * </time>
24
+ *
25
+ * or
26
+ *
27
+ * <time
28
+ * class="op-modified"
29
+ * datetime={date('c', $last_update)}>
30
+ * {date('F jS, g:ia', $last_update)}
31
+ * </time>
32
+ */
33
+ class Time extends Element
34
+ {
35
+ /**
36
+ * @const string Represents the type for when article was first published
37
+ */
38
+ const PUBLISHED = 'op-published';
39
+
40
+ /**
41
+ * @const string Represents the type for when article was last modified
42
+ */
43
+ const MODIFIED = 'op-modified';
44
+
45
+ /**
46
+ * @const string The date formater
47
+ */
48
+ const DATE_FORMAT = 'F jS, g:ia';
49
+
50
+ /**
51
+ * @var DateTime The date formater
52
+ */
53
+ private $date;
54
+
55
+ /**
56
+ * @var string The type of this Article time (MODIFIED or PUBLISHED)
57
+ *
58
+ * @see Time::MODIFIED
59
+ * @see Time::PUBLISHED
60
+ */
61
+ private $type;
62
+
63
+ /**
64
+ * Private constructor. Should use @see Time::create();.
65
+ */
66
+ private function __construct()
67
+ {
68
+ }
69
+
70
+ /**
71
+ * @param string The type of this Article time (MODIFIED or PUBLISHED)
72
+ * @see Time::MODIFIED
73
+ * @see Time::PUBLISHED
74
+ */
75
+ public static function create($type)
76
+ {
77
+ $article_time = new self();
78
+ return $article_time->withType($type);
79
+ }
80
+
81
+ /**
82
+ * Overwrites the current type of time
83
+ *
84
+ * @param string The type of this Article time (MODIFIED or PUBLISHED)
85
+ *
86
+ * @see Time::MODIFIED
87
+ * @see Time::PUBLISHED
88
+ */
89
+ public function withType($type)
90
+ {
91
+ Type::enforceWithin(
92
+ $type,
93
+ array(
94
+ Time::MODIFIED,
95
+ Time::PUBLISHED
96
+ )
97
+ );
98
+ $this->type = $type;
99
+
100
+ return $this;
101
+ }
102
+
103
+ /**
104
+ * Overwrites the current date in the object
105
+ *
106
+ * @param DateTime The date formater
107
+ */
108
+ public function withDatetime($date)
109
+ {
110
+ Type::enforce($date, 'DateTime');
111
+ $this->date = $date;
112
+
113
+ return $this;
114
+ }
115
+
116
+ /**
117
+ * @return DateTime The date
118
+ */
119
+ public function getDatetime()
120
+ {
121
+ return $this->date;
122
+ }
123
+
124
+ /**
125
+ * @return string The time type
126
+ *
127
+ * @see Time::MODIFIED
128
+ * @see Time::PUBLISHED
129
+ */
130
+ public function getType()
131
+ {
132
+ return $this->type;
133
+ }
134
+
135
+ /**
136
+ * Structure and create the full Time in a XML format DOMElement.
137
+ *
138
+ * @param $document DOMDocument where this element will be appended. Optional
139
+ */
140
+ public function toDOMElement($document = null)
141
+ {
142
+ if (!$document) {
143
+ $document = new \DOMDocument();
144
+ }
145
+
146
+ $datetime = $this->date->format('c');
147
+ $date = $this->date->format('F jS, g:ia');
148
+
149
+ $element = $document->createElement('time');
150
+ $element->setAttribute('class', $this->type);
151
+ $element->setAttribute('datetime', $datetime);
152
+ $element->appendChild($document->createTextNode($date));
153
+
154
+ return $element;
155
+ }
156
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Video.php ADDED
@@ -0,0 +1,473 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Video
15
+ * This element Class is the video for the article.
16
+ * Also consider to use one of the other media types for an article:
17
+ * <ul>
18
+ * <li>@see Audio</li>
19
+ * <li>@see Image</li>
20
+ * <li>@see SlideShow</li>
21
+ * <li>@see Map</li>
22
+ * </ul>
23
+ *
24
+ * Example:
25
+ * <figure>
26
+ * <video>
27
+ * <source src="http://mydomain.com/path/to/video.mp4" type="video/mp4" />
28
+ * </video>
29
+ * </figure>
30
+ *
31
+ * @package Facebook\InstantArticle\Elements
32
+ */
33
+ class Video extends Element
34
+ {
35
+ const ASPECT_FIT = 'aspect-fit';
36
+ const ASPECT_FIT_ONLY = 'aspect-fit-only';
37
+ const FULLSCREEN = 'fullscreen';
38
+ const NON_INTERACTIVE = 'non-interactive';
39
+
40
+ const LOOP = 'loop';
41
+ const DATA_FADE = 'data-fade';
42
+
43
+ /**
44
+ * @var string The caption for Video
45
+ */
46
+ private $caption;
47
+
48
+ /**
49
+ * @var string The string url for the video hosted on web that will be shown
50
+ * on the article
51
+ */
52
+ private $url;
53
+
54
+ /**
55
+ * @var string The video content type. Default: "video/mp4"
56
+ */
57
+ private $contentType;
58
+
59
+ /**
60
+ * @var boolean Tells if like is enabled. Default: false
61
+ */
62
+ private $isLikeEnabled;
63
+
64
+ /**
65
+ * @var boolean Tells if comments are enabled. Default: false
66
+ */
67
+ private $isCommentsEnabled;
68
+
69
+ /**
70
+ * @var boolean Makes the video the cover on news feed.
71
+ * @see {link:https://developers.facebook.com/docs/instant-articles/reference/feed-preview}
72
+ */
73
+ private $isFeedCover;
74
+
75
+ /**
76
+ * @var string Content that will be shown on <cite>...</cite> tags.
77
+ */
78
+ private $attribution;
79
+
80
+ /**
81
+ * @var string The picture size for the video.
82
+ * @see Video::ASPECT_FIT
83
+ * @see Video::ASPECT_FIT_ONLY
84
+ * @see Video::FULLSCREEN
85
+ * @see Video::NON_INTERACTIVE
86
+ */
87
+ private $presentation;
88
+
89
+ /**
90
+ * @var GeoTag The json geotag content inside the script geotag
91
+ */
92
+ private $geoTag;
93
+
94
+ /**
95
+ * @var string URL for the placeholder Image that will be placed while video not loaded.
96
+ */
97
+ private $imageURL;
98
+
99
+ /**
100
+ * @var boolean Default true, so every video will autoplay.
101
+ */
102
+ private $isAutoplay = true;
103
+
104
+ /**
105
+ * @var boolean Default false, so every video will have no controls.
106
+ */
107
+ private $isControlsShown = false;
108
+
109
+ /**
110
+ * Private constructor.
111
+ * @see Video::create();.
112
+ */
113
+ private function __construct()
114
+ {
115
+ }
116
+
117
+ /**
118
+ * Factory method
119
+ * @return Video the new instance from Video
120
+ */
121
+ public static function create()
122
+ {
123
+ return new self();
124
+ }
125
+
126
+ /**
127
+ * This sets figcaption tag as documentation. It overrides all sets
128
+ * made with @see Caption.
129
+ *
130
+ * @param Caption the caption the video will have
131
+ */
132
+ public function withCaption($caption)
133
+ {
134
+ Type::enforce($caption, Caption::getClassName());
135
+ $this->caption = $caption;
136
+
137
+ return $this;
138
+ }
139
+
140
+ /**
141
+ * Sets the URL for the video. It is REQUIRED.
142
+ *
143
+ * @param string The url of video. Ie: http://domain.com/video.mp4
144
+ */
145
+ public function withURL($url)
146
+ {
147
+ Type::enforce($url, Type::STRING);
148
+ $this->url = $url;
149
+
150
+ return $this;
151
+ }
152
+
153
+ /**
154
+ * Sets the aspect ration presentation for the video.
155
+ *
156
+ * @param string one of the constants ASPECT_FIT, ASPECT_FIT_ONLY, FULLSCREEN or NON_INTERACTIVE
157
+ * @see Video::ASPECT_FIT
158
+ * @see Video::ASPECT_FIT_ONLY
159
+ * @see Video::FULLSCREEN
160
+ * @see Video::NON_INTERACTIVE
161
+ */
162
+ public function withPresentation($presentation)
163
+ {
164
+ Type::enforceWithin(
165
+ $presentation,
166
+ array(
167
+ Video::ASPECT_FIT,
168
+ Video::ASPECT_FIT_ONLY,
169
+ Video::FULLSCREEN,
170
+ Video::NON_INTERACTIVE
171
+ )
172
+ );
173
+ $this->presentation = $presentation;
174
+
175
+ return $this;
176
+ }
177
+
178
+ /**
179
+ * Makes like enabled for this video.
180
+ */
181
+ public function enableLike()
182
+ {
183
+ $this->isLikeEnabled = true;
184
+
185
+ return $this;
186
+ }
187
+
188
+ /**
189
+ * Makes like disabled for this video.
190
+ */
191
+ public function disableLike()
192
+ {
193
+ $this->isLikeEnabled = false;
194
+
195
+ return $this;
196
+ }
197
+
198
+ /**
199
+ * Makes comments enabled for this video.
200
+ */
201
+ public function enableComments()
202
+ {
203
+ $this->isCommentsEnabled = true;
204
+
205
+ return $this;
206
+ }
207
+
208
+ /**
209
+ * Makes comments disabled for this video.
210
+ */
211
+ public function disableComments()
212
+ {
213
+ $this->isCommentsEnabled = false;
214
+
215
+ return $this;
216
+ }
217
+
218
+ /**
219
+ * Enables the video controls
220
+ */
221
+ public function enableControls()
222
+ {
223
+ $this->isControlsShown = true;
224
+
225
+ return $this;
226
+ }
227
+
228
+ /**
229
+ * Disable the video controls
230
+ */
231
+ public function disableControls()
232
+ {
233
+ $this->isControlsShown = false;
234
+
235
+ return $this;
236
+ }
237
+
238
+ /**
239
+ * Enables the video autoplay
240
+ */
241
+ public function enableAutoplay()
242
+ {
243
+ $this->isAutoplay = true;
244
+
245
+ return $this;
246
+ }
247
+
248
+ /**
249
+ * Disable the video autoplay
250
+ */
251
+ public function disableAutoplay()
252
+ {
253
+ $this->isAutoplay = false;
254
+
255
+ return $this;
256
+ }
257
+
258
+ /**
259
+ * Makes video be the cover on newsfeed
260
+ */
261
+ public function enableFeedCover()
262
+ {
263
+ $this->isFeedCover = true;
264
+
265
+ return $this;
266
+ }
267
+
268
+ /**
269
+ * Removes vide from cover on neewsfeed (and it becomes the og:image that was already defined on the link)
270
+ */
271
+ public function disableFeedCover()
272
+ {
273
+ $this->isFeedCover = false;
274
+
275
+ return $this;
276
+ }
277
+
278
+
279
+ /**
280
+ * @param string content type of the video. Ex: "video/mp4"
281
+ */
282
+ public function withContentType($contentType)
283
+ {
284
+ Type::enforce($contentType, Type::STRING);
285
+ $this->contentType = $contentType;
286
+
287
+ return $this;
288
+ }
289
+
290
+ /**
291
+ * Sets the geotag on the video.
292
+ *
293
+ * @see {link:http://geojson.org/}
294
+ */
295
+ public function withGeoTag($geoTag)
296
+ {
297
+ Type::enforce($geoTag, array(Type::STRING, GeoTag::getClassName()));
298
+ if (Type::is($geoTag, Type::STRING)) {
299
+ $this->geoTag = GeoTag::create()->withScript($geoTag);
300
+ } elseif (Type::is($geoTag, GeoTag::getClassName())) {
301
+ $this->geoTag = $geoTag;
302
+ }
303
+
304
+ return $this;
305
+ }
306
+
307
+
308
+ /**
309
+ * Sets the attribution string
310
+ *
311
+ * @param The attribution text
312
+ */
313
+ public function withAttribution($attribution)
314
+ {
315
+ Type::enforce($attribution, Type::STRING);
316
+ $this->attribution = $attribution;
317
+
318
+ return $this;
319
+ }
320
+
321
+ /**
322
+ * @return Caption gets the caption obj
323
+ */
324
+ public function getCaption()
325
+ {
326
+ return $this->caption;
327
+ }
328
+
329
+ /**
330
+ * @return string URL gets the image url
331
+ */
332
+ public function getUrl()
333
+ {
334
+ return $this->url;
335
+ }
336
+
337
+ /**
338
+ * @return string The content-type of video
339
+ */
340
+ public function getContentType()
341
+ {
342
+ return $this->contentType;
343
+ }
344
+
345
+ /**
346
+ * @return boolean tells if the like button is enabled
347
+ */
348
+ public function isLikeEnabled()
349
+ {
350
+ return $this->isLikeEnabled;
351
+ }
352
+
353
+ /**
354
+ * @return boolean tells if the autoplay is enabled
355
+ */
356
+ public function isAutoplay()
357
+ {
358
+ return $this->isAutoplay;
359
+ }
360
+
361
+ /**
362
+ * @return boolean tells if the comments widget is enabled
363
+ */
364
+ public function isCommentsEnabled()
365
+ {
366
+ return $this->isCommentsEnabled;
367
+ }
368
+
369
+ /**
370
+ * @return boolean tells if the controls will be shown
371
+ */
372
+ public function isControlsShown()
373
+ {
374
+ return $this->isControlsShown;
375
+ }
376
+
377
+ /**
378
+ * @return string one of the constants ASPECT_FIT, ASPECT_FIT_ONLY, FULLSCREEN or NON_INTERACTIVE
379
+ * @see Video::ASPECT_FIT
380
+ * @see Video::ASPECT_FIT_ONLY
381
+ * @see Video::FULLSCREEN
382
+ * @see Video::NON_INTERACTIVE
383
+ */
384
+ public function getPresentation()
385
+ {
386
+ return $this->presentation;
387
+ }
388
+
389
+ /**
390
+ * @return GeoTag The geotag content
391
+ */
392
+ public function getGeotag()
393
+ {
394
+ return $this->geoTag;
395
+ }
396
+
397
+ /**
398
+ * Structure and create the full Video in a XML format DOMElement.
399
+ *
400
+ * @param $document DOMDocument where this element will be appended. Optional
401
+ */
402
+ public function toDOMElement($document = null)
403
+ {
404
+ if (!$document) {
405
+ $document = new \DOMDocument();
406
+ }
407
+ $element = $document->createElement('figure');
408
+
409
+ // Presentation
410
+ if ($this->presentation) {
411
+ $element->setAttribute('data-mode', $this->presentation);
412
+ }
413
+
414
+ // Poster frame / Image placeholder
415
+ if ($this->imageURL) {
416
+ $imageElement = $document->createElement('img');
417
+ $imageElement->setAttribute('src', $this->imageURL);
418
+ $element->appendChild($imageElement);
419
+ }
420
+
421
+ if ($this->isFeedCover) {
422
+ $element->setAttribute('class', 'fb-feed-cover');
423
+ }
424
+
425
+ // Like/comments markup optional
426
+ if ($this->isLikeEnabled || $this->isCommentsEnabled) {
427
+ if ($this->isLikeEnabled && $this->isCommentsEnabled) {
428
+ $element->setAttribute('data-feedback', 'fb:likes,fb:comments');
429
+ } elseif ($this->isLikeEnabled) {
430
+ $element->setAttribute('data-feedback', 'fb:likes');
431
+ } else {
432
+ $element->setAttribute('data-feedback', 'fb:comments');
433
+ }
434
+ }
435
+
436
+ // URL markup required
437
+ if ($this->url) {
438
+ $videoElement = $document->createElement('video');
439
+ if (!$this->isAutoplay) {
440
+ $videoElement->setAttribute('data-fb-disable-autoplay', 'data-fb-disable-autoplay');
441
+ }
442
+ if ($this->isControlsShown) {
443
+ $videoElement->setAttribute('controls', 'controls');
444
+ }
445
+ $sourceElement = $document->createElement('source');
446
+ $sourceElement->setAttribute('src', $this->url);
447
+ if ($this->contentType) {
448
+ $sourceElement->setAttribute('type', $this->contentType);
449
+ }
450
+ $videoElement->appendChild($sourceElement);
451
+ $element->appendChild($videoElement);
452
+ }
453
+
454
+ // Caption markup optional
455
+ if ($this->caption) {
456
+ $element->appendChild($this->caption->toDOMElement($document));
457
+ }
458
+
459
+ // Geotag markup optional
460
+ if ($this->geoTag) {
461
+ $element->appendChild($this->geoTag->toDOMElement($document));
462
+ }
463
+
464
+ // Attribution Citation
465
+ if ($this->attribution) {
466
+ $attributionElement = $document->createElement('cite');
467
+ $attributionElement->appendChild($document->createTextNode($this->attribution));
468
+ $element->appendChild($attributionElement);
469
+ }
470
+
471
+ return $element;
472
+ }
473
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Getters/AbstractGetter.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Getters;
10
+
11
+ use Facebook\InstantArticles\Validators\Type;
12
+ use Symfony\Component\CssSelector\CssSelectorConverter;
13
+
14
+ /**
15
+ * Class abstract for all getters.
16
+ */
17
+ abstract class AbstractGetter
18
+ {
19
+ /**
20
+ * Method that should be implemented so it can be Instantiated by @see GetterFactory
21
+ * @param array(string-> string) $configuration With all properties of this Getter
22
+ * @return $this Returns the self instance configurated.
23
+ */
24
+ abstract public function createFrom($configuration);
25
+
26
+ /**
27
+ * Method that should retrieve
28
+ */
29
+ abstract public function get($node);
30
+
31
+ /**
32
+ * Auxiliary method to extract full qualified class name.
33
+ * @return string The full qualified name of class
34
+ */
35
+ public static function getClassName() {
36
+ return get_called_class();
37
+ }
38
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Getters/ChildrenGetter.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Getters;
10
+
11
+ use Facebook\InstantArticles\Validators\Type;
12
+ use Symfony\Component\CssSelector\CssSelectorConverter;
13
+
14
+ class ChildrenGetter extends ElementGetter
15
+ {
16
+ public function get($node)
17
+ {
18
+ $element = parent::get($node);
19
+ if ($element) {
20
+ $fragment = $element->ownerDocument->createDocumentFragment();
21
+ foreach ($element->childNodes as $child) {
22
+ $fragment->appendChild($child->cloneNode(true));
23
+ }
24
+ if ($fragment->hasChildNodes()) {
25
+ return $fragment;
26
+ }
27
+ }
28
+ return null;
29
+ }
30
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Getters/ElementGetter.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Getters;
10
+
11
+ use Facebook\InstantArticles\Validators\Type;
12
+ use Symfony\Component\CssSelector\CssSelectorConverter;
13
+
14
+ class ElementGetter extends AbstractGetter
15
+ {
16
+ public function createFrom($properties)
17
+ {
18
+ return $this->withSelector($properties['selector']);
19
+ }
20
+
21
+ public function findAll($node)
22
+ {
23
+ $domXPath = new \DOMXPath($node->ownerDocument);
24
+ $converter = new CssSelectorConverter();
25
+ $xpath = $converter->toXPath($this->selector);
26
+ return $domXPath->query($xpath, $node);
27
+ }
28
+
29
+ public function withSelector($selector)
30
+ {
31
+ Type::enforce($selector, Type::STRING);
32
+ $this->selector = $selector;
33
+
34
+ return $this;
35
+ }
36
+
37
+ public function get($node)
38
+ {
39
+ $elements = self::findAll($node, $this->selector);
40
+ if (!empty($elements)) {
41
+ return $elements->item(0);
42
+ }
43
+ return null;
44
+ }
45
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Getters/ExistsGetter.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Getters;
10
+
11
+ use Facebook\InstantArticles\Validators\Type;
12
+ use Symfony\Component\CssSelector\CssSelectorConverter;
13
+
14
+ class ExistsGetter extends StringGetter
15
+ {
16
+ public function createFrom($properties)
17
+ {
18
+ if (isset($properties['selector'])) {
19
+ $this->withSelector($properties['selector']);
20
+ }
21
+ if (isset($properties['attribute'])) {
22
+ $this->withAttribute($properties['attribute']);
23
+ }
24
+ }
25
+
26
+ public function get($node)
27
+ {
28
+ Type::enforce($node, 'DOMNode');
29
+ $elements = self::findAll($node, $this->selector);
30
+ if (!empty($elements) && $elements->item(0)) {
31
+ if (!$this->attribute) {
32
+ return true;
33
+ }
34
+ return $elements->item(0)->hasAttribute($this->attribute);
35
+ }
36
+ return false;
37
+ }
38
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Getters/GetterFactory.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Getters;
10
+
11
+ use Facebook\InstantArticles\Transformer\Validators\Type;
12
+
13
+ class GetterFactory
14
+ {
15
+ const TYPE_STRING_GETTER = 'string';
16
+ const TYPE_INTEGER_GETTER = 'int';
17
+ const TYPE_CHILDREN_GETTER = 'children';
18
+ const TYPE_ELEMENT_GETTER = 'element';
19
+ const TYPE_NEXTSIBLING_GETTER = 'sibling';
20
+ const TYPE_EXISTS_GETTER = 'exists';
21
+ const TYPE_XPATH_GETTER = 'xpath';
22
+
23
+ /**
24
+ * Creates an Getter class.
25
+ *
26
+ * array(
27
+ * type => 'string' | 'children',
28
+ * selector => 'img.cover',
29
+ * [attribute] => 'src'
30
+ * )
31
+ * @see StringGetter
32
+ * @see ChildrenGetter
33
+ * @see IntegerGetter
34
+ * @see ElementGetter
35
+ * @see NextSiblingGetter
36
+ * @see ExistsGetter
37
+ * @see XpathGetter
38
+ * @param array<string, string> $getter_configuration that maps the properties for getter
39
+ * @throws InvalidArgumentException if the type is invalid
40
+ */
41
+ public static function create($getter_configuration)
42
+ {
43
+ $GETTERS = array(
44
+ self::TYPE_STRING_GETTER => StringGetter::getClassName(),
45
+ self::TYPE_INTEGER_GETTER => IntegerGetter::getClassName(),
46
+ self::TYPE_CHILDREN_GETTER => ChildrenGetter::getClassName(),
47
+ self::TYPE_ELEMENT_GETTER => ElementGetter::getClassName(),
48
+ self::TYPE_NEXTSIBLING_GETTER => NextSiblingGetter::getClassName(),
49
+ self::TYPE_EXISTS_GETTER => ExistsGetter::getClassName(),
50
+ self::TYPE_XPATH_GETTER => XpathGetter::getClassName()
51
+ );
52
+
53
+ $clazz = $getter_configuration['type'];
54
+ if (array_key_exists($clazz, $GETTERS)) {
55
+ $clazz = $GETTERS[$clazz];
56
+ }
57
+ $instance = new $clazz();
58
+ $instance->createFrom($getter_configuration);
59
+ return $instance;
60
+
61
+ throw new \InvalidArgumentException(
62
+ 'Type not informed or unrecognized. The configuration must have'.
63
+ ' a type of "StringGetter" or "ChildrenGetter"'
64
+ );
65
+ }
66
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Getters/IntegerGetter.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Getters;
10
+
11
+ use Facebook\InstantArticles\Validators\Type;
12
+ use Symfony\Component\CssSelector\CssSelectorConverter;
13
+
14
+ class IntegerGetter extends StringGetter
15
+ {
16
+ public function createFrom($properties)
17
+ {
18
+ if (isset($properties['selector'])) {
19
+ $this->withSelector($properties['selector']);
20
+ }
21
+ if (isset($properties['attribute'])) {
22
+ $this->withAttribute($properties['attribute']);
23
+ }
24
+ }
25
+
26
+ public function get($node)
27
+ {
28
+ Type::enforce($node, 'DOMNode');
29
+ $elements = self::findAll($node, $this->selector);
30
+ if (!empty($elements) && $elements->item(0)) {
31
+ $element = $elements->item(0);
32
+ if ($this->attribute) {
33
+ return intval($element->getAttribute($this->attribute));
34
+ }
35
+ return intval($element->textContent);
36
+ }
37
+ return null;
38
+ }
39
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Getters/NextSiblingGetter.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Getters;
10
+
11
+ use Facebook\InstantArticles\Validators\Type;
12
+ use Symfony\Component\CssSelector\CssSelectorConverter;
13
+
14
+ class NextSiblingGetter extends StringGetter
15
+ {
16
+ public function createFrom($properties)
17
+ {
18
+ if (isset($properties['selector'])) {
19
+ $this->withSelector($properties['selector']);
20
+ }
21
+ if (isset($properties['attribute'])) {
22
+ $this->withAttribute($properties['attribute']);
23
+ }
24
+ }
25
+
26
+ public function get($node)
27
+ {
28
+ Type::enforce($node, 'DOMNode');
29
+ $elements = self::findAll($node, $this->selector);
30
+ if (!empty($elements) && $elements->item(0)) {
31
+ $element = $elements->item(0);
32
+ $element = $element->nextSibling;
33
+ if ($element) {
34
+ if ($this->attribute) {
35
+ return $element->getAttribute($this->attribute);
36
+ }
37
+ return $element->textContent;
38
+ }
39
+ }
40
+ return null;
41
+ }
42
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Getters/StringGetter.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Getters;
10
+
11
+ use Facebook\InstantArticles\Validators\Type;
12
+ use Symfony\Component\CssSelector\CssSelectorConverter;
13
+
14
+ class StringGetter extends ChildrenGetter
15
+ {
16
+ protected $attribute;
17
+
18
+ public function createFrom($properties)
19
+ {
20
+ if (isset($properties['selector'])) {
21
+ $this->withSelector($properties['selector']);
22
+ }
23
+ if (isset($properties['attribute'])) {
24
+ $this->withAttribute($properties['attribute']);
25
+ }
26
+ }
27
+
28
+ public function withAttribute($attribute)
29
+ {
30
+ Type::enforce($attribute, Type::STRING);
31
+ $this->attribute = $attribute;
32
+
33
+ return $this;
34
+ }
35
+
36
+ public function get($node)
37
+ {
38
+ Type::enforce($node, 'DOMNode');
39
+ $elements = self::findAll($node, $this->selector);
40
+ if (!empty($elements) && $elements->item(0)) {
41
+ $element = $elements->item(0);
42
+ if ($this->attribute) {
43
+ return $element->getAttribute($this->attribute);
44
+ }
45
+ return $element->textContent;
46
+ }
47
+ return null;
48
+ }
49
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Getters/XpathGetter.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Getters;
10
+
11
+ use Facebook\InstantArticles\Validators\Type;
12
+ use Symfony\Component\CssSelector\CssSelectorConverter;
13
+
14
+ class XpathGetter extends ChildrenGetter
15
+ {
16
+ protected $attribute;
17
+
18
+ public function createFrom($properties)
19
+ {
20
+ if (isset($properties['selector'])) {
21
+ $this->withSelector($properties['selector']);
22
+ }
23
+ if (isset($properties['attribute'])) {
24
+ $this->withAttribute($properties['attribute']);
25
+ }
26
+ }
27
+
28
+ public function withAttribute($attribute)
29
+ {
30
+ Type::enforce($attribute, Type::STRING);
31
+ $this->attribute = $attribute;
32
+
33
+ return $this;
34
+ }
35
+
36
+ public function get($node)
37
+ {
38
+ Type::enforce($node, 'DOMNode');
39
+ $domXPath = new \DOMXPath($node->ownerDocument);
40
+ $elements = $domXPath->query($this->selector, $node);
41
+
42
+ if (!empty($elements) && $elements->item(0)) {
43
+ $element = $elements->item(0);
44
+ if ($this->attribute) {
45
+ return $element->getAttribute($this->attribute);
46
+ }
47
+ return $element->textContent;
48
+ }
49
+ return null;
50
+ }
51
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/AdRule.php ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\InstantArticle;
12
+ use Facebook\InstantArticles\Elements\Ad;
13
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
14
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
15
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
16
+ use Facebook\InstantArticles\Transformer\Getters\IntegerGetter;
17
+ use Facebook\InstantArticles\Transformer\Warnings\InvalidSelector;
18
+
19
+ class AdRule extends ConfigurationSelectorRule
20
+ {
21
+ const PROPERTY_AD_URL = 'ad.url';
22
+ const PROPERTY_AD_HEIGHT_URL = 'ad.height';
23
+ const PROPERTY_AD_WIDTH_URL = 'ad.width';
24
+ const PROPERTY_AD_EMBED_URL = 'ad.embed';
25
+
26
+ private $header = false;
27
+
28
+ public function __construct()
29
+ {
30
+ }
31
+
32
+ public function getContextClass()
33
+ {
34
+ return InstantArticle::getClassName();
35
+ }
36
+
37
+ public static function create()
38
+ {
39
+ return new AdRule();
40
+ }
41
+
42
+ public static function createFrom($configuration)
43
+ {
44
+ $ad_rule = self::create();
45
+ $ad_rule->withSelector($configuration['selector']);
46
+
47
+ $ad_rule->withProperties(
48
+ array(
49
+ self::PROPERTY_AD_URL,
50
+ self::PROPERTY_AD_HEIGHT_URL,
51
+ self::PROPERTY_AD_WIDTH_URL,
52
+ self::PROPERTY_AD_EMBED_URL
53
+ ),
54
+ $configuration
55
+ );
56
+
57
+ return $ad_rule;
58
+ }
59
+
60
+ public function apply($transformer, $instant_article, $node)
61
+ {
62
+ $ad = Ad::create();
63
+
64
+ // Builds the ad
65
+ $height = $this->getProperty(self::PROPERTY_AD_HEIGHT_URL, $node);
66
+ if ($height) {
67
+ $ad->withHeight($height);
68
+ }
69
+
70
+ $width = $this->getProperty(self::PROPERTY_AD_WIDTH_URL, $node);
71
+ if ($width) {
72
+ $ad->withWidth($width);
73
+ }
74
+
75
+ $url = $this->getProperty(self::PROPERTY_AD_URL, $node);
76
+ if ($url) {
77
+ $ad->withSource($url);
78
+ }
79
+
80
+ $embed_code = $this->getProperty(self::PROPERTY_AD_EMBED_URL, $node);
81
+ if ($embed_code) {
82
+ $ad->withHTML($embed_code);
83
+ }
84
+
85
+ if ($url || $embed_code) {
86
+ $instant_article->addChild($ad);
87
+ } else {
88
+ $transformer->addWarning(
89
+ new InvalidSelector(
90
+ 'embed code or url',
91
+ $instant_article,
92
+ $node,
93
+ $this
94
+ )
95
+ );
96
+ }
97
+
98
+ return $instant_article;
99
+ }
100
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/AnalyticsRule.php ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\InstantArticle;
12
+ use Facebook\InstantArticles\Elements\Analytics;
13
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
14
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
15
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
16
+ use Facebook\InstantArticles\Transformer\Getters\IntegerGetter;
17
+ use Facebook\InstantArticles\Transformer\Warnings\InvalidSelector;
18
+
19
+ class AnalyticsRule extends ConfigurationSelectorRule
20
+ {
21
+ const PROPERTY_TRACKER_URL = 'analytics.url';
22
+ const PROPERTY_TRACKER_EMBED_URL = 'analytics.embed';
23
+
24
+ private $header = false;
25
+
26
+ public function __construct()
27
+ {
28
+ }
29
+
30
+ public function getContextClass()
31
+ {
32
+ return InstantArticle::getClassName();
33
+ }
34
+
35
+ public static function create()
36
+ {
37
+ return new AnalyticsRule();
38
+ }
39
+
40
+ public static function createFrom($configuration)
41
+ {
42
+ $analytics_rule = self::create();
43
+ $analytics_rule->withSelector($configuration['selector']);
44
+
45
+ $analytics_rule->withProperties(
46
+ array(
47
+ self::PROPERTY_TRACKER_URL,
48
+ self::PROPERTY_TRACKER_EMBED_URL
49
+ ),
50
+ $configuration
51
+ );
52
+
53
+ return $analytics_rule;
54
+ }
55
+
56
+ public function apply($transformer, $instant_article, $node)
57
+ {
58
+ $analytics = Analytics::create();
59
+
60
+ // Builds the analytics
61
+ $url = $this->getProperty(self::PROPERTY_TRACKER_URL, $node);
62
+ if ($url) {
63
+ $analytics->withSource($url);
64
+ }
65
+
66
+ $embed_code = $this->getProperty(self::PROPERTY_TRACKER_EMBED_URL, $node);
67
+ if ($embed_code) {
68
+ $analytics->withHTML($embed_code);
69
+ }
70
+
71
+ if ($url || $embed_code) {
72
+ $instant_article->addChild($analytics);
73
+ } else {
74
+ $transformer->addWarning(
75
+ new InvalidSelector(
76
+ 'embed code or url',
77
+ $instant_article,
78
+ $node,
79
+ $this
80
+ )
81
+ );
82
+ }
83
+
84
+ return $instant_article;
85
+ }
86
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/AnchorRule.php ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\TextContainer;
12
+ use Facebook\InstantArticles\Elements\Anchor;
13
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
14
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
15
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
16
+
17
+ class AnchorRule extends ConfigurationSelectorRule
18
+ {
19
+ const PROPERTY_ANCHOR_HREF = 'anchor.href';
20
+ const PROPERTY_ANCHOR_REL = 'anchor.rel';
21
+
22
+ public function __construct()
23
+ {
24
+ }
25
+
26
+ public static function create()
27
+ {
28
+ return new AnchorRule();
29
+ }
30
+
31
+ public function getContextClass()
32
+ {
33
+ return TextContainer::getClassName();
34
+ }
35
+
36
+ public static function createFrom($configuration)
37
+ {
38
+ $anchor_rule = self::create();
39
+
40
+ $anchor_rule->withSelector($configuration['selector']);
41
+ $properties = $configuration['properties'];
42
+ $anchor_rule->withProperties(
43
+ array(
44
+ self::PROPERTY_ANCHOR_HREF,
45
+ self::PROPERTY_ANCHOR_REL
46
+ ),
47
+ $properties
48
+ );
49
+
50
+ return $anchor_rule;
51
+ }
52
+
53
+ public function apply($transformer, $text_container, $element)
54
+ {
55
+ $anchor = Anchor::create();
56
+
57
+ $url = $this->getProperty(self::PROPERTY_ANCHOR_HREF, $element);
58
+ $rel = $this->getProperty(self::PROPERTY_ANCHOR_REL, $element);
59
+
60
+ if ($url) {
61
+ $anchor->withHref($url);
62
+ }
63
+ if ($rel) {
64
+ $anchor->withRel($rel);
65
+ }
66
+ $text_container->appendText($anchor);
67
+ $transformer->transform($anchor, $element);
68
+
69
+ return $text_container;
70
+ }
71
+
72
+ public function loadFrom($configuration)
73
+ {
74
+ $this->selector = $configuration['selector'];
75
+ }
76
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/AudioRule.php ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Audio;
13
+ use Facebook\InstantArticles\Elements\Caption;
14
+ use Facebook\InstantArticles\Elements\Audible;
15
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
16
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
17
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
18
+ use Facebook\InstantArticles\Transformer\Warnings\InvalidSelector;
19
+
20
+ class AudioRule extends ConfigurationSelectorRule
21
+ {
22
+ const PROPERTY_AUDIO_URL = 'audio.url';
23
+ const PROPERTY_AUDIO_TITLE = 'audio.title';
24
+ const PROPERTY_AUDIO_AUTOPLAY = 'audio.autoplay';
25
+ const PROPERTY_AUDIO_MUTED = 'audio.muted';
26
+
27
+ public function getContextClass()
28
+ {
29
+ return Audible::getClassName();
30
+ }
31
+
32
+ public static function create()
33
+ {
34
+ return new AudioRule();
35
+ }
36
+
37
+ public static function createFrom($configuration)
38
+ {
39
+ $audio_rule = self::create();
40
+ $audio_rule->withSelector($configuration['selector']);
41
+
42
+ $audio_rule->withProperties(
43
+ array(
44
+ self::PROPERTY_AUDIO_URL,
45
+ self::PROPERTY_AUDIO_TITLE,
46
+ self::PROPERTY_AUDIO_AUTOPLAY,
47
+ self::PROPERTY_AUDIO_MUTED
48
+ ),
49
+ $configuration
50
+ );
51
+
52
+ return $audio_rule;
53
+ }
54
+
55
+ public function apply($transformer, $audible, $node)
56
+ {
57
+ $audio = Audio::create();
58
+
59
+ // Builds the image
60
+ $url = $this->getProperty(self::PROPERTY_AUDIO_URL, $node);
61
+ $title = $this->getProperty(self::PROPERTY_AUDIO_TITLE, $node);
62
+ $autoplay = $this->getProperty(self::PROPERTY_AUDIO_AUTOPLAY, $node);
63
+ $muted = $this->getProperty(self::PROPERTY_AUDIO_MUTED, $node);
64
+
65
+ if ($url) {
66
+ $audio->withURL($url);
67
+ $audible->withAudio($audio);
68
+ } else {
69
+ // URL is a required field for Audio
70
+ $transformer->addWarning(
71
+ new InvalidSelector(
72
+ self::PROPERTY_AUDIO_URL,
73
+ $audible,
74
+ $node,
75
+ $this
76
+ )
77
+ );
78
+ }
79
+
80
+ if ($title) {
81
+ $audio->withTitle($title);
82
+ }
83
+ if ($autoplay === "" || $autoplay === "true" || $autoplay === "autoplay") {
84
+ $audio->enableAutoplay();
85
+ }
86
+ if ($muted === "" || $muted === "true" || $muted === "muted") {
87
+ $audio->enableMuted();
88
+ }
89
+
90
+ return $audible;
91
+ }
92
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/AuthorRule.php ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Author;
13
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
14
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
15
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
16
+ use Facebook\InstantArticles\Transformer\Warnings\InvalidSelector;
17
+
18
+ class AuthorRule extends ConfigurationSelectorRule
19
+ {
20
+ const PROPERTY_AUTHOR_URL = 'author.url';
21
+ const PROPERTY_AUTHOR_NAME = 'author.name';
22
+ const PROPERTY_AUTHOR_ROLE_CONTRIBUTION = 'author.role_contribution';
23
+ const PROPERTY_AUTHOR_DESCRIPTION = 'author.description';
24
+
25
+ public function getContextClass()
26
+ {
27
+ return $this->contextClass = Header::getClassName();
28
+ }
29
+
30
+ public static function create()
31
+ {
32
+ return new AuthorRule();
33
+ }
34
+
35
+ public static function createFrom($configuration)
36
+ {
37
+ $author_rule = AuthorRule::create();
38
+
39
+ $author_rule->withSelector($configuration['selector']);
40
+ $properties = $configuration['properties'];
41
+ $author_rule->withProperties(
42
+ array(
43
+ self::PROPERTY_AUTHOR_URL,
44
+ self::PROPERTY_AUTHOR_NAME,
45
+ self::PROPERTY_AUTHOR_DESCRIPTION,
46
+ self::PROPERTY_AUTHOR_ROLE_CONTRIBUTION
47
+ ),
48
+ $properties
49
+ );
50
+
51
+ return $author_rule;
52
+ }
53
+
54
+ public function apply($transformer, $header, $node)
55
+ {
56
+ $author = Author::create();
57
+
58
+ // Builds the author
59
+
60
+ $url = $this->getProperty(self::PROPERTY_AUTHOR_URL, $node);
61
+ $name = $this->getProperty(self::PROPERTY_AUTHOR_NAME, $node);
62
+ $role_contribution = $this->getProperty(self::PROPERTY_AUTHOR_ROLE_CONTRIBUTION, $node);
63
+ $description = $this->getProperty(self::PROPERTY_AUTHOR_DESCRIPTION, $node);
64
+
65
+ if ($name) {
66
+ $author->withName($name);
67
+ $header->addAuthor($author);
68
+ } else {
69
+ $transformer->addWarning(
70
+ new InvalidSelector(
71
+ self::PROPERTY_AUTHOR_NAME,
72
+ $header,
73
+ $node,
74
+ $this
75
+ )
76
+ );
77
+ }
78
+
79
+ if ($role_contribution) {
80
+ $author->withRoleContribution($role_contribution);
81
+ }
82
+
83
+ if ($description) {
84
+ $author->withDescription($description);
85
+ }
86
+
87
+ if ($url) {
88
+ $author->withURL($url);
89
+ }
90
+
91
+ return $header;
92
+ }
93
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/BlockquoteRule.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\InstantArticle;
12
+ use Facebook\InstantArticles\Elements\Blockquote;
13
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
14
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
15
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
16
+
17
+ class BlockquoteRule extends ConfigurationSelectorRule
18
+ {
19
+ public function __construct()
20
+ {
21
+ }
22
+
23
+ public function getContextClass()
24
+ {
25
+ return InstantArticle::getClassName();
26
+ }
27
+
28
+ public static function create()
29
+ {
30
+ return new BlockquoteRule();
31
+ }
32
+
33
+ public static function createFrom($configuration)
34
+ {
35
+ return self::create()->withSelector($configuration['selector']);
36
+ }
37
+
38
+ public function apply($transformer, $instant_article, $element)
39
+ {
40
+ $blockquote = Blockquote::create();
41
+ $instant_article->addChild($blockquote);
42
+ $transformer->transform($blockquote, $element);
43
+ return $instant_article;
44
+ }
45
+
46
+ public function loadFrom($configuration)
47
+ {
48
+ $this->selector = $configuration['selector'];
49
+ }
50
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/BoldRule.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\TextContainer;
12
+ use Facebook\InstantArticles\Elements\Bold;
13
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
14
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
15
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
16
+
17
+ class BoldRule extends ConfigurationSelectorRule
18
+ {
19
+ public function __construct()
20
+ {
21
+ }
22
+
23
+ public function getContextClass()
24
+ {
25
+ return $this->contextClass = TextContainer::getClassName();
26
+ }
27
+
28
+ public static function create()
29
+ {
30
+ return new BoldRule();
31
+ }
32
+
33
+ public static function createFrom($configuration)
34
+ {
35
+ return self::create()->withSelector($configuration['selector']);
36
+ }
37
+
38
+ public function apply($transformer, $text_container, $element)
39
+ {
40
+ $bold = Bold::create();
41
+ $text_container->appendText($bold);
42
+ $transformer->transform($bold, $element);
43
+ return $text_container;
44
+ }
45
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/CaptionCreditRule.php ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Caption;
12
+ use Facebook\InstantArticles\Elements\Cite;
13
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
14
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
15
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
16
+
17
+ class CaptionCreditRule extends ConfigurationSelectorRule
18
+ {
19
+ public function getContextClass()
20
+ {
21
+ return Caption::getClassName();
22
+ }
23
+
24
+ public static function create()
25
+ {
26
+ return new CaptionCreditRule();
27
+ }
28
+
29
+ public static function createFrom($configuration)
30
+ {
31
+ $cite_rule = self::create();
32
+ $cite_rule->withSelector($configuration['selector']);
33
+
34
+ $cite_rule->withProperties(
35
+ array(
36
+ Caption::POSITION_BELOW,
37
+ Caption::POSITION_CENTER,
38
+ Caption::POSITION_ABOVE,
39
+
40
+ Caption::ALIGN_LEFT,
41
+ Caption::ALIGN_CENTER,
42
+ Caption::ALIGN_RIGHT
43
+ ),
44
+ $configuration
45
+ );
46
+
47
+ return $cite_rule;
48
+ }
49
+
50
+ public function apply($transformer, $caption, $node)
51
+ {
52
+ $cite = Cite::create();
53
+ $caption->withCredit($cite);
54
+
55
+ if ($this->getProperty(Caption::POSITION_BELOW, $node)) {
56
+ $cite->withPostion(Caption::POSITION_BELOW);
57
+ }
58
+ if ($this->getProperty(Caption::POSITION_CENTER, $node)) {
59
+ $cite->withPostion(Caption::POSITION_CENTER);
60
+ }
61
+ if ($this->getProperty(Caption::POSITION_ABOVE, $node)) {
62
+ $cite->withPostion(Caption::POSITION_ABOVE);
63
+ }
64
+
65
+ if ($this->getProperty(Caption::ALIGN_LEFT, $node)) {
66
+ $cite->withTextAlignment(Caption::ALIGN_LEFT);
67
+ }
68
+ if ($this->getProperty(Caption::ALIGN_CENTER, $node)) {
69
+ $cite->withTextAlignment(Caption::ALIGN_CENTER);
70
+ }
71
+ if ($this->getProperty(Caption::ALIGN_RIGHT, $node)) {
72
+ $cite->withTextAlignment(Caption::ALIGN_RIGHT);
73
+ }
74
+
75
+ $transformer->transform($cite, $node);
76
+ return $caption;
77
+ }
78
+
79
+ public function loadFrom($configuration)
80
+ {
81
+ $this->selector = $configuration['selector'];
82
+ }
83
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/CaptionRule.php ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Map;
12
+ use Facebook\InstantArticles\Elements\Interactive;
13
+ use Facebook\InstantArticles\Elements\Slideshow;
14
+ use Facebook\InstantArticles\Elements\SocialEmbed;
15
+ use Facebook\InstantArticles\Elements\Video;
16
+ use Facebook\InstantArticles\Elements\Image;
17
+ use Facebook\InstantArticles\Elements\Caption;
18
+ use Facebook\InstantArticles\Elements\InstantArticle;
19
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
20
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
21
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
22
+
23
+ class CaptionRule extends ConfigurationSelectorRule
24
+ {
25
+ const PROPERTY_DEFAULT = 'caption.default';
26
+
27
+ public function getContextClass()
28
+ {
29
+ return
30
+ array(
31
+ Map::getClassName(),
32
+ Image::getClassName(),
33
+ Interactive::getClassName(),
34
+ Slideshow::getClassName(),
35
+ SocialEmbed::getClassName(),
36
+ Video::getClassName()
37
+ );
38
+ }
39
+
40
+ public static function create()
41
+ {
42
+ return new CaptionRule();
43
+ }
44
+
45
+ public static function createFrom($configuration)
46
+ {
47
+ $caption_rule = self::create();
48
+ $caption_rule->withSelector($configuration['selector']);
49
+
50
+ $caption_rule->withProperties(
51
+ array(
52
+ Caption::POSITION_BELOW,
53
+ Caption::POSITION_CENTER,
54
+ Caption::POSITION_ABOVE,
55
+
56
+ Caption::ALIGN_LEFT,
57
+ Caption::ALIGN_CENTER,
58
+ Caption::ALIGN_RIGHT,
59
+
60
+ Caption::SIZE_MEDIUM,
61
+ Caption::SIZE_LARGE,
62
+ Caption::SIZE_XLARGE,
63
+
64
+ self::PROPERTY_DEFAULT
65
+ ),
66
+ $configuration
67
+ );
68
+
69
+ return $caption_rule;
70
+ }
71
+
72
+ public function apply($transformer, $container_of_caption, $node)
73
+ {
74
+ $caption = Caption::create();
75
+ $container_of_caption->withCaption($caption);
76
+
77
+ if ($this->getProperty(Caption::POSITION_BELOW, $node)) {
78
+ $caption->withPostion(Caption::POSITION_BELOW);
79
+ }
80
+ if ($this->getProperty(Caption::POSITION_CENTER, $node)) {
81
+ $caption->withPostion(Caption::POSITION_CENTER);
82
+ }
83
+ if ($this->getProperty(Caption::POSITION_ABOVE, $node)) {
84
+ $caption->withPostion(Caption::POSITION_ABOVE);
85
+ }
86
+
87
+ if ($this->getProperty(Caption::ALIGN_LEFT, $node)) {
88
+ $caption->withTextAlignment(Caption::ALIGN_LEFT);
89
+ }
90
+ if ($this->getProperty(Caption::ALIGN_CENTER, $node)) {
91
+ $caption->withTextAlignment(Caption::ALIGN_CENTER);
92
+ }
93
+ if ($this->getProperty(Caption::ALIGN_RIGHT, $node)) {
94
+ $caption->withTextAlignment(Caption::ALIGN_RIGHT);
95
+ }
96
+
97
+ if ($this->getProperty(Caption::SIZE_MEDIUM, $node)) {
98
+ $caption->withFontsize(Caption::SIZE_MEDIUM);
99
+ }
100
+ if ($this->getProperty(Caption::SIZE_LARGE, $node)) {
101
+ $caption->withFontsize(Caption::SIZE_LARGE);
102
+ }
103
+ if ($this->getProperty(Caption::SIZE_XLARGE, $node)) {
104
+ $caption->withFontsize(Caption::SIZE_XLARGE);
105
+ }
106
+
107
+ $text_default = $this->getProperty(self::PROPERTY_DEFAULT, $node);
108
+ $log = \Logger::getLogger('facebook-instantarticles-transformer');
109
+ $log->debug($node->ownerDocument->saveXML($node));
110
+ if ($text_default) {
111
+ $caption->withTitle($text_default);
112
+ } else {
113
+ $transformer->transform($caption, $node);
114
+ }
115
+
116
+ return $container_of_caption;
117
+ }
118
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/ConfigurationSelectorRule.php ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Symfony\Component\CssSelector\CssSelectorConverter;
12
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
13
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
14
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
15
+ use Facebook\InstantArticles\Validators\Type;
16
+
17
+ abstract class ConfigurationSelectorRule extends Rule
18
+ {
19
+ protected $selector;
20
+ protected $properties = array();
21
+
22
+ public function withSelector($selector)
23
+ {
24
+ $this->selector = $selector;
25
+ return $this;
26
+ }
27
+
28
+ public function withProperty($property, $value)
29
+ {
30
+ if ($value) {
31
+ $this->properties[$property] = GetterFactory::create($value);
32
+ }
33
+ return $this;
34
+ }
35
+
36
+ public function withProperties($properties, $configuration)
37
+ {
38
+ Type::enforceArrayOf($properties, Type::STRING);
39
+ foreach ($properties as $property) {
40
+ $this->withProperty(
41
+ $property,
42
+ self::retrieveProperty($configuration, $property)
43
+ );
44
+ }
45
+ }
46
+
47
+ public function matchesContext($context)
48
+ {
49
+ if (Type::is($context, $this->getContextClass())) {
50
+ return true;
51
+ }
52
+ return false;
53
+ }
54
+
55
+ public function matchesNode($node)
56
+ {
57
+ if ($this->selector === 'html' && $node->nodeName === 'html') {
58
+ return true;
59
+ }
60
+
61
+ $document = $node->ownerDocument;
62
+ $domXPath = new \DOMXPath($document);
63
+
64
+ if (substr($this->selector, 0, 1) === '/') {
65
+ $xpath = $this->selector;
66
+ } else {
67
+ $converter = new CssSelectorConverter();
68
+ $xpath = $converter->toXPath($this->selector);
69
+ }
70
+
71
+ $results = $domXPath->query($xpath);
72
+
73
+ foreach ($results as $result) {
74
+ if ($result === $node) {
75
+ return true;
76
+ }
77
+ }
78
+ return false;
79
+ }
80
+
81
+ public function findAll($node, $selector)
82
+ {
83
+ $domXPath = new \DOMXPath($node->ownerDocument);
84
+ $converter = new CssSelectorConverter();
85
+ $xpath = $converter->toXPath($selector);
86
+ return $domXPath->query($xpath, $node);
87
+ }
88
+
89
+ public function getProperty($property_name, $node)
90
+ {
91
+ $value = null;
92
+ if (isset($this->properties[$property_name])) {
93
+ $value = $this->properties[$property_name]->get($node);
94
+ }
95
+ return $value;
96
+ }
97
+
98
+ public function getProperties()
99
+ {
100
+ return $this->properties;
101
+ }
102
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/FooterRelatedArticlesRule.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\Transformer\Rules;
10
+
11
+ use Facebook\InstantArticles\Elements\RelatedArticles;
12
+ use Facebook\InstantArticles\Elements\Footer;
13
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
14
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
15
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
16
+
17
+ class FooterRelatedArticlesRule extends ConfigurationSelectorRule
18
+ {
19
+ const PROPERTY_TITLE = 'related.title';
20
+
21
+ public function __construct()
22
+ {
23
+ }
24
+
25
+ public function getContextClass()
26
+ {
27
+ return Footer::getClassName();
28
+ }
29
+
30
+ public static function create()
31
+ {
32
+ return new FooterRelatedArticlesRule();
33
+ }
34
+
35
+ public static function createFrom($configuration)
36
+ {
37
+ $related_articles_rule = self::create();
38
+ $related_articles_rule->withSelector($configuration['selector']);
39
+
40
+ $related_articles_rule->withProperty(
41
+ self::PROPERTY_TITLE,
42
+ self::retrieveProperty($configuration, self::PROPERTY_TITLE)
43
+ );
44
+
45
+ return $related_articles_rule;
46
+ }
47
+
48
+ public function apply($transformer, $footer, $node)
49
+ {
50
+ $related_articles = RelatedArticles::create();
51
+
52
+ // Builds the image
53
+ $title = $this->getProperty(self::PROPERTY_TITLE, $node);
54
+ if ($title) {
55
+ $related_articles->withTitle($title);
56
+ $footer->withRelatedArticles($related_articles);
57
+ }
58
+
59
+ $transformer->transform($related_articles, $node);
60
+
61
+ return $footer;
62
+ }
63
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/FooterRule.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\InstantArticle;
12
+ use Facebook\InstantArticles\Elements\Paragraph;
13
+ use Facebook\InstantArticles\Elements\Footer;
14
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
15
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
16
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
17
+
18
+ class FooterRule extends ConfigurationSelectorRule
19
+ {
20
+ public function __construct()
21
+ {
22
+ }
23
+
24
+ public function getContextClass()
25
+ {
26
+ return InstantArticle::getClassName();
27
+ }
28
+
29
+ public static function create()
30
+ {
31
+ return new FooterRule();
32
+ }
33
+
34
+ public static function createFrom($configuration)
35
+ {
36
+ return self::create()->withSelector($configuration['selector']);
37
+ }
38
+
39
+ public function apply($transformer, $instant_article, $element)
40
+ {
41
+ $footer = Footer::create();
42
+ $instant_article->withFooter($footer);
43
+ $transformer->transform($footer, $element);
44
+ return $instant_article;
45
+ }
46
+
47
+ public function loadFrom($configuration)
48
+ {
49
+ $this->selector = $configuration['selector'];
50
+ }
51
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/GeoTagRule.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Video;
13
+ use Facebook\InstantArticles\Elements\Map;
14
+ use Facebook\InstantArticles\Elements\GeoTag;
15
+ use Facebook\InstantArticles\Elements\Caption;
16
+ use Facebook\InstantArticles\Elements\InstantArticle;
17
+ use Facebook\InstantArticles\Transformer\Warnings\InvalidSelector;
18
+
19
+ class GeoTagRule extends ConfigurationSelectorRule
20
+ {
21
+ const PROPERTY_MAP_GEOTAG = 'map.geotag';
22
+
23
+ public function getContextClass()
24
+ {
25
+ return array(Image::getClassName(), Video::getClassName(), Map::getClassName());
26
+ }
27
+
28
+ public static function create()
29
+ {
30
+ return new GeoTagRule();
31
+ }
32
+
33
+ public static function createFrom($configuration)
34
+ {
35
+ $geo_tag_rule = self::create();
36
+ $geo_tag_rule->withSelector($configuration['selector']);
37
+
38
+ $geo_tag_rule->withProperty(
39
+ self::PROPERTY_MAP_GEOTAG,
40
+ self::retrieveProperty($configuration, self::PROPERTY_MAP_GEOTAG)
41
+ );
42
+
43
+ return $geo_tag_rule;
44
+ }
45
+
46
+ public function apply($transformer, $media_container, $node)
47
+ {
48
+ $geo_tag = GeoTag::create();
49
+
50
+ // Builds the image
51
+ $script = $this->getProperty(self::PROPERTY_MAP_GEOTAG, $node);
52
+ if ($script) {
53
+ $geo_tag->withScript($script);
54
+ $media_container->withGeoTag($geo_tag);
55
+ } else {
56
+ $transformer->addWarning(
57
+ new InvalidSelector(
58
+ self::PROPERTY_MAP_GEOTAG,
59
+ $media_container,
60
+ $node,
61
+ $this
62
+ )
63
+ );
64
+ }
65
+
66
+ return $media_container;
67
+ }
68
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/H1Rule.php ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Caption;
12
+ use Facebook\InstantArticles\Elements\H1;
13
+ use Facebook\InstantArticles\Elements\Instantarticle;
14
+ use Facebook\InstantArticles\Validators\Type;
15
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
16
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
17
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
18
+
19
+ class H1Rule extends ConfigurationSelectorRule
20
+ {
21
+ public function getContextClass()
22
+ {
23
+ return array(Caption::getClassName(), InstantArticle::getClassName());
24
+ }
25
+
26
+ public static function create()
27
+ {
28
+ return new H1Rule();
29
+ }
30
+
31
+ public static function createFrom($configuration)
32
+ {
33
+ $h1_rule = self::create();
34
+ $h1_rule->withSelector($configuration['selector']);
35
+
36
+ $h1_rule->withProperties(
37
+ array(
38
+ Caption::POSITION_BELOW,
39
+ Caption::POSITION_CENTER,
40
+ Caption::POSITION_ABOVE,
41
+
42
+ Caption::ALIGN_LEFT,
43
+ Caption::ALIGN_CENTER,
44
+ Caption::ALIGN_RIGHT,
45
+
46
+ Caption::SIZE_MEDIUM,
47
+ Caption::SIZE_LARGE,
48
+ Caption::SIZE_XLARGE
49
+ ),
50
+ $configuration
51
+ );
52
+
53
+ return $h1_rule;
54
+ }
55
+
56
+ public function apply($transformer, $context_element, $node)
57
+ {
58
+ $h1 = H1::create();
59
+ if (Type::is($context_element, Caption::getClassName())) {
60
+ $context_element->withTitle($h1);
61
+ } elseif (Type::is($context_element, InstantArticle::getClassName())) {
62
+ $context_element->addChild($h1);
63
+ }
64
+
65
+ if ($this->getProperty(Caption::POSITION_BELOW, $node)) {
66
+ $h1->withPostion(Caption::POSITION_BELOW);
67
+ }
68
+ if ($this->getProperty(Caption::POSITION_CENTER, $node)) {
69
+ $h1->withPostion(Caption::POSITION_CENTER);
70
+ }
71
+ if ($this->getProperty(Caption::POSITION_ABOVE, $node)) {
72
+ $h1->withPostion(Caption::POSITION_ABOVE);
73
+ }
74
+
75
+ if ($this->getProperty(Caption::ALIGN_LEFT, $node)) {
76
+ $h1->withTextAlignment(Caption::ALIGN_LEFT);
77
+ }
78
+ if ($this->getProperty(Caption::ALIGN_CENTER, $node)) {
79
+ $h1->withTextAlignment(Caption::ALIGN_CENTER);
80
+ }
81
+ if ($this->getProperty(Caption::ALIGN_RIGHT, $node)) {
82
+ $h1->withTextAlignment(Caption::ALIGN_RIGHT);
83
+ }
84
+
85
+ $transformer->transform($h1, $node);
86
+ return $context_element;
87
+ }
88
+
89
+ public function loadFrom($configuration)
90
+ {
91
+ $this->selector = $configuration['selector'];
92
+ }
93
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/H2Rule.php ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Caption;
12
+ use Facebook\InstantArticles\Elements\H2;
13
+ use Facebook\InstantArticles\Elements\Instantarticle;
14
+ use Facebook\InstantArticles\Validators\Type;
15
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
16
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
17
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
18
+
19
+ class H2Rule extends ConfigurationSelectorRule
20
+ {
21
+ public function getContextClass()
22
+ {
23
+ return array(Caption::getClassName(), InstantArticle::getClassName());
24
+ }
25
+
26
+ public static function create()
27
+ {
28
+ return new H2Rule();
29
+ }
30
+
31
+ public static function createFrom($configuration)
32
+ {
33
+ $h2_rule = self::create();
34
+ $h2_rule->withSelector($configuration['selector']);
35
+
36
+ $h2_rule->withProperties(
37
+ array(
38
+ Caption::POSITION_BELOW,
39
+ Caption::POSITION_CENTER,
40
+ Caption::POSITION_ABOVE,
41
+
42
+ Caption::ALIGN_LEFT,
43
+ Caption::ALIGN_CENTER,
44
+ Caption::ALIGN_RIGHT
45
+ ),
46
+ $configuration
47
+ );
48
+
49
+ return $h2_rule;
50
+ }
51
+
52
+ public function apply($transformer, $context_element, $node)
53
+ {
54
+ $h2 = H2::create();
55
+ if (Type::is($context_element, Caption::getClassName())) {
56
+ $context_element->withSubTitle($h2);
57
+ } elseif (Type::is($context_element, InstantArticle::getClassName())) {
58
+ $context_element->addChild($h2);
59
+ }
60
+
61
+ if ($this->getProperty(Caption::POSITION_BELOW, $node)) {
62
+ $h2->withPostion(Caption::POSITION_BELOW);
63
+ }
64
+ if ($this->getProperty(Caption::POSITION_CENTER, $node)) {
65
+ $h2->withPostion(Caption::POSITION_CENTER);
66
+ }
67
+ if ($this->getProperty(Caption::POSITION_ABOVE, $node)) {
68
+ $h2->withPostion(Caption::POSITION_ABOVE);
69
+ }
70
+
71
+ if ($this->getProperty(Caption::ALIGN_LEFT, $node)) {
72
+ $h2->withTextAlignment(Caption::ALIGN_LEFT);
73
+ }
74
+ if ($this->getProperty(Caption::ALIGN_CENTER, $node)) {
75
+ $h2->withTextAlignment(Caption::ALIGN_CENTER);
76
+ }
77
+ if ($this->getProperty(Caption::ALIGN_RIGHT, $node)) {
78
+ $h2->withTextAlignment(Caption::ALIGN_RIGHT);
79
+ }
80
+
81
+ $transformer->transform($h2, $node);
82
+ return $context_element;
83
+ }
84
+
85
+ public function loadFrom($configuration)
86
+ {
87
+ $this->selector = $configuration['selector'];
88
+ }
89
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/HeaderAdRule.php ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Ad;
13
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
14
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
15
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
16
+ use Facebook\InstantArticles\Transformer\Getters\IntegerGetter;
17
+
18
+ class HeaderAdRule extends ConfigurationSelectorRule
19
+ {
20
+ const PROPERTY_AD_URL = 'ad.url';
21
+ const PROPERTY_AD_HEIGHT_URL = 'ad.height';
22
+ const PROPERTY_AD_WIDTH_URL = 'ad.width';
23
+ const PROPERTY_AD_EMBED_URL = 'ad.embed';
24
+
25
+ public function getContextClass()
26
+ {
27
+ return Header::getClassName();
28
+ }
29
+
30
+ public static function create()
31
+ {
32
+ return new HeaderAdRule();
33
+ }
34
+
35
+ public static function createFrom($configuration)
36
+ {
37
+ $ad_rule = self::create();
38
+ $ad_rule->withSelector($configuration['selector']);
39
+
40
+ $ad_rule->withProperties(
41
+ array(
42
+ self::PROPERTY_AD_URL,
43
+ self::PROPERTY_AD_HEIGHT_URL,
44
+ self::PROPERTY_AD_WIDTH_URL,
45
+ self::PROPERTY_AD_EMBED_URL
46
+ ),
47
+ $configuration
48
+ );
49
+
50
+ return $ad_rule;
51
+ }
52
+
53
+ public function apply($transformer, $header, $node)
54
+ {
55
+ $ad = Ad::create();
56
+
57
+ // Builds the ad
58
+ $height = $this->getProperty(self::PROPERTY_AD_HEIGHT_URL, $node);
59
+ if ($height) {
60
+ $ad->withHeight($height);
61
+ }
62
+
63
+ $width = $this->getProperty(self::PROPERTY_AD_WIDTH_URL, $node);
64
+ if ($width) {
65
+ $ad->withWidth($width);
66
+ }
67
+
68
+ $url = $this->getProperty(self::PROPERTY_AD_URL, $node);
69
+ if ($url) {
70
+ $ad->withSource($url);
71
+ }
72
+
73
+ $embed_code = $this->getProperty(self::PROPERTY_AD_EMBED_URL, $node);
74
+ if ($embed_code) {
75
+ $ad->withHTML($embed_code);
76
+ }
77
+
78
+ if ($url || $embed_code) {
79
+ $header->addAd($ad);
80
+ }
81
+
82
+ return $header;
83
+ }
84
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/HeaderImageRule.php ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Caption;
13
+ use Facebook\InstantArticles\Elements\Header;
14
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
15
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
16
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
17
+ use Facebook\InstantArticles\Transformer\Warnings\InvalidSelector;
18
+
19
+ class HeaderImageRule extends ConfigurationSelectorRule
20
+ {
21
+ const PROPERTY_IMAGE_URL = 'image.url';
22
+
23
+ public function __construct()
24
+ {
25
+ }
26
+
27
+ public function getContextClass()
28
+ {
29
+ return Header::getClassName();
30
+ }
31
+
32
+ public static function create()
33
+ {
34
+ return new HeaderImageRule();
35
+ }
36
+
37
+ public static function createFrom($configuration)
38
+ {
39
+ $image_rule = self::create();
40
+ $image_rule->withSelector($configuration['selector']);
41
+
42
+ $image_rule->withProperties(
43
+ array(
44
+ self::PROPERTY_IMAGE_URL
45
+ ),
46
+ $configuration
47
+ );
48
+
49
+ return $image_rule;
50
+ }
51
+
52
+ public function apply($transformer, $header, $node)
53
+ {
54
+ $image = Image::create();
55
+
56
+ // Builds the image
57
+ $url = $this->getProperty(self::PROPERTY_IMAGE_URL, $node);
58
+ if ($url) {
59
+ $image->withURL($url);
60
+ $header->withCover($image);
61
+ } else {
62
+ $transformer->addWarning(
63
+ new InvalidSelector(
64
+ self::PROPERTY_IMAGE_URL,
65
+ $header,
66
+ $node,
67
+ $this
68
+ )
69
+ );
70
+ }
71
+
72
+ $suppress_warnings = $transformer->suppress_warnings;
73
+ $transformer->suppress_warnings = true;
74
+ $transformer->transform($image, $node);
75
+ $transformer->suppress_warnings = $suppress_warnings;
76
+
77
+ return $header;
78
+ }
79
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/HeaderKickerRule.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Transformer\Getters\GetterFactory;
13
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
14
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
15
+
16
+ class HeaderKickerRule extends ConfigurationSelectorRule
17
+ {
18
+ public function getContextClass()
19
+ {
20
+ return Header::getClassName();
21
+ }
22
+
23
+ public static function create()
24
+ {
25
+ return new HeaderKickerRule();
26
+ }
27
+
28
+ public static function createFrom($configuration)
29
+ {
30
+ return self::create()->withSelector($configuration['selector']);
31
+ }
32
+
33
+ public function apply($transformer, $header, $h3)
34
+ {
35
+ $header->withKicker($h3->textContent);
36
+ return $header;
37
+ }
38
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/HeaderRule.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Image;
13
+ use Facebook\InstantArticles\Elements\Caption;
14
+ use Facebook\InstantArticles\Elements\InstantArticle;
15
+ use Facebook\InstantArticles\Validators\Type;
16
+ use Facebook\InstantArticles\Transformer\Transformer;
17
+
18
+ class HeaderRule extends ConfigurationSelectorRule
19
+ {
20
+ public function getContextClass()
21
+ {
22
+ return InstantArticle::getClassName();
23
+ }
24
+
25
+ public static function create()
26
+ {
27
+ return new HeaderRule();
28
+ }
29
+
30
+ public static function createFrom($configuration)
31
+ {
32
+ $header_rule = self::create();
33
+ $header_rule->withSelector($configuration['selector']);
34
+ return $header_rule;
35
+ }
36
+
37
+ public function apply($transformer, $instant_article, $node)
38
+ {
39
+ $header = Header::create();
40
+ $instant_article->withHeader($header);
41
+ $transformer->transform($header, $node);
42
+
43
+ return $instant_article;
44
+ }
45
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/HeaderSubTitleRule.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Transformer\Getters\GetterFactory;
13
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
14
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
15
+
16
+ class HeaderSubTitleRule extends ConfigurationSelectorRule
17
+ {
18
+ public function __construct()
19
+ {
20
+ }
21
+
22
+ public function getContextClass()
23
+ {
24
+ return Header::getClassName();
25
+ }
26
+
27
+ public static function create()
28
+ {
29
+ return new HeaderSubTitleRule();
30
+ }
31
+
32
+ public static function createFrom($configuration)
33
+ {
34
+ return self::create()->withSelector($configuration['selector']);
35
+ }
36
+
37
+ public function apply($transformer, $header, $h2)
38
+ {
39
+ $header->withSubTitle($h2->textContent);
40
+ return $header;
41
+ }
42
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/HeaderTitleRule.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Transformer\Getters\GetterFactory;
13
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
14
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
15
+
16
+ class HeaderTitleRule extends ConfigurationSelectorRule
17
+ {
18
+ public function getContextClass()
19
+ {
20
+ return Header::getClassName();
21
+ }
22
+
23
+ public static function create()
24
+ {
25
+ return new HeaderTitleRule();
26
+ }
27
+
28
+ public static function createFrom($configuration)
29
+ {
30
+ return self::create()->withSelector($configuration['selector']);
31
+ }
32
+
33
+ public function apply($transformer, $header, $h1)
34
+ {
35
+ $header->withTitle($h1->textContent);
36
+ return $header;
37
+ }
38
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/IgnoreRule.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Element;
12
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
13
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
14
+ use Facebook\InstantArticles\Transformer\Getters\ElementGetter;
15
+
16
+ class IgnoreRule extends ConfigurationSelectorRule
17
+ {
18
+ public function __construct()
19
+ {
20
+ }
21
+
22
+ public static function create()
23
+ {
24
+ return new IgnoreRule();
25
+ }
26
+
27
+ public static function createFrom($configuration)
28
+ {
29
+ return self::create()->withSelector($configuration['selector']);
30
+ }
31
+
32
+ public function getContextClass()
33
+ {
34
+ return $this->contextClass = Element::getClassName();
35
+ }
36
+
37
+ public function apply($transformer, $context, $element)
38
+ {
39
+ return $context;
40
+ }
41
+
42
+ public function loadFrom($configuration)
43
+ {
44
+ $this->selector = $configuration['selector'];
45
+ }
46
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/ImageRule.php ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Caption;
13
+ use Facebook\InstantArticles\Elements\InstantArticle;
14
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
15
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
16
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
17
+ use Facebook\InstantArticles\Transformer\Warnings\InvalidSelector;
18
+
19
+ class ImageRule extends ConfigurationSelectorRule
20
+ {
21
+ const PROPERTY_IMAGE_URL = 'image.url';
22
+ const PROPERTY_LIKE = 'image.like';
23
+ const PROPERTY_COMMENTS = 'image.comments';
24
+
25
+ public function __construct()
26
+ {
27
+ }
28
+
29
+ public function getContextClass()
30
+ {
31
+ return InstantArticle::getClassName();
32
+ }
33
+
34
+ public static function create()
35
+ {
36
+ return new ImageRule();
37
+ }
38
+
39
+ public static function createFrom($configuration)
40
+ {
41
+ $image_rule = self::create();
42
+ $image_rule->withSelector($configuration['selector']);
43
+
44
+ $image_rule->withProperties(
45
+ array(
46
+ self::PROPERTY_IMAGE_URL,
47
+ self::PROPERTY_LIKE,
48
+ self::PROPERTY_COMMENTS
49
+ ),
50
+ $configuration
51
+ );
52
+
53
+ return $image_rule;
54
+ }
55
+
56
+ public function apply($transformer, $instant_article, $node)
57
+ {
58
+ $image = Image::create();
59
+
60
+ // Builds the image
61
+ $url = $this->getProperty(self::PROPERTY_IMAGE_URL, $node);
62
+ if ($url) {
63
+ $image->withURL($url);
64
+ $instant_article->addChild($image);
65
+ } else {
66
+ $transformer->addWarning(
67
+ new InvalidSelector(
68
+ self::PROPERTY_IMAGE_URL,
69
+ $instant_article,
70
+ $node,
71
+ $this
72
+ )
73
+ );
74
+ }
75
+
76
+ if ($this->getProperty(self::PROPERTY_LIKE, $node)) {
77
+ $image->enableLike();
78
+ }
79
+
80
+ if ($this->getProperty(self::PROPERTY_COMMENTS, $node)) {
81
+ $image->enableComments();
82
+ }
83
+
84
+ $suppress_warnings = $transformer->suppress_warnings;
85
+ $transformer->suppress_warnings = true;
86
+ $transformer->transform($image, $node);
87
+ $transformer->suppress_warnings = $suppress_warnings;
88
+
89
+ return $instant_article;
90
+ }
91
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/InstantArticleRule.php ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Caption;
13
+ use Facebook\InstantArticles\Elements\InstantArticle;
14
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
15
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
16
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
17
+ use Facebook\InstantArticles\Transformer\Warnings\InvalidSelector;
18
+
19
+ class InstantArticleRule extends ConfigurationSelectorRule
20
+ {
21
+ const PROPERTY_CANONICAL = 'article.canonical';
22
+ const PROPERTY_CHARSET = 'article.charset';
23
+ const PROPERTY_MARKUP_VERSION = 'article.markup.version';
24
+ const PROPERTY_AUTO_AD_PLACEMENT = 'article.auto.ad';
25
+
26
+ public function __construct()
27
+ {
28
+ }
29
+
30
+ public function getContextClass()
31
+ {
32
+ return InstantArticle::getClassName();
33
+ }
34
+
35
+ public static function create()
36
+ {
37
+ return new InstantArticleRule();
38
+ }
39
+
40
+ public static function createFrom($configuration)
41
+ {
42
+ $canonical_rule = self::create();
43
+ $canonical_rule->withSelector($configuration['selector']);
44
+
45
+ $canonical_rule->withProperties(
46
+ array(
47
+ self::PROPERTY_CANONICAL,
48
+ self::PROPERTY_CHARSET,
49
+ self::PROPERTY_MARKUP_VERSION,
50
+ self::PROPERTY_AUTO_AD_PLACEMENT
51
+ ),
52
+ $configuration
53
+ );
54
+
55
+ return $canonical_rule;
56
+
57
+ }
58
+
59
+ public function apply($transformer, $instant_article, $node)
60
+ {
61
+ // Builds the image
62
+ $url = $this->getProperty(self::PROPERTY_CANONICAL, $node);
63
+ if ($url) {
64
+ $instant_article->withCanonicalURL($url);
65
+ } else {
66
+ $transformer->addWarning(
67
+ new InvalidSelector(
68
+ self::PROPERTY_CANONICAL,
69
+ $instant_article,
70
+ $node,
71
+ $this
72
+ )
73
+ );
74
+ }
75
+
76
+ $charset = $this->getProperty(self::PROPERTY_CHARSET, $node);
77
+ if ($charset) {
78
+ $instant_article->withCharset($charset);
79
+ }
80
+
81
+ $markup_version = $this->getProperty(self::PROPERTY_MARKUP_VERSION, $node);
82
+ if ($markup_version) {
83
+ //TODO Validate if the markup is valid with this code
84
+ }
85
+
86
+ $auto_ad_placement = $this->getProperty(self::PROPERTY_AUTO_AD_PLACEMENT, $node);
87
+ if ($auto_ad_placement === 'false') {
88
+ $instant_article->disableAutomaticAdPlacement();
89
+ }
90
+
91
+ return $instant_article;
92
+ }
93
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/InteractiveRule.php ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Interactive;
12
+ use Facebook\InstantArticles\Elements\Caption;
13
+ use Facebook\InstantArticles\Elements\InstantArticle;
14
+ use Facebook\InstantArticles\Transformer\Warnings\InvalidSelector;
15
+
16
+ class InteractiveRule extends ConfigurationSelectorRule
17
+ {
18
+ const PROPERTY_IFRAME = 'interactive.iframe';
19
+ const PROPERTY_URL = 'interactive.url';
20
+ const PROPERTY_WIDTH_NO_MARGIN = Interactive::NO_MARGIN;
21
+ const PROPERTY_WIDTH_COLUMN_WIDTH = Interactive::COLUMN_WIDTH;
22
+ const PROPERTY_HEIGHT = 'interactive.height';
23
+
24
+ public function getContextClass()
25
+ {
26
+ return InstantArticle::getClassName();
27
+ }
28
+
29
+ public static function create()
30
+ {
31
+ return new InteractiveRule();
32
+ }
33
+
34
+ public static function createFrom($configuration)
35
+ {
36
+ $interactive_rule = self::create();
37
+ $interactive_rule->withSelector($configuration['selector']);
38
+
39
+ $interactive_rule->withProperties(
40
+ array(
41
+ self::PROPERTY_IFRAME,
42
+ self::PROPERTY_URL,
43
+ self::PROPERTY_WIDTH_NO_MARGIN,
44
+ self::PROPERTY_WIDTH_COLUMN_WIDTH,
45
+ self::PROPERTY_HEIGHT
46
+ ),
47
+ $configuration
48
+ );
49
+
50
+ return $interactive_rule;
51
+ }
52
+
53
+ public function apply($transformer, $instant_article, $node)
54
+ {
55
+ $interactive = Interactive::create();
56
+
57
+ // Builds the image
58
+ $iframe = $this->getProperty(self::PROPERTY_IFRAME, $node);
59
+ $url = $this->getProperty(self::PROPERTY_URL, $node);
60
+ if ($iframe) {
61
+ $interactive->withHTML($iframe);
62
+ }
63
+ if ($url) {
64
+ $interactive->withSource($url);
65
+ }
66
+ if ($iframe || $url) {
67
+ $instant_article->addChild($interactive);
68
+ } else {
69
+ $transformer->addWarning(
70
+ new InvalidSelector(
71
+ self::PROPERTY_IFRAME,
72
+ $instant_article,
73
+ $node,
74
+ $this
75
+ )
76
+ );
77
+ }
78
+
79
+ if ($this->getProperty(self::PROPERTY_WIDTH_COLUMN_WIDTH, $node)) {
80
+ $interactive->withWidth(Interactive::COLUMN_WIDTH);
81
+ } else {
82
+ $interactive->withWidth(Interactive::NO_MARGIN);
83
+ }
84
+
85
+ $height = $this->getProperty(self::PROPERTY_HEIGHT, $node);
86
+ if ($height) {
87
+ $interactive->withHeight($height);
88
+ }
89
+
90
+ $suppress_warnings = $transformer->suppress_warnings;
91
+ $transformer->suppress_warnings = true;
92
+ $transformer->transform($interactive, $node);
93
+ $transformer->suppress_warnings = $suppress_warnings;
94
+
95
+ return $instant_article;
96
+ }
97
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/ItalicRule.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\TextContainer;
12
+ use Facebook\InstantArticles\Elements\Italic;
13
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
14
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
15
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
16
+
17
+ class ItalicRule extends ConfigurationSelectorRule
18
+ {
19
+ public function __construct()
20
+ {
21
+ }
22
+
23
+ public static function create()
24
+ {
25
+ return new ItalicRule();
26
+ }
27
+
28
+ public static function createFrom($configuration)
29
+ {
30
+ return self::create()->withSelector($configuration['selector']);
31
+ }
32
+
33
+ public function getContextClass()
34
+ {
35
+ return $this->contextClass = TextContainer::getClassName();
36
+ }
37
+
38
+ public function apply($transformer, $text_container, $element)
39
+ {
40
+ $bold = Italic::create();
41
+ $text_container->appendText($bold);
42
+ $transformer->transform($bold, $element);
43
+ return $text_container;
44
+ }
45
+
46
+ public function loadFrom($configuration)
47
+ {
48
+ $this->selector = $configuration['selector'];
49
+ }
50
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/LineBreakRule.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\TextContainer;
12
+ use Facebook\InstantArticles\Elements\LineBreak;
13
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
14
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
15
+ use Facebook\InstantArticles\Transformer\Getters\ElementGetter;
16
+
17
+ class LineBreakRule extends ConfigurationSelectorRule
18
+ {
19
+ public function __construct()
20
+ {
21
+ }
22
+
23
+ public function getContextClass()
24
+ {
25
+ return $this->contextClass = TextContainer::getClassName();
26
+ }
27
+
28
+ public static function create()
29
+ {
30
+ return new LineBreakRule();
31
+ }
32
+
33
+ public static function createFrom($configuration)
34
+ {
35
+ return self::create()->withSelector($configuration['selector']);
36
+ }
37
+
38
+ public function apply($transformer, $text_container, $element)
39
+ {
40
+ $line_break = LineBreak::create();
41
+ $text_container->appendText($line_break);
42
+ return $text_container;
43
+ }
44
+
45
+ public function loadFrom($configuration)
46
+ {
47
+ $this->selector = $configuration['selector'];
48
+ }
49
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/ListElementRule.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\InstantArticle;
12
+ use Facebook\InstantArticles\Elements\ListElement;
13
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
14
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
15
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
16
+
17
+ class ListElementRule extends ConfigurationSelectorRule
18
+ {
19
+ public function __construct()
20
+ {
21
+ }
22
+
23
+ public function getContextClass()
24
+ {
25
+ return InstantArticle::getClassName();
26
+ }
27
+
28
+ public static function create()
29
+ {
30
+ return new ListElementRule();
31
+ }
32
+
33
+ public static function createFrom($configuration)
34
+ {
35
+ return self::create()->withSelector($configuration['selector']);
36
+ }
37
+
38
+ public function apply($transformer, $instant_article, $element)
39
+ {
40
+ $list =
41
+ $element->nodeName === 'ol' ?
42
+ ListElement::createOrdered() :
43
+ ListElement::createUnordered();
44
+ $instant_article->addChild($list);
45
+ $transformer->transform($list, $element);
46
+ return $instant_article;
47
+ }
48
+
49
+ public function loadFrom($configuration)
50
+ {
51
+ $this->selector = $configuration['selector'];
52
+ }
53
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/ListItemRule.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\ListElement;
12
+ use Facebook\InstantArticles\Elements\ListItem;
13
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
14
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
15
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
16
+
17
+ class ListItemRule extends ConfigurationSelectorRule
18
+ {
19
+ public function __construct()
20
+ {
21
+ }
22
+
23
+ public function getContextClass()
24
+ {
25
+ return ListElement::getClassName();
26
+ }
27
+
28
+ public static function create()
29
+ {
30
+ return new ListItemRule();
31
+ }
32
+
33
+ public static function createFrom($configuration)
34
+ {
35
+ return self::create()->withSelector($configuration['selector']);
36
+ }
37
+
38
+ public function apply($transformer, $list, $element)
39
+ {
40
+ $li = ListItem::create();
41
+ $list->addItem($li);
42
+ $transformer->transform($li, $element);
43
+
44
+ return $list;
45
+ }
46
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/MapRule.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Map;
12
+ use Facebook\InstantArticles\Elements\Caption;
13
+ use Facebook\InstantArticles\Elements\InstantArticle;
14
+
15
+ class MapRule extends ConfigurationSelectorRule
16
+ {
17
+ public function getContextClass()
18
+ {
19
+ return InstantArticle::getClassName();
20
+ }
21
+
22
+ public static function create()
23
+ {
24
+ return new MapRule();
25
+ }
26
+
27
+ public static function createFrom($configuration)
28
+ {
29
+ $map_rule = self::create();
30
+ $map_rule->withSelector($configuration['selector']);
31
+ return $map_rule;
32
+ }
33
+
34
+ public function apply($transformer, $instant_article, $node)
35
+ {
36
+ $map = Map::create();
37
+ $instant_article->addChild($map);
38
+ $transformer->transform($map, $node);
39
+
40
+ return $instant_article;
41
+ }
42
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/ParagraphFooterRule.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Paragraph;
12
+ use Facebook\InstantArticles\Elements\Footer;
13
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
14
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
15
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
16
+
17
+ class ParagraphFooterRule extends ConfigurationSelectorRule
18
+ {
19
+ public function __construct()
20
+ {
21
+ }
22
+
23
+ public function getContextClass()
24
+ {
25
+ return Footer::getClassName();
26
+ }
27
+
28
+ public static function create()
29
+ {
30
+ return new ParagraphFooterRule();
31
+ }
32
+
33
+ public static function createFrom($configuration)
34
+ {
35
+ return self::create()->withSelector($configuration['selector']);
36
+ }
37
+
38
+ public function apply($transformer, $footer, $element)
39
+ {
40
+ $p = Paragraph::create();
41
+ $footer->addCredit($p);
42
+ $transformer->transform($p, $element);
43
+ return $footer;
44
+ }
45
+
46
+ public function loadFrom($configuration)
47
+ {
48
+ $this->selector = $configuration['selector'];
49
+ }
50
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/ParagraphRule.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\InstantArticle;
12
+ use Facebook\InstantArticles\Elements\Paragraph;
13
+ use Facebook\InstantArticles\Elements\ListItem;
14
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
15
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
16
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
17
+ use Facebook\InstantArticles\Validators\Type;
18
+
19
+ class ParagraphRule extends ConfigurationSelectorRule
20
+ {
21
+ public function __construct()
22
+ {
23
+ }
24
+
25
+ public function getContextClass()
26
+ {
27
+ return InstantArticle::getClassName();
28
+ }
29
+
30
+ public static function create()
31
+ {
32
+ return new ParagraphRule();
33
+ }
34
+
35
+ public static function createFrom($configuration)
36
+ {
37
+ return self::create()->withSelector($configuration['selector']);
38
+ }
39
+
40
+ public function apply($transformer, $context_element, $element)
41
+ {
42
+ $p = Paragraph::create();
43
+ $context_element->addChild($p);
44
+ $transformer->transform($p, $element);
45
+
46
+ return $context_element;
47
+ }
48
+
49
+ public function loadFrom($configuration)
50
+ {
51
+ $this->selector = $configuration['selector'];
52
+ }
53
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/PassThroughRule.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Element;
12
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
13
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
14
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
15
+
16
+ class PassThroughRule extends ConfigurationSelectorRule
17
+ {
18
+ public function __construct()
19
+ {
20
+ }
21
+
22
+ public function getContextClass()
23
+ {
24
+ return Element::getClassName();
25
+ }
26
+
27
+ public static function create()
28
+ {
29
+ return new PassThroughRule();
30
+ }
31
+
32
+ public static function createFrom($configuration)
33
+ {
34
+ return self::create()->withSelector($configuration['selector']);
35
+ }
36
+
37
+ public function apply($transformer, $context, $node)
38
+ {
39
+ $transformer->transform($context, $node);
40
+ return $context;
41
+ }
42
+
43
+ public function loadFrom($configuration)
44
+ {
45
+ $this->selector = $configuration['selector'];
46
+ }
47
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/PullquoteCiteRule.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Cite;
12
+ use Facebook\InstantArticles\Elements\Pullquote;
13
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
14
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
15
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
16
+
17
+ class PullquoteCiteRule extends ConfigurationSelectorRule
18
+ {
19
+ public function getContextClass()
20
+ {
21
+ return Pullquote::getClassName();
22
+ }
23
+
24
+ public static function create()
25
+ {
26
+ return new PullquoteCiteRule();
27
+ }
28
+
29
+ public static function createFrom($configuration)
30
+ {
31
+ $cite_rule = self::create();
32
+ $cite_rule->withSelector($configuration['selector']);
33
+
34
+ return $cite_rule;
35
+ }
36
+
37
+ public function apply($transformer, $pullquote, $node)
38
+ {
39
+ $cite = Cite::create();
40
+ $pullquote->withAttribution($cite);
41
+ $transformer->transform($cite, $node);
42
+
43
+ return $pullquote;
44
+ }
45
+
46
+ public function loadFrom($configuration)
47
+ {
48
+ $this->selector = $configuration['selector'];
49
+ }
50
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/PullquoteRule.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\InstantArticle;
12
+ use Facebook\InstantArticles\Elements\Pullquote;
13
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
14
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
15
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
16
+
17
+ class PullquoteRule extends ConfigurationSelectorRule
18
+ {
19
+ public function __construct()
20
+ {
21
+ }
22
+
23
+ public function getContextClass()
24
+ {
25
+ return InstantArticle::getClassName();
26
+ }
27
+
28
+ public static function create()
29
+ {
30
+ return new PullquoteRule();
31
+ }
32
+
33
+ public static function createFrom($configuration)
34
+ {
35
+ return self::create()->withSelector($configuration['selector']);
36
+ }
37
+
38
+ public function apply($transformer, $instant_article, $element)
39
+ {
40
+ $pullquote = Pullquote::create();
41
+ $instant_article->addChild($pullquote);
42
+ $transformer->transform($pullquote, $element);
43
+ return $instant_article;
44
+ }
45
+
46
+ public function loadFrom($configuration)
47
+ {
48
+ $this->selector = $configuration['selector'];
49
+ }
50
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/RelatedArticlesRule.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\Transformer\Rules;
10
+
11
+ use Facebook\InstantArticles\Elements\RelatedArticles;
12
+ use Facebook\InstantArticles\Elements\InstantArticle;
13
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
14
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
15
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
16
+
17
+ class RelatedArticlesRule extends ConfigurationSelectorRule
18
+ {
19
+ const PROPERTY_TITLE = 'related.title';
20
+
21
+ public function __construct()
22
+ {
23
+ }
24
+
25
+ public function getContextClass()
26
+ {
27
+ return InstantArticle::getClassName();
28
+ }
29
+
30
+ public static function create()
31
+ {
32
+ return new RelatedArticlesRule();
33
+ }
34
+
35
+ public static function createFrom($configuration)
36
+ {
37
+ $related_articles_rule = self::create();
38
+ $related_articles_rule->withSelector($configuration['selector']);
39
+
40
+ $related_articles_rule->withProperty(
41
+ self::PROPERTY_TITLE,
42
+ self::retrieveProperty($configuration, self::PROPERTY_TITLE)
43
+ );
44
+
45
+ return $related_articles_rule;
46
+ }
47
+
48
+ public function apply($transformer, $instant_article, $node)
49
+ {
50
+ $related_articles = RelatedArticles::create();
51
+
52
+ // Builds the image
53
+ $title = $this->getProperty(self::PROPERTY_TITLE, $node);
54
+ if ($title) {
55
+ $related_articles->withTitle($title);
56
+ $instant_article->addChild($related_articles);
57
+ }
58
+
59
+ $transformer->transform($related_articles, $node);
60
+
61
+ return $instant_article;
62
+ }
63
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/RelatedItemRule.php ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\RelatedItem;
12
+ use Facebook\InstantArticles\Elements\RelatedArticles;
13
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
14
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
15
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
16
+ use Facebook\InstantArticles\Transformer\Warnings\InvalidSelector;
17
+
18
+ class RelatedItemRule extends ConfigurationSelectorRule
19
+ {
20
+ const PROPERTY_SPONSORED = 'related.sponsored';
21
+ const PROPERTY_URL = 'related.url';
22
+
23
+ public function __construct()
24
+ {
25
+ }
26
+
27
+ public function getContextClass()
28
+ {
29
+ return RelatedArticles::getClassName();
30
+ }
31
+
32
+ public static function create()
33
+ {
34
+ return new RelatedItemRule();
35
+ }
36
+
37
+ public static function createFrom($configuration)
38
+ {
39
+ $related_item_rule = self::create();
40
+ $related_item_rule->withSelector($configuration['selector']);
41
+
42
+ $related_item_rule->withProperties(
43
+ array(
44
+ self::PROPERTY_SPONSORED,
45
+ self::PROPERTY_URL
46
+ ),
47
+ $configuration
48
+ );
49
+
50
+ return $related_item_rule;
51
+ }
52
+
53
+ public function apply($transformer, $related_articles, $node)
54
+ {
55
+ $related_item = RelatedItem::create();
56
+ $related_articles->addRelated($related_item);
57
+
58
+ $url = $this->getProperty(self::PROPERTY_URL, $node);
59
+ if ($url) {
60
+ $related_item->withURL($url);
61
+ } else {
62
+ $transformer->addWarning(
63
+ new InvalidSelector(
64
+ self::PROPERTY_URL,
65
+ $related_articles,
66
+ $node,
67
+ $this
68
+ )
69
+ );
70
+ }
71
+
72
+ if ($this->getProperty(self::PROPERTY_SPONSORED, $node)) {
73
+ $related_item->enableSponsored();
74
+ }
75
+
76
+ return $related_articles;
77
+ }
78
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/Rule.php ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ abstract class Rule
12
+ {
13
+ public function matches($context, $node)
14
+ {
15
+ $log = \Logger::getLogger('facebook-instantarticles-transformer');
16
+
17
+ $matches_context = $this->matchesContext($context);
18
+ $matches_node = $this->matchesNode($node);
19
+ if ($matches_context && $matches_node) {
20
+ $log->debug('context class: '.get_class($context));
21
+ $log->debug('context matches: '.($matches_context ? 'MATCHES' : 'no match'));
22
+ $log->debug('node name: <'.$node->nodeName.' />');
23
+ $log->debug('node matches: '.($matches_node ? 'MATCHES' : 'no match'));
24
+ $log->debug('rule: '.get_class($this));
25
+ $log->debug('-------');
26
+ return true;
27
+ }
28
+ if ($node->nodeName === 'img') {
29
+ $log->debug('context class: '.get_class($context));
30
+ $log->debug('context matches: '.($matches_context ? 'MATCHES' : 'no match'));
31
+ $log->debug('node name: <'.$node->nodeName.' />');
32
+ $log->debug('node: '.$node->ownerDocument->saveXML($node).' />');
33
+ $log->debug('node matches: '.($matches_node ? 'MATCHES' : 'no match'));
34
+ $log->debug('rule: '.get_class($this));
35
+ $log->debug('-------');
36
+ }
37
+ return false;
38
+ }
39
+
40
+ abstract public function matchesContext($context);
41
+
42
+ abstract public function matchesNode($node);
43
+
44
+ abstract public function apply($transformer, $container, $node);
45
+
46
+ abstract public function getContextClass();
47
+
48
+ public static function create()
49
+ {
50
+ throw new Exception(
51
+ 'All Rule class extension should implement the '.
52
+ 'Rule::create() method'
53
+ );
54
+ }
55
+
56
+ public static function createFrom($configuration)
57
+ {
58
+ throw new Exception(
59
+ 'All Rule class extension should implement the '.
60
+ 'Rule::createFrom($configuration) method'
61
+ );
62
+ }
63
+
64
+ public static function retrieveProperty($array, $property_name)
65
+ {
66
+ if (isset($array[$property_name])) {
67
+ return $array[$property_name];
68
+ } elseif (isset($array['properties']) && isset($array['properties'][$property_name])) {
69
+ return $array['properties'][$property_name];
70
+ }
71
+ }
72
+
73
+ /**
74
+ * Auxiliary method to extract full qualified class name.
75
+ * @return string The full qualified name of class
76
+ */
77
+ public static function getClassName() {
78
+ return get_called_class();
79
+ }
80
+
81
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/SlideshowImageRule.php ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Caption;
13
+ use Facebook\InstantArticles\Elements\Slideshow;
14
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
15
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
16
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
17
+ use Facebook\InstantArticles\Transformer\Warnings\InvalidSelector;
18
+
19
+ class SlideshowImageRule extends ConfigurationSelectorRule
20
+ {
21
+ const PROPERTY_IMAGE_URL = 'image.url';
22
+ const PROPERTY_CAPTION_TITLE = 'caption.title';
23
+ const PROPERTY_CAPTION_CREDIT = 'caption.credit';
24
+
25
+ public function __construct()
26
+ {
27
+ }
28
+
29
+ public function getContextClass()
30
+ {
31
+ return Slideshow::getClassName();
32
+ }
33
+
34
+ public static function create()
35
+ {
36
+ return new SlideshowImageRule();
37
+ }
38
+
39
+ public static function createFrom($configuration)
40
+ {
41
+ $image_rule = self::create();
42
+ $image_rule->withSelector($configuration['selector']);
43
+
44
+ $image_rule->withProperties(
45
+ array(
46
+ self::PROPERTY_IMAGE_URL,
47
+ self::PROPERTY_CAPTION_TITLE,
48
+ self::PROPERTY_CAPTION_CREDIT
49
+ ),
50
+ $configuration
51
+ );
52
+
53
+ return $image_rule;
54
+ }
55
+
56
+ public function apply($transformer, $slideshow, $node)
57
+ {
58
+ $image = Image::create();
59
+
60
+ // Builds the image
61
+ $url = $this->getProperty(self::PROPERTY_IMAGE_URL, $node);
62
+ if ($url) {
63
+ $image->withURL($url);
64
+ $slideshow->addImage($image);
65
+ } else {
66
+ $transformer->addWarning(
67
+ new InvalidSelector(
68
+ self::PROPERTY_IMAGE_URL,
69
+ $slideshow,
70
+ $node,
71
+ $this
72
+ )
73
+ );
74
+ }
75
+
76
+ $caption = Caption::create();
77
+
78
+ $caption_title = $this->getProperty(self::PROPERTY_CAPTION_TITLE, $node);
79
+ if ($caption_title) {
80
+ $caption->withTitle($caption_title);
81
+ $image->withCaption($caption);
82
+ }
83
+
84
+ $caption_credit = $this->getProperty(self::PROPERTY_CAPTION_CREDIT, $node);
85
+ if ($caption_credit) {
86
+ $caption->withCredit($caption_credit);
87
+ }
88
+
89
+ return $slideshow;
90
+ }
91
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/SlideshowRule.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\InstantArticle;
12
+ use Facebook\InstantArticles\Elements\Slideshow;
13
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
14
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
15
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
16
+
17
+ class SlideshowRule extends ConfigurationSelectorRule
18
+ {
19
+ public function getContextClass()
20
+ {
21
+ return InstantArticle::getClassName();
22
+ }
23
+
24
+ public static function create()
25
+ {
26
+ return new SlideshowRule();
27
+ }
28
+
29
+ public static function createFrom($configuration)
30
+ {
31
+ $slideshow_rule = self::create();
32
+ $slideshow_rule->withSelector($configuration['selector']);
33
+
34
+ return $slideshow_rule;
35
+ }
36
+
37
+ public function apply($transformer, $instant_article, $node)
38
+ {
39
+ // Builds the slideshow
40
+ $slideshow = Slideshow::create();
41
+ $instant_article->addChild($slideshow);
42
+
43
+ $transformer->transform($slideshow, $node);
44
+
45
+ return $instant_article;
46
+ }
47
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/SocialEmbedRule.php ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\SocialEmbed;
12
+ use Facebook\InstantArticles\Elements\Caption;
13
+ use Facebook\InstantArticles\Elements\InstantArticle;
14
+ use Facebook\InstantArticles\Transformer\Warnings\InvalidSelector;
15
+
16
+ class SocialEmbedRule extends ConfigurationSelectorRule
17
+ {
18
+ const PROPERTY_IFRAME = 'socialembed.iframe';
19
+ const PROPERTY_URL = 'socialembed.url';
20
+
21
+ public function getContextClass()
22
+ {
23
+ return InstantArticle::getClassName();
24
+ }
25
+
26
+ public static function create()
27
+ {
28
+ return new SocialEmbedRule();
29
+ }
30
+
31
+ public static function createFrom($configuration)
32
+ {
33
+ $social_embed_rule = self::create();
34
+ $social_embed_rule->withSelector($configuration['selector']);
35
+
36
+ $social_embed_rule->withProperties(
37
+ array(
38
+ self::PROPERTY_IFRAME,
39
+ self::PROPERTY_URL
40
+ ),
41
+ $configuration
42
+ );
43
+
44
+ return $social_embed_rule;
45
+ }
46
+
47
+ public function apply($transformer, $instant_article, $node)
48
+ {
49
+ $social_embed = SocialEmbed::create();
50
+
51
+ // Builds the image
52
+ $iframe = $this->getProperty(self::PROPERTY_IFRAME, $node);
53
+ $url = $this->getProperty(self::PROPERTY_URL, $node);
54
+ if ($iframe) {
55
+ $social_embed->withHTML($iframe);
56
+ }
57
+ if ($url) {
58
+ $social_embed->withSource($url);
59
+ }
60
+ if ($iframe || $url) {
61
+ $instant_article->addChild($social_embed);
62
+ } else {
63
+ $transformer->addWarning(
64
+ new InvalidSelector(
65
+ 'iframe and/or url',
66
+ $instant_article,
67
+ $node,
68
+ $this
69
+ )
70
+ );
71
+ }
72
+
73
+ $suppress_warnings = $transformer->suppress_warnings;
74
+ $transformer->suppress_warnings = true;
75
+ $transformer->transform($social_embed, $node);
76
+ $transformer->suppress_warnings = $suppress_warnings;
77
+
78
+ return $instant_article;
79
+ }
80
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/TextNodeRule.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\Transformer\Rules;
10
+
11
+ use Facebook\InstantArticles\Elements\TextContainer;
12
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
13
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
14
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
15
+
16
+ class TextNodeRule extends Rule
17
+ {
18
+ public function __construct()
19
+ {
20
+ }
21
+
22
+ public function getContextClass()
23
+ {
24
+ return TextContainer::getClassName();
25
+ }
26
+
27
+ public static function create()
28
+ {
29
+ return new TextNodeRule();
30
+ }
31
+
32
+ public static function createFrom($configuration)
33
+ {
34
+ return self::create();
35
+ }
36
+
37
+ public function matchesContext($context)
38
+ {
39
+ if (is_a($context, $this->getContextClass())) {
40
+ return true;
41
+ }
42
+ return false;
43
+ }
44
+
45
+ public function matchesNode($node)
46
+ {
47
+ if ($node->nodeName === '#text') {
48
+ return true;
49
+ }
50
+ return false;
51
+ }
52
+
53
+ public function apply($transformer, $text_container, $text)
54
+ {
55
+ $text_container->appendText($text->textContent);
56
+ return $text_container;
57
+ }
58
+
59
+ public function loadFrom($configuration)
60
+ {
61
+ // Nothing to load/configure
62
+ }
63
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/TimeRule.php ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Time;
12
+ use Facebook\InstantArticles\Elements\Header;
13
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
14
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
15
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
16
+ use Facebook\InstantArticles\Transformer\Warnings\InvalidSelector;
17
+
18
+ class TimeRule extends ConfigurationSelectorRule
19
+ {
20
+ const PROPERTY_TIME_TYPE = 'article.time_type';
21
+ const PROPERTY_TIME = 'article.time';
22
+
23
+ private $type = Time::PUBLISHED;
24
+
25
+ public function __construct()
26
+ {
27
+ }
28
+
29
+ public function getContextClass()
30
+ {
31
+ return Header::getClassName();
32
+ }
33
+
34
+ public static function create()
35
+ {
36
+ return new TimeRule();
37
+ }
38
+
39
+ public static function createFrom($configuration)
40
+ {
41
+ $time_rule = self::create();
42
+ $time_rule->withSelector($configuration['selector']);
43
+
44
+ $time_rule->withProperty(
45
+ self::PROPERTY_TIME,
46
+ self::retrieveProperty($configuration, self::PROPERTY_TIME)
47
+ );
48
+
49
+ if (isset($configuration[self::PROPERTY_TIME_TYPE])) {
50
+ $time_rule->type = $configuration[self::PROPERTY_TIME_TYPE];
51
+ }
52
+
53
+ return $time_rule;
54
+
55
+ }
56
+
57
+ public function apply($transformer, $header, $node)
58
+ {
59
+ // Builds the image
60
+ $time_string = $this->getProperty(self::PROPERTY_TIME, $node);
61
+ if ($time_string) {
62
+ $time = Time::create($this->type);
63
+ $time->withDatetime(new \DateTime($time_string));
64
+ $header->withTime($time);
65
+ } else {
66
+ $transformer->addWarning(
67
+ new InvalidSelector(
68
+ self::PROPERTY_TIME,
69
+ $header,
70
+ $node,
71
+ $this
72
+ )
73
+ );
74
+ }
75
+
76
+ return $header;
77
+ }
78
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/VideoRule.php ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Symfony\Component\CssSelector\CssSelectorConverter;
12
+
13
+ use Facebook\InstantArticles\Elements\Video;
14
+ use Facebook\InstantArticles\Elements\Caption;
15
+ use Facebook\InstantArticles\Elements\InstantArticle;
16
+ use Facebook\InstantArticles\Transformer\Getters\GetterFactory;
17
+ use Facebook\InstantArticles\Transformer\Getters\StringGetter;
18
+ use Facebook\InstantArticles\Transformer\Getters\ChildrenGetter;
19
+ use Facebook\InstantArticles\Transformer\Warnings\InvalidSelector;
20
+
21
+ class VideoRule extends ConfigurationSelectorRule
22
+ {
23
+ const PROPERTY_VIDEO_URL = 'video.url';
24
+ const PROPERTY_VIDEO_TYPE = 'video.type';
25
+ const PROPERTY_PLAYBACK_MODE = 'video.playback';
26
+ const PROPERTY_CONTROLS = 'video.controls';
27
+ const PROPERTY_LIKE = 'video.like';
28
+ const PROPERTY_COMMENTS = 'video.comments';
29
+
30
+
31
+ public function __construct()
32
+ {
33
+ }
34
+
35
+ public function getContextClass()
36
+ {
37
+ return InstantArticle::getClassName();
38
+ }
39
+
40
+ public static function create()
41
+ {
42
+ return new VideoRule();
43
+ }
44
+
45
+ public function withContainsChild($child_selector)
46
+ {
47
+ $this->childSelector = $child_selector;
48
+ return $this;
49
+ }
50
+
51
+ public function matchesNode($node)
52
+ {
53
+ $matches_node = parent::matchesNode($node);
54
+ if ($matches_node && $this->childSelector) {
55
+ $matches_node = false;
56
+ if ($node->hasChildNodes()) {
57
+ foreach ($node->childNodes as $child) {
58
+
59
+ $domXPath = new \DOMXPath($child->ownerDocument);
60
+ $converter = new CssSelectorConverter();
61
+ $xpath = $converter->toXPath($this->childSelector);
62
+ $results = $domXPath->query($xpath, $node);
63
+ foreach ($results as $result) {
64
+ if ($result === $child) {
65
+ $matches_node = true;
66
+ }
67
+ }
68
+
69
+ }
70
+ }
71
+ }
72
+
73
+ return $matches_node;
74
+ }
75
+
76
+ public static function createFrom($configuration)
77
+ {
78
+ $video_rule = self::create();
79
+ $video_rule->withSelector($configuration['selector']);
80
+
81
+ if (isset($configuration['containsChild'])) {
82
+ $video_rule->withContainsChild($configuration['containsChild']);
83
+ }
84
+
85
+ $video_rule->withProperties(
86
+ array(
87
+ self::PROPERTY_VIDEO_URL,
88
+ self::PROPERTY_VIDEO_TYPE,
89
+
90
+ Video::ASPECT_FIT,
91
+ Video::ASPECT_FIT_ONLY,
92
+ Video::FULLSCREEN,
93
+ Video::NON_INTERACTIVE,
94
+
95
+ self::PROPERTY_PLAYBACK_MODE,
96
+ self::PROPERTY_CONTROLS,
97
+
98
+ self::PROPERTY_LIKE,
99
+ self::PROPERTY_COMMENTS
100
+ ),
101
+ $configuration
102
+ );
103
+ return $video_rule;
104
+ }
105
+
106
+ public function apply($transformer, $instant_article, $node)
107
+ {
108
+ $video = Video::create();
109
+
110
+ // Builds the image
111
+ $url = $this->getProperty(self::PROPERTY_VIDEO_URL, $node);
112
+ if ($url) {
113
+ $video->withURL($url);
114
+ $instant_article->addChild($video);
115
+ } else {
116
+ $transformer->addWarning(
117
+ new InvalidSelector(
118
+ self::PROPERTY_VIDEO_URL,
119
+ $instant_article,
120
+ $node,
121
+ $this
122
+ )
123
+ );
124
+ }
125
+
126
+ $video_type = $this->getProperty(self::PROPERTY_VIDEO_TYPE, $node);
127
+ if ($video_type) {
128
+ $video->withContentType($video_type);
129
+ }
130
+
131
+ if ($this->getProperty(Video::ASPECT_FIT, $node)) {
132
+ $video->withPresentation(Video::ASPECT_FIT);
133
+ } elseif ($this->getProperty(Video::ASPECT_FIT_ONLY, $node)) {
134
+ $video->withPresentation(Video::ASPECT_FIT_ONLY);
135
+ } elseif ($this->getProperty(Video::FULLSCREEN, $node)) {
136
+ $video->withPresentation(Video::FULLSCREEN);
137
+ } elseif ($this->getProperty(Video::NON_INTERACTIVE, $node)) {
138
+ $video->withPresentation(Video::NON_INTERACTIVE);
139
+ }
140
+
141
+ if ($this->getProperty(self::PROPERTY_CONTROLS, $node)) {
142
+ $video->enableControls();
143
+ }
144
+
145
+ if ($this->getProperty(self::PROPERTY_PLAYBACK_MODE, $node)) {
146
+ $video->disableAutoplay();
147
+ }
148
+
149
+ if ($this->getProperty(self::PROPERTY_LIKE, $node)) {
150
+ $video->enableLike();
151
+ }
152
+
153
+ if ($this->getProperty(self::PROPERTY_COMMENTS, $node)) {
154
+ $video->enableComments();
155
+ }
156
+
157
+ $suppress_warnings = $transformer->suppress_warnings;
158
+ $transformer->suppress_warnings = true;
159
+ $transformer->transform($video, $node);
160
+ $transformer->suppress_warnings = $suppress_warnings;
161
+
162
+ return $instant_article;
163
+ }
164
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Transformer.php ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
10
+
11
+ use Facebook\InstantArticles\Transformer\Warnings\UnrecognizedElement;
12
+ use Facebook\InstantArticles\Transformer\Rules\Rule;
13
+ use Facebook\InstantArticles\Elements\InstantArticle;
14
+ use Facebook\InstantArticles\Validators\Type;
15
+
16
+ class Transformer
17
+ {
18
+ private $rules = array();
19
+ private $warnings = array();
20
+
21
+ public $suppress_warnings = false;
22
+
23
+ public function getWarnings()
24
+ {
25
+ return $this->warnings;
26
+ }
27
+
28
+ public function addRule($rule)
29
+ {
30
+ Type::enforce($rule, Rule::getClassName());
31
+ // Adds in reversed order for bottom-top processing rules
32
+ array_unshift($this->rules, $rule);
33
+ }
34
+
35
+ public function addWarning($warning)
36
+ {
37
+ $this->warnings[] = $warning;
38
+ }
39
+
40
+ public function transform($context, $node)
41
+ {
42
+ if (Type::is($context, InstantArticle::getClassName())) {
43
+ $context->addMetaProperty('op:transformer', 'facebook-instant-articles-sdk-php');
44
+ $context->addMetaProperty('op:transformer:version', InstantArticle::CURRENT_VERSION);
45
+ }
46
+
47
+ $log = \Logger::getLogger('facebook-instantarticles-transformer');
48
+ if (!$node) {
49
+ $e = new \Exception();
50
+ $log->error(
51
+ 'Transformer::transform($context, $node) requires $node'.
52
+ ' to be a valid one. Check on the stacktrace if this is '.
53
+ 'some nested transform operation and fix the selector.',
54
+ $e->getTraceAsString()
55
+ );
56
+ }
57
+ $current_context = $context;
58
+ if ($node->hasChildNodes()) {
59
+ foreach ($node->childNodes as $child) {
60
+ $matched = false;
61
+ $log->debug("===========================");
62
+ foreach ($this->rules as $rule) {
63
+ if ($rule->matches($context, $child)) {
64
+ $current_context = $rule->apply($this, $current_context, $child);
65
+ $matched = true;
66
+ break;
67
+ }
68
+ }
69
+ if (!$matched &&
70
+ !($child->nodeName === '#text' && trim($child->textContent) === '') &&
71
+ !($child->nodeName === '#comment') &&
72
+ !$this->suppress_warnings
73
+ ) {
74
+ $tag_content = $child->ownerDocument->saveXML($child);
75
+ $tag_trimmed = trim($tag_content);
76
+ if (!empty($tag_trimmed)) {
77
+ $log->debug('context class: '.get_class($context));
78
+ $log->debug('node name: '.$child->nodeName);
79
+ $log->debug("CONTENT NOT MATCHED: \n".$tag_content);
80
+ } else {
81
+ $log->debug('empty content ignored');
82
+ }
83
+
84
+ $this->addWarning(new UnrecognizedElement($current_context, $child));
85
+ }
86
+ }
87
+ }
88
+ return $context;
89
+ }
90
+
91
+ public function loadRules($json_file)
92
+ {
93
+ $configuration = json_decode($json_file, true);
94
+ if ($configuration && isset($configuration['rules'])) {
95
+ foreach ($configuration['rules'] as $configuration_rule) {
96
+ $clazz = $configuration_rule['class'];
97
+ try {
98
+ $factory_method = new \ReflectionMethod($clazz, 'createFrom');
99
+ } catch (\ReflectionException $e) {
100
+ $factory_method =
101
+ new \ReflectionMethod(
102
+ 'Facebook\\InstantArticles\\Transformer\\Rules\\'.$clazz,
103
+ 'createFrom'
104
+ );
105
+ }
106
+ $this->addRule($factory_method->invoke(null, $configuration_rule));
107
+ }
108
+ }
109
+ }
110
+
111
+ /**
112
+ * Removes all rules already set in this transformer instance.
113
+ */
114
+ public function resetRules()
115
+ {
116
+ $this->rules = array();
117
+ }
118
+
119
+ /**
120
+ * Gets all rules already set in this transformer instance.
121
+ *
122
+ * @return array List of configured rules.
123
+ */
124
+ public function getRules()
125
+ {
126
+ return $this->rules;
127
+ }
128
+
129
+ /**
130
+ * Overrides all rules already set in this transformer instance.
131
+ *
132
+ * @return array List of configured rules.
133
+ */
134
+ public function setRules($rules)
135
+ {
136
+ Type::enforceArrayOf($rules, Rule::getClassName());
137
+ $this->rules = $rules;
138
+ }
139
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Warnings/InvalidSelector.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\Transformer\Warnings;
10
+
11
+ /**
12
+ * Class InvalidSelector warning to show that an invalid selector for a required property was used
13
+ */
14
+ class InvalidSelector
15
+ {
16
+ private $fields;
17
+ private $context;
18
+ private $node;
19
+ private $rule;
20
+
21
+ public function __construct($fields, $context, $node, $rule)
22
+ {
23
+ $this->fields = $fields;
24
+ $this->context = $context;
25
+ $this->node = $node;
26
+ $this->rule = $rule;
27
+ }
28
+
29
+ public function __toString()
30
+ {
31
+ $reflection = new \ReflectionClass(get_class($this->context));
32
+ $class_name = $reflection->getShortName();
33
+
34
+ $reflection = new \ReflectionClass(get_class($this->rule));
35
+ $rule_name = $reflection->getShortName();
36
+
37
+ $has_properties = false;
38
+ $str_properties = '';
39
+ foreach ($this->rule->getProperties() as $name => $value) {
40
+ if (!$has_properties) {
41
+ $str_properties = '';
42
+ } else {
43
+ $str_properties = $str_properties.',';
44
+ }
45
+
46
+ $reflection = new \ReflectionClass(get_class($value));
47
+ $value_name = $reflection->getShortName();
48
+ $str_properties = $str_properties.' '.$name.'='.$value_name;
49
+ }
50
+ return "Invalid selector for fields ({$this->fields}). ".
51
+ "The node being transformed was <{$this->node->nodeName}> in the ".
52
+ "context of $class_name within the Rule $rule_name with these ".
53
+ "properties: {{$str_properties}}";
54
+ }
55
+
56
+ public function getContext()
57
+ {
58
+ return $this->context;
59
+ }
60
+
61
+ public function getNode()
62
+ {
63
+ return $this->node;
64
+ }
65
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Warnings/UnrecognizedElement.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Validators\Type;
12
+
13
+ class UnrecognizedElement
14
+ {
15
+ private $context;
16
+ private $node;
17
+
18
+ public function __construct($context, $node)
19
+ {
20
+ $this->context = $context;
21
+ $this->node = $node;
22
+ }
23
+
24
+ public function __toString()
25
+ {
26
+ $reflection = new \ReflectionClass(get_class($this->context));
27
+ $className = $reflection->getShortName();
28
+ $nodeName = $this->node->nodeName;
29
+ if (substr($nodeName, 0, 1) === '#') {
30
+ $nodeDescription = '"'.mb_strimwidth($this->node->textContent, 0, 30, '...').'"';
31
+ }
32
+ else {
33
+ $nodeDescription = '<';
34
+ $nodeDescription .= $nodeName;
35
+ if (Type::is($this->node, 'DOMElement')) {
36
+ $class = $this->node->getAttribute('class');
37
+ if ($class) {
38
+ $nodeDescription .= ' class="'. $class .'"';
39
+ }
40
+ }
41
+ $nodeDescription .= '>';
42
+ }
43
+ return "No rules defined for {$nodeDescription} in the context of $className";
44
+ }
45
+
46
+ public function getContext()
47
+ {
48
+ return $this->context;
49
+ }
50
+
51
+ public function getNode()
52
+ {
53
+ return $this->node;
54
+ }
55
+ }
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Validators/Type.php ADDED
@@ -0,0 +1,365 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Validators;
10
+
11
+ /**
12
+ * Class that have all the typechecks and sizechecks for elements and classes
13
+ * that needs to be well checked.
14
+ *
15
+ * is*() prefixed methods return boolean
16
+ *
17
+ * enforce*() prefixed methods return true for success and throw
18
+ * InvalidArgumentException for the invalid cases.
19
+ */
20
+ class Type
21
+ {
22
+ const STRING = 'STRING';
23
+ const INTEGER = 'INTEGER';
24
+ const BOOLEAN = 'BOOLEAN';
25
+ const FLOAT = 'FLOAT';
26
+ const ARRAY_TYPE = 'ARRAY_TYPE';
27
+
28
+ /**
29
+ * This method enforces the $var param to be instanceof one of the $types_allowed informed.
30
+ * It will throw exception if not satisfied
31
+ *
32
+ * @param mixed $var The object that will be verified
33
+ * @param mixed $types_allowed array of classes or one single class
34
+ * @return boolean true when success, or throws exception when not satisfied
35
+ * @throws InvalidArgumentException when $var doesnt comply with $types_allowed
36
+ */
37
+ public static function enforce($var, $types_allowed)
38
+ {
39
+ return self::is($var, $types_allowed, true);
40
+ }
41
+
42
+ /**
43
+ * This method checks if the $var param is instanceof one of the $types_allowed informed.
44
+ * It will return the success of the check.
45
+ *
46
+ * @param mixed $var The object that will be verified
47
+ * @param mixed $types_allowed array of classes or one single class
48
+ * @param boolean $enforce If informed with true, it works as ()@see Type::enforce()) method
49
+ * @return boolean true when success, false when failed the check
50
+ * @throws InvalidArgumentException if $enforced is true and $var doesnt comply with the $types_allowed
51
+ */
52
+ public static function is($var, $types_allowed, $enforce = false)
53
+ {
54
+ if (is_array($types_allowed)) {
55
+ foreach ($types_allowed as $type) {
56
+ if (($var instanceof $type) || self::isPrimitive($var, $type)) {
57
+ return true;
58
+ }
59
+ }
60
+ if ($enforce) {
61
+ self::throwException($var, $types_allowed);
62
+ }
63
+ return false;
64
+ } else {
65
+ $result = ($var instanceof $types_allowed) ||
66
+ self::isPrimitive($var, $types_allowed);
67
+ if (!$result && $enforce) {
68
+ self::throwException($var, $types_allowed);
69
+ }
70
+ return $result;
71
+ }
72
+ }
73
+
74
+
75
+ /**
76
+ * Auxiliary function to check for the primitive types.
77
+ *
78
+ * @param $var the Variable that will be testRenderBasic
79
+ * @param $type one of the Type::const that will be the set of possible values for $var
80
+ *
81
+ * @see Type::STRING
82
+ * @see Type::INTEGER
83
+ * @see Type::FLOAT
84
+ * @see Type::BOOLEAN
85
+ * @see Type::ARRAY_TYPE
86
+ */
87
+ private static function isPrimitive($var, $type)
88
+ {
89
+ switch ($type) {
90
+ case Type::STRING:
91
+ return is_string($var);
92
+ case Type::INTEGER:
93
+ return is_int($var);
94
+ case Type::FLOAT:
95
+ return is_float($var);
96
+ case Type::BOOLEAN:
97
+ return is_bool($var);
98
+ case Type::ARRAY_TYPE:
99
+ return is_array($var);
100
+ }
101
+ return false;
102
+ }
103
+
104
+ /**
105
+ * Method that checks if all elements in one array comply with the types
106
+ * inside the $types_allowed. If any element on that array doesnt meet the
107
+ * expectations an InvalidArgumentException will be thrown.
108
+ *
109
+ * @param array $var the target variable to be checked. REQUIRED must be array
110
+ * @param array|class $types_allowed The set of classes that $var will be checked against
111
+ * @throws InvalidArgumentException when not all items in an array are from the types in $types_allowed
112
+ *
113
+ * @see Type::STRING
114
+ * @see Type::INTEGER
115
+ * @see Type::FLOAT
116
+ * @see Type::BOOLEAN
117
+ */
118
+ public static function enforceArrayOf(
119
+ $var,
120
+ $types_allowed
121
+ ) {
122
+ return self::isArrayOf($var, $types_allowed, true);
123
+ }
124
+
125
+ /**
126
+ * Method that checks if all elements in one array comply with the types
127
+ * inside the $types_allowed. If any element on that array doesnt meet the
128
+ * expectations false will be returned
129
+ *
130
+ * @param array $var the target variable to be checked. REQUIRED must be array
131
+ * @param array|class $types_allowed The set of classes that $var will be checked against
132
+ * @return true for success, false otherwise
133
+ *
134
+ * @see Type::STRING
135
+ * @see Type::INTEGER
136
+ * @see Type::FLOAT
137
+ * @see Type::BOOLEAN
138
+ */
139
+ public static function isArrayOf(
140
+ $var,
141
+ $types_allowed,
142
+ $enforce = false
143
+ ) {
144
+ if (!is_array($var)) {
145
+ if ($enforce) {
146
+ throw new \InvalidArgumentException(
147
+ 'Type::isArrayOf() expects'.
148
+ 'first parameter to be an array.'
149
+ );
150
+ }
151
+ return false;
152
+ }
153
+ foreach ($var as $item) {
154
+ if (!self::is($item, $types_allowed, $enforce)) {
155
+ return false;
156
+ }
157
+ }
158
+ return true;
159
+ }
160
+
161
+ /**
162
+ * Auxiliary method that formats the message string and throws the Exception
163
+ */
164
+ private static function throwException($var, $types_allowed)
165
+ {
166
+ // stringify the $var parameter
167
+ ob_start();
168
+ var_dump($var);
169
+ $var_str = ob_get_clean();
170
+
171
+ // stringify the $types_allowed parameter
172
+ ob_start();
173
+ var_dump($types_allowed);
174
+ $types_str = ob_get_clean();
175
+
176
+ throw new \InvalidArgumentException(
177
+ "Method expects this value \n----[\n".$var_str."]----\n".
178
+ " to be one of the types \n====[\n".$types_str."]===="
179
+ );
180
+ }
181
+
182
+ /**
183
+ * Method that enforces the array size to be EXACTLY the $size informed. If
184
+ * the size differs from the $size it will throw InvalidArgumentException
185
+ * @param array $array the array that will be checked
186
+ * @param int $size The EXACTLY size that array must have
187
+ */
188
+ public static function enforceArraySize($array, $size)
189
+ {
190
+ return self::isArraySize($array, $size, true);
191
+ }
192
+
193
+ /**
194
+ * Method that checks the array size to be EXACTLY the $size informed. If
195
+ * the size differs from the $size it will return false, otherwise true.
196
+ * @param array $array the array that will be checked
197
+ * @param int $size The EXACTLY size that array must have
198
+ * @return true if matches the size, false otherwise
199
+ */
200
+ public static function isArraySize($array, $size, $enforce = false)
201
+ {
202
+ if (!is_array($array)) {
203
+ if ($enforce) {
204
+ throw new \InvalidArgumentException(
205
+ 'Type::isArraySize() expects'.
206
+ 'first parameter to be an array.'
207
+ );
208
+ }
209
+ return false;
210
+ }
211
+
212
+ $meets_size = count($array) == $size;
213
+ if ($enforce && !$meets_size) {
214
+ self::throwArrayException($array, $size, 'Exact size');
215
+ }
216
+ return $meets_size;
217
+ }
218
+
219
+ /**
220
+ * Method that enforces the array to have at least $min_size of elements. If
221
+ * the size is less than $min_size it will throw InvalidArgumentException
222
+ * I.e.: array (1,2,3), $min_size 3 = true
223
+ * I.e.: array (1,2,3), $min_size 4 = throws InvalidArgumentException
224
+ * @param array $array the array that will be checked
225
+ * @param int $min_size The EXACTLY size that array must have
226
+ * @throws InvalidArgumentException if $array doesnt have at least $min_size items
227
+ */
228
+ public static function enforceArraySizeGreaterThan($array, $min_size)
229
+ {
230
+ return self::isArraySizeGreaterThan($array, $min_size, true);
231
+ }
232
+
233
+ /**
234
+ * Method that checks if the array has at least $min_size of elements. If
235
+ * the size is less than $min_size it will return false.
236
+ * I.e.: array (1,2,3), $min_size 3 = true
237
+ * I.e.: array (1,2,3), $min_size 4 = false
238
+ * @param array $array the array that will be checked
239
+ * @param int $min_size The minimum elements the array must have
240
+ * @return true if has at least $min_size, false otherwise
241
+ */
242
+ public static function isArraySizeGreaterThan($array, $min_size, $enforce = false)
243
+ {
244
+ if (!is_array($array)) {
245
+ if ($enforce) {
246
+ throw new \InvalidArgumentException(
247
+ 'Type::isArraySizeGreaterThan() expects'.
248
+ 'first parameter to be an array.'
249
+ );
250
+ }
251
+ return false;
252
+ }
253
+
254
+ $meets_size = count($array) >= $min_size;
255
+ if ($enforce && !$meets_size) {
256
+ self::throwArrayException($array, $min_size, 'Minimal size');
257
+ }
258
+ return $meets_size;
259
+ }
260
+
261
+ /**
262
+ * Method that enforces the array to have at most $max_size of elements. If
263
+ * the size is more than $max_size it will throw InvalidArgumentException
264
+ * I.e.: array (1,2,3), $max_size 3 = true
265
+ * I.e.: array (1,2,3), $max_size 2 = throws InvalidArgumentException
266
+ * @param array $array the array that will be checked
267
+ * @param int $max_size The maximun items the array can have
268
+ * @throws InvalidArgumentException if $array have more than $max_size items
269
+ */
270
+ public static function enforceArraySizeLowerThan($array, $max_size)
271
+ {
272
+ return self::isArraySizeLowerThan($array, $max_size, true);
273
+ }
274
+
275
+ /**
276
+ * Method that checks if the array has at most $max_size of elements. If
277
+ * the size is more than $max_size it will return false
278
+ * I.e.: array (1,2,3), $max_size 3 = true
279
+ * I.e.: array (1,2,3), $max_size 2 = false
280
+ * @param array $array the array that will be checked
281
+ * @param int $max_size The maximun items the array can have
282
+ * @param boolean $enforce works as @see Type::enforceArrayMaxSize()
283
+ * @return true if it has less elements than $max_size, false otherwise
284
+ */
285
+ public static function isArraySizeLowerThan($array, $max_size, $enforce = false)
286
+ {
287
+ if (!is_array($array)) {
288
+ if ($enforce) {
289
+ throw new \InvalidArgumentException(
290
+ 'Type::isArraySizeLowerThan() expects'.
291
+ 'first parameter to be an array.'
292
+ );
293
+ }
294
+ return false;
295
+ }
296
+
297
+ $meets_size = count($array) <= $max_size;
298
+ if ($enforce && !$meets_size) {
299
+ self::throwArrayException($array, $max_size, 'Maximum size');
300
+ }
301
+ return $meets_size;
302
+ }
303
+
304
+ /*
305
+ * Utilitary method that constructs the message about array sizes an throws.
306
+ */
307
+ private static function throwArrayException($array, $size, $message)
308
+ {
309
+ $error_message =
310
+ 'Array expects a '.$message.' of '.$size.
311
+ ' but received an array with '.count($array).' items.';
312
+
313
+ throw new \InvalidArgumentException($error_message);
314
+ }
315
+
316
+ /**
317
+ * Method that checks if the value is in the possible ones from the set to
318
+ * compare against
319
+ *
320
+ * @param mixed $value The value that will be verified
321
+ * @param array $universe The universe the $value must be in.
322
+ * @return true if the value is IN the universe, false otherwise.
323
+ */
324
+ public static function isWithin($value, $universe, $enforce = false)
325
+ {
326
+ $within = in_array($value, $universe, true);
327
+ if (!$within && $enforce) {
328
+ self::throwNotWithingException($value, $universe);
329
+ }
330
+
331
+ return $within;
332
+ }
333
+
334
+ /**
335
+ * Method that enforces the value to be IN the universe informed, if not an
336
+ * exception will be thrown.
337
+ *
338
+ * @param mixed $value The value that will be verified
339
+ * @param array $universe The universe the $value must be in.
340
+ * @return true if the value is IN the universe, throws Exception otherwise.
341
+ * @throws InvalidArgumentException if the value not IN the expected universe.
342
+ */
343
+ public static function enforceWithin($value, $universe)
344
+ {
345
+ return self::isWithin($value, $universe, true);
346
+ }
347
+
348
+ private static function throwNotWithingException($value, $universe)
349
+ {
350
+ // stringify the $value parameter
351
+ ob_start();
352
+ var_dump($value);
353
+ $value_str = ob_get_clean();
354
+
355
+ // stringify the $universe parameter
356
+ ob_start();
357
+ var_dump($universe);
358
+ $universe_str = ob_get_clean();
359
+
360
+ throw new \InvalidArgumentException(
361
+ "Method expects this value \n----[\n".$value_str."]----\n".
362
+ " to be within this universe of values \n====[\n".$universe_str."]===="
363
+ );
364
+ }
365
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Client/ClientTest.php ADDED
@@ -0,0 +1,299 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Client;
10
+
11
+ use Facebook\Facebook;
12
+ use Facebook\InstantArticles\Elements\InstantArticle;
13
+ use Facebook\InstantArticles\Elements\Paragraph;
14
+
15
+ class ClientTest extends \PHPUnit_Framework_TestCase
16
+ {
17
+ private $client;
18
+ private $article;
19
+ private $facebook;
20
+
21
+ public function setUp()
22
+ {
23
+ $this->facebook = $this->getMockBuilder('Facebook\Facebook')
24
+ ->disableOriginalConstructor()
25
+ ->getMock();
26
+ $this->client = new Client(
27
+ $this->facebook,
28
+ "PAGE_ID",
29
+ false // developmentMode
30
+ );
31
+ $this->article =
32
+ InstantArticle::create()
33
+ ->addChild(
34
+ Paragraph::create()
35
+ ->appendText('Test')
36
+ );
37
+ }
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
+ /**
68
+ * Tests removing an article from an Instant Articles library.
69
+ *
70
+ * @covers Facebook\InstantArticles\Client\Client::removeArticle()
71
+ */
72
+ public function testRemoveArticle()
73
+ {
74
+ $canonicalURL = 'http://facebook.com';
75
+ $articleID = '1';
76
+
77
+ // Use a mocked client with stubbed getArticleIDFromCanonicalURL().
78
+ $this->client = $this->getMockBuilder('Facebook\InstantArticles\Client\Client')
79
+ ->setMethods(array('getArticleIDFromCanonicalURL'))
80
+ ->setConstructorArgs(array(
81
+ $this->facebook,
82
+ "PAGE_ID",
83
+ true // developmentMode
84
+ ))->getMock();
85
+
86
+ $this->client
87
+ ->expects($this->once())
88
+ ->method('getArticleIDFromCanonicalURL')
89
+ ->with($canonicalURL)
90
+ ->will($this->returnValue($articleID));;
91
+
92
+ $this->facebook
93
+ ->expects($this->once())
94
+ ->method('delete')
95
+ ->with($articleID);
96
+
97
+ $this->client->removeArticle($canonicalURL);
98
+ }
99
+
100
+ public function testImportArticleDevelopmentMode()
101
+ {
102
+ $this->client = new Client(
103
+ $this->facebook,
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()
139
+ {
140
+ $canonicalURL = "http://facebook.com";
141
+
142
+ $expectedArticleID = 123;
143
+
144
+ $serverResponseMock =
145
+ $this->getMockBuilder('Facebook\FacebookResponse')
146
+ ->disableOriginalConstructor()
147
+ ->getMock();
148
+ $graphNodeMock =
149
+ $this->getMockBuilder('Facebook\GraphNodes\GraphNode')
150
+ ->disableOriginalConstructor()
151
+ ->getMock();
152
+ $instantArticleMock =
153
+ $this->getMockBuilder('Facebook\GraphNodes\GraphNode')
154
+ ->disableOriginalConstructor()
155
+ ->getMock();
156
+
157
+ $instantArticleMock
158
+ ->expects($this->once())
159
+ ->method('getField')
160
+ ->with($this->equalTo('id'))
161
+ ->will($this->returnValue($expectedArticleID));
162
+ $graphNodeMock
163
+ ->expects($this->once())
164
+ ->method('getField')
165
+ ->with($this->equalTo('instant_article'))
166
+ ->will($this->returnValue($instantArticleMock));
167
+ $serverResponseMock
168
+ ->expects($this->once())
169
+ ->method('getGraphNode')
170
+ ->will($this->returnValue($graphNodeMock));
171
+ $this->facebook
172
+ ->expects($this->once())
173
+ ->method('get')
174
+ ->with($this->equalTo('?id='.$canonicalURL.'&fields=instant_article'))
175
+ ->will($this->returnValue($serverResponseMock));
176
+
177
+ $articleID = $this->client->getArticleIDFromCanonicalURL($canonicalURL);
178
+ $this->assertEquals($expectedArticleID, $articleID);
179
+ }
180
+
181
+ public function testGetArticleIDFromNotFoundCanonicalURL()
182
+ {
183
+ $canonicalURL = "http://facebook.com";
184
+
185
+ $expectedArticleID = null;
186
+
187
+ $serverResponseMock =
188
+ $this->getMockBuilder('Facebook\FacebookResponse')
189
+ ->disableOriginalConstructor()
190
+ ->getMock();
191
+ $graphNodeMock =
192
+ $this->getMockBuilder('Facebook\GraphNodes\GraphNode')
193
+ ->disableOriginalConstructor()
194
+ ->getMock();
195
+
196
+ $graphNodeMock
197
+ ->expects($this->once())
198
+ ->method('getField')
199
+ ->with($this->equalTo('instant_article'))
200
+ ->will($this->returnValue(null));
201
+ $serverResponseMock
202
+ ->expects($this->once())
203
+ ->method('getGraphNode')
204
+ ->will($this->returnValue($graphNodeMock));
205
+ $this->facebook
206
+ ->expects($this->once())
207
+ ->method('get')
208
+ ->with($this->equalTo('?id='.$canonicalURL.'&fields=instant_article'))
209
+ ->will($this->returnValue($serverResponseMock));
210
+
211
+ $articleID = $this->client->getArticleIDFromCanonicalURL($canonicalURL);
212
+ $this->assertEquals($expectedArticleID, $articleID);
213
+ }
214
+
215
+ public function testGetLastSubmissionStatus()
216
+ {
217
+ $articleID = '123';
218
+
219
+ $serverResponseMock =
220
+ $this->getMockBuilder('Facebook\FacebookResponse')
221
+ ->disableOriginalConstructor()
222
+ ->getMock();
223
+ $graphNodeMock =
224
+ $this->getMockBuilder('Facebook\GraphNodes\GraphNode')
225
+ ->disableOriginalConstructor()
226
+ ->getMock();
227
+
228
+ $graphNodeMock
229
+ ->expects($this->once())
230
+ ->method('getField')
231
+ ->with($this->equalTo('most_recent_import_status'))
232
+ ->will($this->returnValue(array(
233
+ "status" => "success",
234
+ "errors" => array(
235
+ array(
236
+ "level" => "warning",
237
+ "message" => "Test warning"
238
+ ),
239
+ array(
240
+ "level" => "fatal",
241
+ "message" => "Test fatal"
242
+ ),
243
+ array(
244
+ "level" => "error",
245
+ "message" => "Test error"
246
+ ),
247
+ array(
248
+ "level" => "info",
249
+ "message" => "Test info"
250
+ )
251
+ )
252
+ )));
253
+
254
+ $serverResponseMock
255
+ ->expects($this->once())
256
+ ->method('getGraphNode')
257
+ ->will($this->returnValue($graphNodeMock));
258
+ $this->facebook
259
+ ->expects($this->once())
260
+ ->method('get')
261
+ ->with($this->equalTo($articleID . '?fields=most_recent_import_status'))
262
+ ->will($this->returnValue($serverResponseMock));
263
+
264
+ $status = $this->client->getLastSubmissionStatus($articleID);
265
+ $this->assertEquals($status->getStatus(), InstantArticleStatus::SUCCESS);
266
+ $this->assertEquals(
267
+ $status->getMessages()[0]->getLevel(),
268
+ ServerMessage::WARNING
269
+ );
270
+ $this->assertEquals(
271
+ $status->getMessages()[0]->getMessage(),
272
+ 'Test warning'
273
+ );
274
+ $this->assertEquals(
275
+ $status->getMessages()[1]->getLevel(),
276
+ ServerMessage::FATAL
277
+ );
278
+ $this->assertEquals(
279
+ $status->getMessages()[1]->getMessage(),
280
+ 'Test fatal'
281
+ );
282
+ $this->assertEquals(
283
+ $status->getMessages()[2]->getLevel(),
284
+ ServerMessage::ERROR
285
+ );
286
+ $this->assertEquals(
287
+ $status->getMessages()[2]->getMessage(),
288
+ 'Test error'
289
+ );
290
+ $this->assertEquals(
291
+ $status->getMessages()[3]->getLevel(),
292
+ ServerMessage::INFO
293
+ );
294
+ $this->assertEquals(
295
+ $status->getMessages()[3]->getMessage(),
296
+ 'Test info'
297
+ );
298
+ }
299
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Client/HelperTest.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\Client;
10
+
11
+ use Facebook\Facebook;
12
+ use Facebook\InstantArticles\Elements\InstantArticle;
13
+ use Facebook\InstantArticles\Elements\Paragraph;
14
+
15
+ class HelperTest extends \PHPUnit_Framework_TestCase
16
+ {
17
+ private $helper;
18
+ private $facebook;
19
+
20
+ public function setUp()
21
+ {
22
+ $this->facebook = $this->getMockBuilder('Facebook\Facebook')
23
+ ->disableOriginalConstructor()
24
+ ->getMock();
25
+ $this->helper = new Helper(
26
+ $this->facebook
27
+ );
28
+ }
29
+
30
+ public function testGetPagesAndTokes()
31
+ {
32
+ $pagesAndTokens = array('page' => 'token');
33
+
34
+ $accessToken =
35
+ $this->getMockBuilder('Facebook\Authentication\AccessToken')
36
+ ->disableOriginalConstructor()
37
+ ->getMock();
38
+ $accessToken
39
+ ->expects($this->once())
40
+ ->method('isLongLived')
41
+ ->will($this->returnValue(true));
42
+ $this->facebook
43
+ ->expects($this->once())
44
+ ->method('setDefaultAccessToken')
45
+ ->with($accessToken);
46
+
47
+ $response =
48
+ $this->getMockBuilder('Facebook\FacebookResponse')
49
+ ->disableOriginalConstructor()
50
+ ->getMock();
51
+ $response
52
+ ->expects($this->once())
53
+ ->method('getGraphEdge')
54
+ ->will($this->returnValue($pagesAndTokens));
55
+
56
+ $this->facebook
57
+ ->expects($this->once())
58
+ ->method('get')
59
+ ->with('/me/accounts?fields=name,id,access_token,supports_instant_articles')
60
+ ->will($this->returnValue($response));
61
+
62
+ $pagesAndTokensReturned = $this->helper->getPagesAndTokens($accessToken);
63
+ $this->assertEquals($pagesAndTokensReturned, $pagesAndTokens);
64
+ }
65
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/AdTest.php ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Elements\Ad;
12
+
13
+ class AdTest extends \PHPUnit_Framework_TestCase
14
+ {
15
+ public function setUp()
16
+ {
17
+ }
18
+
19
+ public function testRenderBasic()
20
+ {
21
+ $ad =
22
+ Ad::create()
23
+ ->withSource('http://foo.com');
24
+
25
+ $expected =
26
+ '<figure class="op-ad">'.
27
+ '<iframe src="http://foo.com"></iframe>'.
28
+ '</figure>';
29
+
30
+ $rendered = $ad->render();
31
+ $this->assertEquals($expected, $rendered);
32
+ }
33
+
34
+ public function testRenderBasicWithHeightAndWidth()
35
+ {
36
+ $ad =
37
+ Ad::create()
38
+ ->withSource('http://foo.com')
39
+ ->withHeight(640)
40
+ ->withWidth(480);
41
+
42
+ $expected =
43
+ '<figure class="op-ad">'.
44
+ '<iframe src="http://foo.com" width="480" height="640"></iframe>'.
45
+ '</figure>';
46
+
47
+ $rendered = $ad->render();
48
+ $this->assertEquals($expected, $rendered);
49
+ }
50
+
51
+ public function testRenderBasicWithDefaultEnabled()
52
+ {
53
+ $ad =
54
+ Ad::create()
55
+ ->withSource('http://foo.com')
56
+ ->withHeight(640)
57
+ ->withWidth(480)
58
+ ->enableDefaultForReuse();
59
+
60
+ $expected =
61
+ '<figure class="op-ad op-ad-default">'.
62
+ '<iframe src="http://foo.com" width="480" height="640"></iframe>'.
63
+ '</figure>';
64
+
65
+ $rendered = $ad->render();
66
+ $this->assertEquals($expected, $rendered);
67
+ }
68
+
69
+ public function testRenderInlineWithHeightAndWidth()
70
+ {
71
+ $inline =
72
+ '<h1>Some custom code</h1>'.
73
+ '<script>alert("test");</script>';
74
+ $document = new \DOMDocument();
75
+ $fragment = $document->createDocumentFragment();
76
+ $fragment->appendXML($inline);
77
+ $ad =
78
+ Ad::create()
79
+ ->withHTML($fragment)
80
+ ->withHeight(640)
81
+ ->withWidth(480);
82
+
83
+ $expected =
84
+ '<figure class="op-ad">'.
85
+ '<iframe width="480" height="640">'.
86
+ '<h1>Some custom code</h1>'.
87
+ '<script>alert("test");</script>'.
88
+ '</iframe>'.
89
+ '</figure>';
90
+
91
+ $rendered = $ad->render();
92
+ $this->assertEquals($expected, $rendered);
93
+ }
94
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/AnalyticsTest.php ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Elements\Analytics;
12
+
13
+ class AnalyticsTest extends \PHPUnit_Framework_TestCase
14
+ {
15
+ public function setUp()
16
+ {
17
+ }
18
+
19
+ public function testRenderBasic()
20
+ {
21
+ $analytics =
22
+ Analytics::create()
23
+ ->withSource('http://foo.com');
24
+
25
+ $expected =
26
+ '<figure class="op-tracker">'.
27
+ '<iframe src="http://foo.com"></iframe>'.
28
+ '</figure>';
29
+
30
+ $rendered = $analytics->render();
31
+ $this->assertEquals($expected, $rendered);
32
+ }
33
+
34
+ public function testRenderWithHTML()
35
+ {
36
+ $inline =
37
+ '<h1>Some custom code</h1>'.
38
+ '<script>alert("test");</script>';
39
+ $document = new \DOMDocument();
40
+ $fragment = $document->createDocumentFragment();
41
+ $fragment->appendXML($inline);
42
+
43
+ $analytics =
44
+ Analytics::create()
45
+ ->withHTML($fragment);
46
+
47
+ $expected =
48
+ '<figure class="op-tracker">'.
49
+ '<iframe>'.
50
+ '<h1>Some custom code</h1>'.
51
+ '<script>alert("test");</script>'.
52
+ '</iframe>'.
53
+ '</figure>';
54
+
55
+ $rendered = $analytics->render();
56
+ $this->assertEquals($expected, $rendered);
57
+ }
58
+
59
+ public function testRenderWithGoogleAnalytics()
60
+ {
61
+ $google_analytics =
62
+ '<!-- Google Analytics -->'.
63
+ '<script>'.
64
+ '(function(i,s,o,g,r,a,m){i["GoogleAnalyticsObject"]=r;i[r]=i[r]||function(){'.
65
+ '(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),'.
66
+ 'm=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)'.
67
+ '})(window,document,"script","//www.google-analytics.com/analytics.js","ga");'.
68
+ 'ga("create", "UA-XXXXX-Y", "auto");'.
69
+ 'ga("send", "pageview");'.
70
+ '</script>'.
71
+ '<!-- End Google Analytics -->';
72
+ $document = new \DOMDocument();
73
+ $fragment = $document->createDocumentFragment();
74
+ $fragment->appendXML($google_analytics);
75
+
76
+ $analytics =
77
+ Analytics::create()
78
+ ->withHTML($fragment);
79
+
80
+ $expected =
81
+ '<figure class="op-tracker">'.
82
+ '<iframe>'.
83
+ $google_analytics.
84
+ '</iframe>'.
85
+ '</figure>';
86
+
87
+ $rendered = $analytics->render();
88
+ $this->assertEquals($expected, $rendered);
89
+ }
90
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/AudioTest.php ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Elements\Audio;
12
+
13
+ class AudioTest extends \PHPUnit_Framework_TestCase
14
+ {
15
+ public function setUp()
16
+ {
17
+ }
18
+
19
+ public function testRenderBasic()
20
+ {
21
+ $audio =
22
+ Audio::create()
23
+ ->withURL('http://foo.com/mp3');
24
+
25
+ $expected =
26
+ '<audio>'.
27
+ '<source src="http://foo.com/mp3"/>'.
28
+ '</audio>';
29
+
30
+ $rendered = $audio->render();
31
+ $this->assertEquals($expected, $rendered);
32
+ }
33
+
34
+ public function testRenderWithTitle()
35
+ {
36
+ $audio =
37
+ Audio::create()
38
+ ->withURL('http://foo.com/mp3')
39
+ ->withTitle('audio title');
40
+
41
+ $expected =
42
+ '<audio title="audio title">'.
43
+ '<source src="http://foo.com/mp3"/>'.
44
+ '</audio>';
45
+
46
+ $rendered = $audio->render();
47
+ $this->assertEquals($expected, $rendered);
48
+ }
49
+
50
+ public function testRenderWithAutoplay()
51
+ {
52
+ $audio =
53
+ Audio::create()
54
+ ->withURL('http://foo.com/mp3')
55
+ ->enableAutoplay();
56
+
57
+ $expected =
58
+ '<audio autoplay="autoplay">'.
59
+ '<source src="http://foo.com/mp3"/>'.
60
+ '</audio>';
61
+
62
+ $rendered = $audio->render();
63
+ $this->assertEquals($expected, $rendered);
64
+ }
65
+
66
+ public function testRenderWithMuted()
67
+ {
68
+ $audio =
69
+ Audio::create()
70
+ ->withURL('http://foo.com/mp3')
71
+ ->enableMuted();
72
+
73
+ $expected =
74
+ '<audio muted="muted">'.
75
+ '<source src="http://foo.com/mp3"/>'.
76
+ '</audio>';
77
+
78
+ $rendered = $audio->render();
79
+ $this->assertEquals($expected, $rendered);
80
+ }
81
+
82
+ public function testRenderWithTitleAndAutoplayMuted()
83
+ {
84
+ $audio =
85
+ Audio::create()
86
+ ->withURL('http://foo.com/mp3')
87
+ ->withTitle('audio title')
88
+ ->enableMuted()
89
+ ->enableAutoplay();
90
+
91
+ $expected =
92
+ '<audio title="audio title" autoplay="autoplay" muted="muted">'.
93
+ '<source src="http://foo.com/mp3"/>'.
94
+ '</audio>';
95
+
96
+ $rendered = $audio->render();
97
+ $this->assertEquals($expected, $rendered);
98
+ }
99
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/AuthorTest.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Elements\Author;
12
+
13
+ class AuthorTest extends \PHPUnit_Framework_TestCase
14
+ {
15
+ public function setUp()
16
+ {
17
+ }
18
+
19
+ public function testRenderAuthorWithFB()
20
+ {
21
+ $author =
22
+ Author::create()
23
+ ->withURL('http://facebook.com/everton.rosario')
24
+ ->withName('Everton Rosario')
25
+ ->withDescription('Passionate coder and mountain biker');
26
+
27
+ $expected =
28
+ '<address>'.
29
+ '<a href="http://facebook.com/everton.rosario" rel="facebook">Everton Rosario</a>'.
30
+ 'Passionate coder and mountain biker'.
31
+ '</address>';
32
+
33
+ $rendered = $author->render();
34
+ $this->assertEquals($expected, $rendered);
35
+ }
36
+
37
+ public function testRenderAuthorWithTwitter()
38
+ {
39
+ $author =
40
+ Author::create()
41
+ ->withURL('http://twitter.com/evertonrosario')
42
+ ->withName('Everton Rosario')
43
+ ->withDescription('Passionate coder and mountain biker');
44
+
45
+ $expected =
46
+ '<address>'.
47
+ '<a href="http://twitter.com/evertonrosario">Everton Rosario</a>'.
48
+ 'Passionate coder and mountain biker'.
49
+ '</address>';
50
+
51
+ $rendered = $author->render();
52
+ $this->assertEquals($expected, $rendered);
53
+ }
54
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/BlockquoteTest.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Elements\Blockquote;
12
+
13
+ class BlockquoteTest extends \PHPUnit_Framework_TestCase
14
+ {
15
+ public function setUp()
16
+ {
17
+ }
18
+
19
+ public function testRenderBasic()
20
+ {
21
+ $blockquote =
22
+ Blockquote::create()
23
+ ->appendText('Some text to be within a blockquote for testing.');
24
+
25
+ $expected =
26
+ '<blockquote>'.
27
+ 'Some text to be within a blockquote for testing.'.
28
+ '</blockquote>';
29
+
30
+ $rendered = $blockquote->render();
31
+ $this->assertEquals($expected, $rendered);
32
+ }
33
+
34
+ public function testRenderWithBoldStrongItalicEm()
35
+ {
36
+ $blockquote =
37
+ Blockquote::create()
38
+ ->appendText(Bold::create()->appendText('Some'))
39
+ ->appendText(' text to be ')
40
+ ->appendText(Italic::create()->appendText('within'))
41
+ ->appendText(' a ')
42
+ ->appendText(Italic::create()->appendText('blockquote'))
43
+ ->appendText(' for ')
44
+ ->appendText(Bold::create()->appendText('testing.'));
45
+
46
+ $expected =
47
+ '<blockquote>'.
48
+ '<b>Some</b> text to be <i>within</i> a <i>blockquote</i> for <b>testing.</b>'.
49
+ '</blockquote>';
50
+
51
+ $rendered = $blockquote->render();
52
+ $this->assertEquals($expected, $rendered);
53
+ }
54
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/CaptionTest.php ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Elements\Caption;
12
+
13
+ class CaptionTest extends \PHPUnit_Framework_TestCase
14
+ {
15
+ public function setUp()
16
+ {
17
+ }
18
+
19
+ public function testRenderBasic()
20
+ {
21
+ $caption =
22
+ Caption::create()
23
+ ->appendText('Caption Title');
24
+
25
+ $expected =
26
+ '<figcaption>'.
27
+ 'Caption Title'.
28
+ '</figcaption>';
29
+
30
+ $rendered = $caption->render();
31
+ $this->assertEquals($expected, $rendered);
32
+ }
33
+
34
+ public function testRenderWithSubTitle()
35
+ {
36
+ $caption =
37
+ Caption::create()
38
+ ->withTitle('Caption Title')
39
+ ->withSubTitle('Caption SubTitle');
40
+
41
+ $expected =
42
+ '<figcaption>'.
43
+ '<h1>Caption Title</h1>'.
44
+ '<h2>Caption SubTitle</h2>'.
45
+ '</figcaption>';
46
+
47
+ $rendered = $caption->render();
48
+ $this->assertEquals($expected, $rendered);
49
+ }
50
+
51
+ public function testRenderWithCredit()
52
+ {
53
+ $caption =
54
+ Caption::create()
55
+ ->withTitle('Caption Title')
56
+ ->withCredit('Caption Credit');
57
+
58
+ $expected =
59
+ '<figcaption>'.
60
+ '<h1>Caption Title</h1>'.
61
+ '<cite>Caption Credit</cite>'.
62
+ '</figcaption>';
63
+
64
+ $rendered = $caption->render();
65
+ $this->assertEquals($expected, $rendered);
66
+ }
67
+
68
+ public function testRenderWithPosition()
69
+ {
70
+ $caption =
71
+ Caption::create()
72
+ ->appendText('Caption Title')
73
+ ->withPostion(Caption::POSITION_BELOW);
74
+
75
+ $expected =
76
+ '<figcaption class="op-vertical-below">'.
77
+ 'Caption Title'.
78
+ '</figcaption>';
79
+
80
+ $rendered = $caption->render();
81
+ $this->assertEquals($expected, $rendered);
82
+ }
83
+
84
+ public function testRenderWithFontSize()
85
+ {
86
+ $caption =
87
+ Caption::create()
88
+ ->appendText('Caption Title')
89
+ ->withFontsize(Caption::SIZE_LARGE);
90
+
91
+ $expected =
92
+ '<figcaption class="op-large">'.
93
+ 'Caption Title'.
94
+ '</figcaption>';
95
+
96
+ $rendered = $caption->render();
97
+ $this->assertEquals($expected, $rendered);
98
+ }
99
+
100
+ public function testRenderWithTextAlignment()
101
+ {
102
+ $caption =
103
+ Caption::create()
104
+ ->appendText('Caption Title')
105
+ ->withTextAlignment(Caption::ALIGN_LEFT);
106
+
107
+ $expected =
108
+ '<figcaption class="op-left">'.
109
+ 'Caption Title'.
110
+ '</figcaption>';
111
+
112
+ $rendered = $caption->render();
113
+ $this->assertEquals($expected, $rendered);
114
+ }
115
+
116
+ public function testRenderWithAllFormating()
117
+ {
118
+ $caption =
119
+ Caption::create()
120
+ ->appendText('Caption Title')
121
+ ->withFontsize(Caption::SIZE_LARGE)
122
+ ->withPostion(Caption::POSITION_BELOW)
123
+ ->withTextAlignment(Caption::ALIGN_LEFT);
124
+
125
+ $expected =
126
+ '<figcaption class="op-left op-large op-vertical-below">'.
127
+ 'Caption Title'.
128
+ '</figcaption>';
129
+
130
+ $rendered = $caption->render();
131
+ $this->assertEquals($expected, $rendered);
132
+ }
133
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/CiteTest.php ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Elements\Cite;
12
+ use Facebook\InstantArticles\Elements\Bold;
13
+ use Facebook\InstantArticles\Elements\Italic;
14
+ use Facebook\InstantArticles\Elements\Anchor;
15
+
16
+ class CiteTest extends \PHPUnit_Framework_TestCase
17
+ {
18
+ public function setUp()
19
+ {
20
+ }
21
+
22
+ public function testRenderBasic()
23
+ {
24
+ $cite =
25
+ Cite::create()
26
+ ->appendText('Citation simple text.');
27
+
28
+ $expected =
29
+ '<cite>'.
30
+ 'Citation simple text.'.
31
+ '</cite>';
32
+
33
+ $rendered = $cite->render();
34
+ $this->assertEquals($expected, $rendered);
35
+ }
36
+
37
+ public function testRenderWithPosition()
38
+ {
39
+ $cite =
40
+ Cite::create()
41
+ ->appendText('Citation simple text.')
42
+ ->withPostion(Caption::POSITION_ABOVE);
43
+
44
+ $expected =
45
+ '<cite class="op-vertical-above">'.
46
+ 'Citation simple text.'.
47
+ '</cite>';
48
+
49
+ $rendered = $cite->render();
50
+ $this->assertEquals($expected, $rendered);
51
+ }
52
+
53
+ public function testRenderWithTextAlign()
54
+ {
55
+ $cite =
56
+ Cite::create()
57
+ ->appendText('Citation simple text.')
58
+ ->withTextAlignment(Caption::ALIGN_LEFT);
59
+
60
+ $expected =
61
+ '<cite class="op-left">'.
62
+ 'Citation simple text.'.
63
+ '</cite>';
64
+
65
+ $rendered = $cite->render();
66
+ $this->assertEquals($expected, $rendered);
67
+ }
68
+
69
+ public function testRenderWithPositionAndAlignment()
70
+ {
71
+ $cite =
72
+ Cite::create()
73
+ ->appendText('Citation simple text.')
74
+ ->withPostion(Caption::POSITION_ABOVE)
75
+ ->withTextAlignment(Caption::ALIGN_LEFT);
76
+
77
+ $expected =
78
+ '<cite class="op-vertical-above op-left">'.
79
+ 'Citation simple text.'.
80
+ '</cite>';
81
+
82
+ $rendered = $cite->render();
83
+ $this->assertEquals($expected, $rendered);
84
+ }
85
+
86
+ public function testRenderWithUnescapedHTML()
87
+ {
88
+ $cite =
89
+ Cite::create()
90
+ ->appendText(
91
+ '<b>Some</b> text to be <i>within</i> a <em>paragraph</em> for <strong>testing.</strong>'
92
+ );
93
+
94
+ $expected =
95
+ '<cite>'.
96
+ '&lt;b&gt;Some&lt;/b&gt; text to be &lt;i&gt;within&lt;/i&gt; a'.
97
+ ' &lt;em&gt;paragraph&lt;/em&gt; for &lt;strong&gt;testing.&lt;/strong&gt;'.
98
+ '</cite>';
99
+
100
+ $rendered = $cite->render();
101
+ $this->assertEquals($expected, $rendered);
102
+ }
103
+
104
+ public function testRenderWithFormattedText()
105
+ {
106
+ $cite =
107
+ Cite::create()
108
+ ->appendText(Bold::create()->appendText('Some'))
109
+ ->appendText(' text to be ')
110
+ ->appendText(Italic::create()->appendText('within'))
111
+ ->appendText(' a ')
112
+ ->appendText(Italic::create()->appendText('paragraph'))
113
+ ->appendText(' for ')
114
+ ->appendText(Bold::create()->appendText('testing.'));
115
+
116
+ $expected =
117
+ '<cite>'.
118
+ '<b>Some</b> text to be <i>within</i> a <i>paragraph</i> for <b>testing.</b>'.
119
+ '</cite>';
120
+
121
+ $rendered = $cite->render();
122
+ $this->assertEquals($expected, $rendered);
123
+ }
124
+
125
+ public function testRenderWithLink()
126
+ {
127
+ $cite =
128
+ Cite::create()
129
+ ->appendText('Some ')
130
+ ->appendText(
131
+ Anchor::create()
132
+ ->withHRef('http://foo.com')
133
+ ->appendText('link')
134
+ )
135
+ ->appendText('.');
136
+
137
+ $expected =
138
+ '<cite>'.
139
+ 'Some <a href="http://foo.com">link</a>.'.
140
+ '</cite>';
141
+
142
+ $rendered = $cite->render();
143
+ $this->assertEquals($expected, $rendered);
144
+ }
145
+
146
+ public function testRenderWithNestedFormattedText()
147
+ {
148
+ $cite =
149
+ Cite::create()
150
+ ->appendText(
151
+ Bold::create()
152
+ ->appendText('Some ')
153
+ ->appendText(Italic::create()->appendText('nested formatting'))
154
+ ->appendText('.')
155
+ );
156
+
157
+ $expected =
158
+ '<cite>'.
159
+ '<b>Some <i>nested formatting</i>.</b>'.
160
+ '</cite>';
161
+
162
+ $rendered = $cite->render();
163
+ $this->assertEquals($expected, $rendered);
164
+ }
165
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/FooterTest.php ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Elements\Footer;
12
+ use Facebook\InstantArticles\Elements\Paragraph;
13
+ use Facebook\InstantArticles\Elements\RelatedArticles;
14
+
15
+ class FooterTest extends \PHPUnit_Framework_TestCase
16
+ {
17
+ public function setUp()
18
+ {
19
+ }
20
+
21
+ public function testRenderBasic()
22
+ {
23
+ $footer =
24
+ Footer::create()
25
+ ->withCredits('Some plaintext credits.');
26
+
27
+ $expected =
28
+ '<footer>'.
29
+ '<aside>'.
30
+ 'Some plaintext credits.'.
31
+ '</aside>'.
32
+ '</footer>';
33
+
34
+ $rendered = $footer->render();
35
+ $this->assertEquals($expected, $rendered);
36
+ }
37
+
38
+ public function testRenderWithParagraphCredits()
39
+ {
40
+ $footer =
41
+ Footer::create()
42
+ ->withCredits([
43
+ Paragraph::create()->appendText('Some paragraph credits.'),
44
+ Paragraph::create()->appendText('Other paragraph credits.'),
45
+ ]);
46
+
47
+ $expected =
48
+ '<footer>'.
49
+ '<aside>'.
50
+ '<p>'.
51
+ 'Some paragraph credits.'.
52
+ '</p>'.
53
+ '<p>'.
54
+ 'Other paragraph credits.'.
55
+ '</p>'.
56
+ '</aside>'.
57
+ '</footer>';
58
+
59
+ $rendered = $footer->render();
60
+ $this->assertEquals($expected, $rendered);
61
+ }
62
+
63
+ public function testRenderWithParagraphCreditsAppend()
64
+ {
65
+ $footer =
66
+ Footer::create()
67
+ ->addCredit(
68
+ Paragraph::create()->appendText('Some paragraph credits.')
69
+ )
70
+ ->addCredit(
71
+ Paragraph::create()->appendText('Other paragraph credits.')
72
+ );
73
+
74
+ $expected =
75
+ '<footer>'.
76
+ '<aside>'.
77
+ '<p>'.
78
+ 'Some paragraph credits.'.
79
+ '</p>'.
80
+ '<p>'.
81
+ 'Other paragraph credits.'.
82
+ '</p>'.
83
+ '</aside>'.
84
+ '</footer>';
85
+
86
+ $rendered = $footer->render();
87
+ $this->assertEquals($expected, $rendered);
88
+ }
89
+
90
+ public function testRenderWithCopyright()
91
+ {
92
+ $footer =
93
+ Footer::create()
94
+ ->withCopyright('2016 Facebook');
95
+
96
+ $expected =
97
+ '<footer>'.
98
+ '<small>'.
99
+ '2016 Facebook'.
100
+ '</small>'.
101
+ '</footer>';
102
+
103
+ $rendered = $footer->render();
104
+ $this->assertEquals($expected, $rendered);
105
+ }
106
+
107
+ public function testRenderWithRelatedArticles()
108
+ {
109
+ $footer =
110
+ Footer::create()
111
+ ->withCopyright('2016 Facebook')
112
+ ->withRelatedArticles(
113
+ RelatedArticles::create()
114
+ ->addRelated(RelatedItem::create()->withURL('http://related.com/1'))
115
+ ->addRelated(RelatedItem::create()->withURL('http://related.com/2'))
116
+ ->addRelated(RelatedItem::create()->withURL('http://sponsored.com/1')->enableSponsored())
117
+ );
118
+
119
+ $expected =
120
+ '<footer>'.
121
+ '<small>'.
122
+ '2016 Facebook'.
123
+ '</small>'.
124
+ '<ul class="op-related-articles">'.
125
+ '<li><a href="http://related.com/1"></a></li>'.
126
+ '<li><a href="http://related.com/2"></a></li>'.
127
+ '<li data-sponsored="true"><a href="http://sponsored.com/1"></a></li>'.
128
+ '</ul>'.
129
+ '</footer>';
130
+
131
+ $rendered = $footer->render();
132
+ $this->assertEquals($expected, $rendered);
133
+ }
134
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/GeoTagTest.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Elements\GeoTag;
12
+ use Facebook\InstantArticles\Elements\Caption;
13
+
14
+ class GeoTagTest extends \PHPUnit_Framework_TestCase
15
+ {
16
+ public function setUp()
17
+ {
18
+ }
19
+
20
+ public function testRenderWithGeotag()
21
+ {
22
+ $script =
23
+ '{'.
24
+ '"type": "Feature",'.
25
+ '"geometry": {'.
26
+ '"type": "Point",'.
27
+ '"coordinates": [23.166667, 89.216667]'.
28
+ '},'.
29
+ '"properties": {'.
30
+ '"title": "Jessore, Bangladesh",'.
31
+ '"radius": 750000,'.
32
+ '"pivot": true,'.
33
+ '"style": "satellite"'.
34
+ '}'.
35
+ '}';
36
+
37
+ $geo_tag = GeoTag::create()->withScript($script);
38
+
39
+ $expected =
40
+ '<script type="application/json" class="op-geotag">'.
41
+ $script.
42
+ '</script>';
43
+
44
+ $rendered = $geo_tag->render();
45
+ $this->assertEquals($expected, $rendered);
46
+ }
47
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/H1Test.php ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Elements\H1;
12
+ use Facebook\InstantArticles\Elements\Bold;
13
+ use Facebook\InstantArticles\Elements\Italic;
14
+ use Facebook\InstantArticles\Elements\Anchor;
15
+
16
+ class H1Test extends \PHPUnit_Framework_TestCase
17
+ {
18
+ public function setUp()
19
+ {
20
+ }
21
+
22
+ public function testRenderBasic()
23
+ {
24
+ $h1 =
25
+ H1::create()
26
+ ->appendText('Title simple text.');
27
+
28
+ $expected =
29
+ '<h1>'.
30
+ 'Title simple text.'.
31
+ '</h1>';
32
+
33
+ $rendered = $h1->render();
34
+ $this->assertEquals($expected, $rendered);
35
+ }
36
+
37
+ public function testRenderWithPosition()
38
+ {
39
+ $h1 =
40
+ H1::create()
41
+ ->appendText('Title simple text.')
42
+ ->withPostion(Caption::POSITION_ABOVE);
43
+
44
+ $expected =
45
+ '<h1 class="op-vertical-above">'.
46
+ 'Title simple text.'.
47
+ '</h1>';
48
+
49
+ $rendered = $h1->render();
50
+ $this->assertEquals($expected, $rendered);
51
+ }
52
+
53
+ public function testRenderWithTextAlign()
54
+ {
55
+ $h1 =
56
+ H1::create()
57
+ ->appendText('Title simple text.')
58
+ ->withTextAlignment(Caption::ALIGN_LEFT);
59
+
60
+ $expected =
61
+ '<h1 class="op-left">'.
62
+ 'Title simple text.'.
63
+ '</h1>';
64
+
65
+ $rendered = $h1->render();
66
+ $this->assertEquals($expected, $rendered);
67
+ }
68
+
69
+ public function testRenderWithPositionAndAlignment()
70
+ {
71
+ $h1 =
72
+ H1::create()
73
+ ->appendText('Title simple text.')
74
+ ->withPostion(Caption::POSITION_ABOVE)
75
+ ->withTextAlignment(Caption::ALIGN_LEFT);
76
+
77
+ $expected =
78
+ '<h1 class="op-vertical-above op-left">'.
79
+ 'Title simple text.'.
80
+ '</h1>';
81
+
82
+ $rendered = $h1->render();
83
+ $this->assertEquals($expected, $rendered);
84
+ }
85
+
86
+ public function testRenderWithUnescapedHTML()
87
+ {
88
+ $h1 =
89
+ H1::create()
90
+ ->appendText(
91
+ '<b>Some</b> text to be <i>within</i> a <em>paragraph</em> for <strong>testing.</strong>'
92
+ );
93
+
94
+ $expected =
95
+ '<h1>'.
96
+ '&lt;b&gt;Some&lt;/b&gt; text to be &lt;i&gt;within&lt;/i&gt; a'.
97
+ ' &lt;em&gt;paragraph&lt;/em&gt; for &lt;strong&gt;testing.&lt;/strong&gt;'.
98
+ '</h1>';
99
+
100
+ $rendered = $h1->render();
101
+ $this->assertEquals($expected, $rendered);
102
+ }
103
+
104
+ public function testRenderWithFormattedText()
105
+ {
106
+ $h1 =
107
+ H1::create()
108
+ ->appendText(Bold::create()->appendText('Some'))
109
+ ->appendText(' text to be ')
110
+ ->appendText(Italic::create()->appendText('within'))
111
+ ->appendText(' a ')
112
+ ->appendText(Italic::create()->appendText('paragraph'))
113
+ ->appendText(' for ')
114
+ ->appendText(Bold::create()->appendText('testing.'));
115
+
116
+ $expected =
117
+ '<h1>'.
118
+ '<b>Some</b> text to be <i>within</i> a <i>paragraph</i> for <b>testing.</b>'.
119
+ '</h1>';
120
+
121
+ $rendered = $h1->render();
122
+ $this->assertEquals($expected, $rendered);
123
+ }
124
+
125
+ public function testRenderWithLink()
126
+ {
127
+ $h1 =
128
+ H1::create()
129
+ ->appendText('Some ')
130
+ ->appendText(
131
+ Anchor::create()
132
+ ->withHRef('http://foo.com')
133
+ ->appendText('link')
134
+ )
135
+ ->appendText('.');
136
+
137
+ $expected =
138
+ '<h1>'.
139
+ 'Some <a href="http://foo.com">link</a>.'.
140
+ '</h1>';
141
+
142
+ $rendered = $h1->render();
143
+ $this->assertEquals($expected, $rendered);
144
+ }
145
+
146
+ public function testRenderWithNestedFormattedText()
147
+ {
148
+ $h1 =
149
+ H1::create()
150
+ ->appendText(
151
+ Bold::create()
152
+ ->appendText('Some ')
153
+ ->appendText(Italic::create()->appendText('nested formatting'))
154
+ ->appendText('.')
155
+ );
156
+
157
+ $expected =
158
+ '<h1>'.
159
+ '<b>Some <i>nested formatting</i>.</b>'.
160
+ '</h1>';
161
+
162
+ $rendered = $h1->render();
163
+ $this->assertEquals($expected, $rendered);
164
+ }
165
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/H2Test.php ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Elements\H2;
12
+ use Facebook\InstantArticles\Elements\Bold;
13
+ use Facebook\InstantArticles\Elements\Italic;
14
+ use Facebook\InstantArticles\Elements\Anchor;
15
+
16
+ class H2Test extends \PHPUnit_Framework_TestCase
17
+ {
18
+ public function setUp()
19
+ {
20
+ }
21
+
22
+ public function testRenderBasic()
23
+ {
24
+ $h2 =
25
+ H2::create()
26
+ ->appendText('Sub title simple text.');
27
+
28
+ $expected =
29
+ '<h2>'.
30
+ 'Sub title simple text.'.
31
+ '</h2>';
32
+
33
+ $rendered = $h2->render();
34
+ $this->assertEquals($expected, $rendered);
35
+ }
36
+
37
+ public function testRenderWithPosition()
38
+ {
39
+ $h2 =
40
+ H2::create()
41
+ ->appendText('Sub title simple text.')
42
+ ->withPostion(Caption::POSITION_ABOVE);
43
+
44
+ $expected =
45
+ '<h2 class="op-vertical-above">'.
46
+ 'Sub title simple text.'.
47
+ '</h2>';
48
+
49
+ $rendered = $h2->render();
50
+ $this->assertEquals($expected, $rendered);
51
+ }
52
+
53
+ public function testRenderWithTextAlign()
54
+ {
55
+ $h2 =
56
+ H2::create()
57
+ ->appendText('Sub title simple text.')
58
+ ->withTextAlignment(Caption::ALIGN_LEFT);
59
+
60
+ $expected =
61
+ '<h2 class="op-left">'.
62
+ 'Sub title simple text.'.
63
+ '</h2>';
64
+
65
+ $rendered = $h2->render();
66
+ $this->assertEquals($expected, $rendered);
67
+ }
68
+
69
+ public function testRenderWithPositionAndAlignment()
70
+ {
71
+ $h2 =
72
+ H2::create()
73
+ ->appendText('Sub title simple text.')
74
+ ->withPostion(Caption::POSITION_ABOVE)
75
+ ->withTextAlignment(Caption::ALIGN_LEFT);
76
+
77
+ $expected =
78
+ '<h2 class="op-vertical-above op-left">'.
79
+ 'Sub title simple text.'.
80
+ '</h2>';
81
+
82
+ $rendered = $h2->render();
83
+ $this->assertEquals($expected, $rendered);
84
+ }
85
+
86
+ public function testRenderWithUnescapedHTML()
87
+ {
88
+ $h2 =
89
+ H2::create()
90
+ ->appendText(
91
+ '<b>Some</b> text to be <i>within</i> a <em>paragraph</em> for <strong>testing.</strong>'
92
+ );
93
+
94
+ $expected =
95
+ '<h2>'.
96
+ '&lt;b&gt;Some&lt;/b&gt; text to be &lt;i&gt;within&lt;/i&gt; a'.
97
+ ' &lt;em&gt;paragraph&lt;/em&gt; for &lt;strong&gt;testing.&lt;/strong&gt;'.
98
+ '</h2>';
99
+
100
+ $rendered = $h2->render();
101
+ $this->assertEquals($expected, $rendered);
102
+ }
103
+
104
+ public function testRenderWithFormattedText()
105
+ {
106
+ $h2 =
107
+ H2::create()
108
+ ->appendText(Bold::create()->appendText('Some'))
109
+ ->appendText(' text to be ')
110
+ ->appendText(Italic::create()->appendText('within'))
111
+ ->appendText(' a ')
112
+ ->appendText(Italic::create()->appendText('paragraph'))
113
+ ->appendText(' for ')
114
+ ->appendText(Bold::create()->appendText('testing.'));
115
+
116
+ $expected =
117
+ '<h2>'.
118
+ '<b>Some</b> text to be <i>within</i> a <i>paragraph</i> for <b>testing.</b>'.
119
+ '</h2>';
120
+
121
+ $rendered = $h2->render();
122
+ $this->assertEquals($expected, $rendered);
123
+ }
124
+
125
+ public function testRenderWithLink()
126
+ {
127
+ $h2 =
128
+ H2::create()
129
+ ->appendText('Some ')
130
+ ->appendText(
131
+ Anchor::create()
132
+ ->withHRef('http://foo.com')
133
+ ->appendText('link')
134
+ )
135
+ ->appendText('.');
136
+
137
+ $expected =
138
+ '<h2>'.
139
+ 'Some <a href="http://foo.com">link</a>.'.
140
+ '</h2>';
141
+
142
+ $rendered = $h2->render();
143
+ $this->assertEquals($expected, $rendered);
144
+ }
145
+
146
+ public function testRenderWithNestedFormattedText()
147
+ {
148
+ $h2 =
149
+ H2::create()
150
+ ->appendText(
151
+ Bold::create()
152
+ ->appendText('Some ')
153
+ ->appendText(Italic::create()->appendText('nested formatting'))
154
+ ->appendText('.')
155
+ );
156
+
157
+ $expected =
158
+ '<h2>'.
159
+ '<b>Some <i>nested formatting</i>.</b>'.
160
+ '</h2>';
161
+
162
+ $rendered = $h2->render();
163
+ $this->assertEquals($expected, $rendered);
164
+ }
165
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/HeaderTest.php ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Elements\InstantArticle;
12
+ use Facebook\InstantArticles\Elements\Header;
13
+ use Facebook\InstantArticles\Elements\Time;
14
+ use Facebook\InstantArticles\Elements\Author;
15
+ use Facebook\InstantArticles\Elements\Image;
16
+ use Facebook\InstantArticles\Elements\Caption;
17
+
18
+ class HeaderTest extends \PHPUnit_Framework_TestCase
19
+ {
20
+ public function testCompleteHeader()
21
+ {
22
+ date_default_timezone_set('UTC');
23
+
24
+ $inline =
25
+ '<script>alert("test");</script>';
26
+ $document = new \DOMDocument();
27
+ $fragment = $document->createDocumentFragment();
28
+ $fragment->appendXML($inline);
29
+
30
+ $header =
31
+ Header::create()
32
+ ->withTitle('Big Top Title')
33
+ ->withSubTitle('Smaller SubTitle')
34
+ ->withPublishTime(
35
+ Time::create(Time::PUBLISHED)
36
+ ->withDatetime(
37
+ \DateTime::createFromFormat(
38
+ 'j-M-Y G:i:s',
39
+ '14-Aug-1984 19:30:00'
40
+ )
41
+ )
42
+ )
43
+ ->withModifyTime(
44
+ Time::create(Time::MODIFIED)
45
+ ->withDatetime(
46
+ \DateTime::createFromFormat(
47
+ 'j-M-Y G:i:s',
48
+ '10-Feb-2016 10:00:00'
49
+ )
50
+ )
51
+ )
52
+ ->addAuthor(
53
+ Author::create()
54
+ ->withName('Author One')
55
+ ->withDescription('Passionate coder and mountain biker')
56
+ )
57
+ ->addAuthor(
58
+ Author::create()
59
+ ->withName('Author Two')
60
+ ->withDescription('Weend surfer with heavy weight coding skils')
61
+ ->withURL('http://facebook.com/author')
62
+ )
63
+ ->withKicker('Some kicker of this article')
64
+ ->withCover(
65
+ Image::create()
66
+ ->withURL('https://jpeg.org/images/jpegls-home.jpg')
67
+ ->withCaption(
68
+ Caption::create()
69
+ ->appendText('Some caption to the image')
70
+ )
71
+ )
72
+ ->addAd(
73
+ Ad::create()
74
+ ->withSource('http://foo.com')
75
+ )
76
+ ->addAd(
77
+ Ad::create()
78
+ ->withSource('http://foo.com')
79
+ ->withWidth(350)
80
+ ->withHeight(50)
81
+ ->enableDefaultForReuse()
82
+ )
83
+ ->addAd(
84
+ Ad::create()
85
+ ->withWidth(300)
86
+ ->withHeight(250)
87
+ ->enableDefaultForReuse()
88
+ ->withHTML($fragment)
89
+ );
90
+
91
+ $expected =
92
+ '<header>'.
93
+ '<figure>'.
94
+ '<img src="https://jpeg.org/images/jpegls-home.jpg"/>'.
95
+ '<figcaption>Some caption to the image</figcaption>'.
96
+ '</figure>'.
97
+ '<h1>Big Top Title</h1>'.
98
+ '<h2>Smaller SubTitle</h2>'.
99
+ '<time class="op-published" datetime="1984-08-14T19:30:00+00:00">August 14th, 7:30pm</time>'.
100
+ '<time class="op-modified" datetime="2016-02-10T10:00:00+00:00">February 10th, 10:00am</time>'.
101
+ '<address>'.
102
+ '<a>Author One</a>'.
103
+ 'Passionate coder and mountain biker'.
104
+ '</address>'.
105
+ '<address>'.
106
+ '<a href="http://facebook.com/author" rel="facebook">Author Two</a>'.
107
+ 'Weend surfer with heavy weight coding skils'.
108
+ '</address>'.
109
+ '<h3 class="op-kicker">Some kicker of this article</h3>'.
110
+ '<section class="op-ad-template">'.
111
+ '<figure class="op-ad">'.
112
+ '<iframe src="http://foo.com"></iframe>'.
113
+ '</figure>'.
114
+ '<figure class="op-ad op-ad-default">'.
115
+ '<iframe src="http://foo.com" width="350" height="50"></iframe>'.
116
+ '</figure>'.
117
+ '<figure class="op-ad">'.
118
+ '<iframe width="300" height="250">'.
119
+ '<script>alert("test");</script>'.
120
+ '</iframe>'.
121
+ '</figure>'.
122
+ '</section>'.
123
+ '</header>';
124
+
125
+ $rendered = $header->render();
126
+
127
+ $this->assertEquals($expected, $rendered);
128
+ }
129
+
130
+ public function testHeaderWithSingleDefaultAd()
131
+ {
132
+ $header =
133
+ Header::create()
134
+ ->addAd(
135
+ Ad::create()
136
+ ->withSource('http://foo.com')
137
+ ->withWidth(350)
138
+ ->withHeight(50)
139
+ ->enableDefaultForReuse()
140
+ );
141
+
142
+ // It should not set op-ad-default
143
+ $expected =
144
+ '<header>'.
145
+ '<figure class="op-ad">'.
146
+ '<iframe src="http://foo.com" width="350" height="50"></iframe>'.
147
+ '</figure>'.
148
+ '</header>';
149
+
150
+ $rendered = $header->render();
151
+
152
+ $this->assertEquals($expected, $rendered);
153
+ }
154
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/ImageTest.php ADDED
@@ -0,0 +1,223 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Elements\Image;
12
+ use Facebook\InstantArticles\Elements\Audio;
13
+ use Facebook\InstantArticles\Elements\Caption;
14
+
15
+ class ImageTest extends \PHPUnit_Framework_TestCase
16
+ {
17
+ public function setUp()
18
+ {
19
+ }
20
+
21
+ public function testRenderBasic()
22
+ {
23
+ $image =
24
+ Image::create()
25
+ ->withURL('https://jpeg.org/images/jpegls-home.jpg');
26
+
27
+ $expected =
28
+ '<figure>'.
29
+ '<img src="https://jpeg.org/images/jpegls-home.jpg"/>'.
30
+ '</figure>';
31
+
32
+ $rendered = $image->render();
33
+ $this->assertEquals($expected, $rendered);
34
+ }
35
+
36
+ public function testRenderWithCaption()
37
+ {
38
+ $image =
39
+ Image::create()
40
+ ->withURL('https://jpeg.org/images/jpegls-home.jpg')
41
+ ->withCaption(
42
+ Caption::create()
43
+ ->appendText('Some caption to the image')
44
+ );
45
+
46
+ $expected =
47
+ '<figure>'.
48
+ '<img src="https://jpeg.org/images/jpegls-home.jpg"/>'.
49
+ '<figcaption>Some caption to the image</figcaption>'.
50
+ '</figure>';
51
+
52
+ $rendered = $image->render();
53
+ $this->assertEquals($expected, $rendered);
54
+ }
55
+
56
+ public function testRenderWithAttributionCaption()
57
+ {
58
+ $image =
59
+ Image::create()
60
+ ->withURL('https://jpeg.org/images/jpegls-home.jpg')
61
+ ->withCaption(
62
+ Caption::create()
63
+ ->withTitle('Title of Image caption')
64
+ ->withCredit('Some caption to the image')
65
+ ->withPostion(Caption::POSITION_BELOW)
66
+ );
67
+
68
+ $expected =
69
+ '<figure>'.
70
+ '<img src="https://jpeg.org/images/jpegls-home.jpg"/>'.
71
+ '<figcaption class="op-vertical-below">'.
72
+ '<h1>Title of Image caption</h1>'.
73
+ '<cite>Some caption to the image</cite>'.
74
+ '</figcaption>'.
75
+ '</figure>';
76
+
77
+ $rendered = $image->render();
78
+ $this->assertEquals($expected, $rendered);
79
+ }
80
+
81
+ public function testRenderWithLike()
82
+ {
83
+ $image =
84
+ Image::create()
85
+ ->withURL('https://jpeg.org/images/jpegls-home.jpg')
86
+ ->withCaption(
87
+ Caption::create()
88
+ ->appendText('Some caption to the image')
89
+ )
90
+ ->enableLike();
91
+
92
+ $expected =
93
+ '<figure data-feedback="fb:likes">'.
94
+ '<img src="https://jpeg.org/images/jpegls-home.jpg"/>'.
95
+ '<figcaption>Some caption to the image</figcaption>'.
96
+ '</figure>';
97
+
98
+ $rendered = $image->render();
99
+ $this->assertEquals($expected, $rendered);
100
+ }
101
+
102
+ public function testRenderWithComments()
103
+ {
104
+ $image =
105
+ Image::create()
106
+ ->withURL('https://jpeg.org/images/jpegls-home.jpg')
107
+ ->withCaption(
108
+ Caption::create()
109
+ ->appendText('Some caption to the image')
110
+ )
111
+ ->enableComments();
112
+
113
+ $expected =
114
+ '<figure data-feedback="fb:comments">'.
115
+ '<img src="https://jpeg.org/images/jpegls-home.jpg"/>'.
116
+ '<figcaption>Some caption to the image</figcaption>'.
117
+ '</figure>';
118
+
119
+ $rendered = $image->render();
120
+ $this->assertEquals($expected, $rendered);
121
+ }
122
+
123
+ public function testRenderWithLikeAndComments()
124
+ {
125
+ $image =
126
+ Image::create()
127
+ ->withURL('https://jpeg.org/images/jpegls-home.jpg')
128
+ ->withCaption(
129
+ Caption::create()
130
+ ->appendText('Some caption to the image')
131
+ )
132
+ ->enableLike()
133
+ ->enableComments();
134
+
135
+ $expected =
136
+ '<figure data-feedback="fb:likes,fb:comments">'.
137
+ '<img src="https://jpeg.org/images/jpegls-home.jpg"/>'.
138
+ '<figcaption>Some caption to the image</figcaption>'.
139
+ '</figure>';
140
+
141
+ $rendered = $image->render();
142
+ $this->assertEquals($expected, $rendered);
143
+ }
144
+
145
+ public function testRenderWithFullscreen()
146
+ {
147
+ $image =
148
+ Image::create()
149
+ ->withURL('https://jpeg.org/images/jpegls-home.jpg')
150
+ ->withPresentation(Image::FULLSCREEN);
151
+
152
+ $expected =
153
+ '<figure data-mode="fullscreen">'.
154
+ '<img src="https://jpeg.org/images/jpegls-home.jpg"/>'.
155
+ '</figure>';
156
+
157
+ $rendered = $image->render();
158
+ $this->assertEquals($expected, $rendered);
159
+ }
160
+
161
+ public function testRenderWithGeotag()
162
+ {
163
+ $script =
164
+ '{'.
165
+ '"type": "Feature",'.
166
+ '"geometry": {'.
167
+ '"type": "Point",'.
168
+ '"coordinates": [23.166667, 89.216667]'.
169
+ '},'.
170
+ '"properties": {'.
171
+ '"title": "Jessore, Bangladesh",'.
172
+ '"radius": 750000,'.
173
+ '"pivot": true,'.
174
+ '"style": "satellite"'.
175
+ '}'.
176
+ '}';
177
+
178
+ $image =
179
+ Image::create()
180
+ ->withURL('https://jpeg.org/images/jpegls-home.jpg')
181
+ ->withGeoTag(GeoTag::create()->withScript($script));
182
+
183
+ $expected =
184
+ '<figure>'.
185
+ '<img src="https://jpeg.org/images/jpegls-home.jpg"/>'.
186
+ '<script type="application/json" class="op-geotag">'.
187
+ $script.
188
+ '</script>'.
189
+ '</figure>';
190
+
191
+ $rendered = $image->render();
192
+ $this->assertEquals($expected, $rendered);
193
+ }
194
+
195
+ public function testRenderWithAudio()
196
+ {
197
+ $audio =
198
+ Audio::create()
199
+ ->withURL('http://foo.com/mp3')
200
+ ->withTitle('audio title')
201
+ ->enableMuted()
202
+ ->enableAutoplay();
203
+
204
+ $expected_audio =
205
+ '<audio title="audio title" autoplay="autoplay" muted="muted">'.
206
+ '<source src="http://foo.com/mp3"/>'.
207
+ '</audio>';
208
+
209
+ $image =
210
+ Image::create()
211
+ ->withURL('https://jpeg.org/images/jpegls-home.jpg')
212
+ ->withAudio($audio);
213
+
214
+ $expected =
215
+ '<figure>'.
216
+ '<img src="https://jpeg.org/images/jpegls-home.jpg"/>'.
217
+ $expected_audio.
218
+ '</figure>';
219
+
220
+ $rendered = $image->render();
221
+ $this->assertEquals($expected, $rendered);
222
+ }
223
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/InstantArticleTest.php ADDED
@@ -0,0 +1,217 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Elements\Element;
12
+ use Facebook\InstantArticles\Elements\InstantArticle;
13
+ use Facebook\InstantArticles\Elements\Header;
14
+ use Facebook\InstantArticles\Elements\Time;
15
+ use Facebook\InstantArticles\Elements\Author;
16
+ use Facebook\InstantArticles\Elements\Image;
17
+ use Facebook\InstantArticles\Elements\Caption;
18
+ use Facebook\InstantArticles\Elements\Paragraph;
19
+ use Facebook\InstantArticles\Elements\SlideShow;
20
+ use Facebook\InstantArticles\Elements\Analytics;
21
+ use Facebook\InstantArticles\Elements\Ad;
22
+ use Facebook\InstantArticles\Elements\Footer;
23
+
24
+ class InstantArticleTest extends \PHPUnit_Framework_TestCase
25
+ {
26
+ /**
27
+ * @var InstantArticle
28
+ */
29
+ private $article;
30
+ public function setUp()
31
+ {
32
+ date_default_timezone_set('UTC');
33
+
34
+ $inline =
35
+ '<h1>Some custom code</h1>'.
36
+ '<script>alert("test");</script>';
37
+ $document = new \DOMDocument();
38
+ $fragment = $document->createDocumentFragment();
39
+ $fragment->appendXML($inline);
40
+
41
+ $this->article =
42
+ InstantArticle::create()
43
+ ->withCanonicalUrl('http://foo.com/article.html')
44
+ ->withStyle('myarticlestyle')
45
+ ->withHeader(
46
+ Header::create()
47
+ ->withTitle('Big Top Title')
48
+ ->withSubTitle('Smaller SubTitle')
49
+ ->withPublishTime(
50
+ Time::create(Time::PUBLISHED)
51
+ ->withDatetime(
52
+ \DateTime::createFromFormat(
53
+ 'j-M-Y G:i:s',
54
+ '14-Aug-1984 19:30:00'
55
+ )
56
+ )
57
+ )
58
+ ->withModifyTime(
59
+ Time::create(Time::MODIFIED)
60
+ ->withDatetime(
61
+ \DateTime::createFromFormat(
62
+ 'j-M-Y G:i:s',
63
+ '10-Feb-2016 10:00:00'
64
+ )
65
+ )
66
+ )
67
+ ->addAuthor(
68
+ Author::create()
69
+ ->withName('Author Name')
70
+ ->withDescription('Author more detailed description')
71
+ )
72
+ ->addAuthor(
73
+ Author::create()
74
+ ->withName('Author in FB')
75
+ ->withDescription('Author user in facebook')
76
+ ->withURL('http://facebook.com/author')
77
+ )
78
+ ->withKicker('Some kicker of this article')
79
+ ->withCover(
80
+ Image::create()
81
+ ->withURL('https://jpeg.org/images/jpegls-home.jpg')
82
+ ->withCaption(
83
+ Caption::create()
84
+ ->appendText('Some caption to the image')
85
+ )
86
+ )
87
+ )
88
+ // Paragraph1
89
+ ->addChild(
90
+ Paragraph::create()
91
+ ->appendText('Some text to be within a paragraph for testing.')
92
+ )
93
+
94
+ // Paragraph2
95
+ ->addChild(
96
+ Paragraph::create()
97
+ ->appendText('Other text to be within a second paragraph for testing.')
98
+ )
99
+
100
+ // Slideshow
101
+ ->addChild(
102
+ SlideShow::create()
103
+ ->addImage(
104
+ Image::create()
105
+ ->withURL('https://jpeg.org/images/jpegls-home.jpg')
106
+ )
107
+ ->addImage(
108
+ Image::create()
109
+ ->withURL('https://jpeg.org/images/jpegls-home2.jpg')
110
+ )
111
+ ->addImage(
112
+ Image::create()
113
+ ->withURL('https://jpeg.org/images/jpegls-home3.jpg')
114
+ )
115
+ )
116
+
117
+ // Paragraph3
118
+ ->addChild(
119
+ Paragraph::create()
120
+ ->appendText('Some text to be within a paragraph for testing.')
121
+ )
122
+
123
+ // Ad
124
+ ->addChild(
125
+ Ad::create()
126
+ ->withSource('http://foo.com')
127
+ )
128
+
129
+ // Paragraph4
130
+ ->addChild(
131
+ Paragraph::create()
132
+ ->appendText('Other text to be within a second paragraph for testing.')
133
+ )
134
+
135
+ // Analytics
136
+ ->addChild(
137
+ Analytics::create()
138
+ ->withHTML($fragment)
139
+ )
140
+
141
+ // Footer
142
+ ->withFooter(
143
+ Footer::create()
144
+ ->withCredits('Some plaintext credits.')
145
+ );
146
+ }
147
+
148
+ public function testRender()
149
+ {
150
+
151
+ $expected =
152
+ '<!doctype html>'.
153
+ '<html>'.
154
+ '<head>'.
155
+ '<link rel="canonical" href="http://foo.com/article.html"/>'.
156
+ '<meta charset="utf-8"/>'.
157
+ '<meta property="op:generator" content="facebook-instant-articles-sdk-php"/>'.
158
+ '<meta property="op:generator:version" content="'.InstantArticle::CURRENT_VERSION.'"/>'.
159
+ '<meta property="op:markup_version" content="v1.0"/>'.
160
+ '<meta property="fb:use_automatic_ad_placement" content="true"/>'.
161
+ '<meta property="fb:article_style" content="myarticlestyle"/>'.
162
+ '</head>'.
163
+ '<body>'.
164
+ '<article>'.
165
+ '<header>'.
166
+ '<figure>'.
167
+ '<img src="https://jpeg.org/images/jpegls-home.jpg"/>'.
168
+ '<figcaption>Some caption to the image</figcaption>'.
169
+ '</figure>'.
170
+ '<h1>Big Top Title</h1>'.
171
+ '<h2>Smaller SubTitle</h2>'.
172
+ '<time class="op-published" datetime="1984-08-14T19:30:00+00:00">August 14th, 7:30pm</time>'.
173
+ '<time class="op-modified" datetime="2016-02-10T10:00:00+00:00">February 10th, 10:00am</time>'.
174
+ '<address>'.
175
+ '<a>Author Name</a>'.
176
+ 'Author more detailed description'.
177
+ '</address>'.
178
+ '<address>'.
179
+ '<a href="http://facebook.com/author" rel="facebook">Author in FB</a>'.
180
+ 'Author user in facebook'.
181
+ '</address>'.
182
+ '<h3 class="op-kicker">Some kicker of this article</h3>'.
183
+ '</header>'.
184
+ '<p>Some text to be within a paragraph for testing.</p>'.
185
+ '<p>Other text to be within a second paragraph for testing.</p>'.
186
+ '<figure class="op-slideshow">'.
187
+ '<figure>'.
188
+ '<img src="https://jpeg.org/images/jpegls-home.jpg"/>'.
189
+ '</figure>'.
190
+ '<figure>'.
191
+ '<img src="https://jpeg.org/images/jpegls-home2.jpg"/>'.
192
+ '</figure>'.
193
+ '<figure>'.
194
+ '<img src="https://jpeg.org/images/jpegls-home3.jpg"/>'.
195
+ '</figure>'.
196
+ '</figure>'.
197
+ '<p>Some text to be within a paragraph for testing.</p>'.
198
+ '<figure class="op-ad">'.
199
+ '<iframe src="http://foo.com"></iframe>'.
200
+ '</figure>'.
201
+ '<p>Other text to be within a second paragraph for testing.</p>'.
202
+ '<figure class="op-tracker">'.
203
+ '<iframe>'.
204
+ '<h1>Some custom code</h1>'.
205
+ '<script>alert("test");</script>'.
206
+ '</iframe>'.
207
+ '</figure>'.
208
+ '<footer>'.
209
+ '<aside>Some plaintext credits.</aside>'.
210
+ '</footer>'.
211
+ '</article>'.
212
+ '</body>'.
213
+ '</html>';
214
+
215
+ $this->assertEquals($expected, $this->article->render());
216
+ }
217
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/InteractiveTest.php ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
10
+
11
+ use Facebook\InstantArticles\Elements\Caption;
12
+ use Facebook\InstantArticles\Elements\Interactive;
13
+
14
+ class InteractiveTest extends \PHPUnit_Framework_TestCase
15
+ {
16
+ public function setUp()
17
+ {
18
+ }
19
+
20
+ public function testRenderBasic()
21
+ {
22
+ $interactive =
23
+ Interactive::create()
24
+ ->withSource('http://foo.com/interactive-graphic');
25
+
26
+ $expected =
27
+ '<figure class="op-interactive">'.
28
+ '<iframe src="http://foo.com/interactive-graphic"></iframe>'.
29
+ '</figure>';
30
+
31
+ $rendered = $interactive->render();
32
+ $this->assertEquals($expected, $rendered);
33
+ }
34
+
35
+
36
+ public function testRenderBasicWithCaption()
37
+ {
38
+ $social_embed =
39
+ interactive::create()
40
+ ->withSource('http://foo.com/interactive-graphic')
41
+ ->withCaption(
42
+ Caption::create()
43
+ ->appendText('Some caption to the interactive graphic')
44
+ );
45
+
46
+ $expected =
47
+ '<figure class="op-interactive">'.
48
+ '<iframe src="http://foo.com/interactive-graphic"></iframe>'.
49
+ '<figcaption>Some caption to the interactive graphic</figcaption>'.
50
+ '</figure>';
51
+
52
+ $rendered = $social_embed->render();
53
+ $this->assertEquals($expected, $rendered);
54
+ }
55
+
56
+ public function testRenderBasicWithHeight()
57
+ {
58
+ $interactive =
59
+ Interactive::create()
60
+ ->withSource('http://foo.com/interactive-graphic')
61
+ ->withHeight(640);
62
+
63
+ $expected =
64
+ '<figure class="op-interactive">'.
65
+ '<iframe src="http://foo.com/interactive-graphic" height="640"></iframe>'.
66
+ '</figure>';
67
+
68
+ $rendered = $interactive->render();
69
+ $this->assertEquals($expected, $rendered);
70
+ }
71
+
72
+ public function testRenderBasicWithColumnWidth()
73
+ {
74
+ $interactive =
75
+ Interactive::create()
76
+ ->withSource('http://foo.com/interactive-graphic')
77
+ ->withWidth(Interactive::COLUMN_WIDTH);
78
+
79
+ $expected =
80
+ '<figure class="op-interactive">'.
81
+ '<iframe src="http://foo.com/interactive-graphic" class="column-width"></iframe>'.
82
+ '</figure>';
83
+
84
+ $rendered = $interactive->render();
85
+ $this->assertEquals($expected, $rendered);
86
+ }
87
+
88
+ public function testRenderBasicWithNoMargin()
89
+ {
90
+ $interactive =
91
+ Interactive::create()
92
+ ->withSource('http://foo.com/interactive-graphic')
93
+ ->withWidth(Interactive::NO_MARGIN);
94
+
95
+ $expected =
96
+ '<figure class="op-interactive">'.
97
+ '<iframe src="http://foo.com/interactive-graphic" class="no-margin"></iframe>'.
98
+ '</figure>';
99
+
100
+ $rendered = $interactive->render();
101
+ $this->assertEquals($expected, $rendered);
102
+ }
103
+
104
+ public function testRenderInlineWithHeightAndWidth()
105
+ {
106
+ $inline =
107
+ '<h1>Some custom code</h1>'.
108
+ '<script>alert("test");</script>';
109
+ $document = new \DOMDocument();
110
+ $fragment = $document->createDocumentFragment();
111
+ $fragment->appendXML($inline);
112
+
113
+ $interactive =
114
+ Interactive::create()
115
+ ->withHTML($fragment)
116
+ ->withHeight(640)
117
+ ->withWidth(Interactive::NO_MARGIN);
118
+
119
+ $expected =
120
+ '<figure class="op-interactive">'.
121
+ '<iframe class="no-margin" height="640">'.
122
+ '<h1>Some custom code</h1>'.
123
+ '<script>alert("test");</script>'.
124
+ '</iframe>'.
125
+ '</figure>';
126
+
127
+ $rendered = $interactive->render();
128
+ $this->assertEquals($expected, $rendered);
129
+ }
130
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/ListElementTest.php ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Elements\ListElement;
12
+
13
+ class ListElementTest extends \PHPUnit_Framework_TestCase
14
+ {
15
+ public function setUp()
16
+ {
17
+ }
18
+
19
+ public function testRenderOrdered()
20
+ {
21
+ $list =
22
+ ListElement::createOrdered()
23
+ ->addItem('Item 1')
24
+ ->addItem('Item 2')
25
+ ->addItem('Item 3');
26
+
27
+ $expected =
28
+ '<ol>'.
29
+ '<li>Item 1</li>'.
30
+ '<li>Item 2</li>'.
31
+ '<li>Item 3</li>'.
32
+ '</ol>';
33
+
34
+ $rendered = $list->render();
35
+ $this->assertEquals($expected, $rendered);
36
+ }
37
+
38
+ public function testRenderOrderedWithAllItems()
39
+ {
40
+ $list =
41
+ ListElement::createOrdered()
42
+ ->withItems(array('Item 1', 'Item 2', 'Item 3'));
43
+
44
+ $expected =
45
+ '<ol>'.
46
+ '<li>Item 1</li>'.
47
+ '<li>Item 2</li>'.
48
+ '<li>Item 3</li>'.
49
+ '</ol>';
50
+
51
+ $rendered = $list->render();
52
+ $this->assertEquals($expected, $rendered);
53
+ }
54
+
55
+ public function testRenderUnordered()
56
+ {
57
+ $list =
58
+ ListElement::createUnordered()
59
+ ->addItem('Item 1')
60
+ ->addItem('Item 2')
61
+ ->addItem('Item 3');
62
+
63
+ $expected =
64
+ '<ul>'.
65
+ '<li>Item 1</li>'.
66
+ '<li>Item 2</li>'.
67
+ '<li>Item 3</li>'.
68
+ '</ul>';
69
+
70
+ $rendered = $list->render();
71
+ $this->assertEquals($expected, $rendered);
72
+ }
73
+
74
+ public function testRenderUnorderedWithAllItems()
75
+ {
76
+ $list =
77
+ ListElement::createUnordered()
78
+ ->withItems(array('Item 1', 'Item 2', 'Item 3'));
79
+
80
+ $expected =
81
+ '<ul>'.
82
+ '<li>Item 1</li>'.
83
+ '<li>Item 2</li>'.
84
+ '<li>Item 3</li>'.
85
+ '</ul>';
86
+
87
+ $rendered = $list->render();
88
+ $this->assertEquals($expected, $rendered);
89
+ }
90
+
91
+ public function testRenderWithSingleContainerUnordered()
92
+ {
93
+ $list =
94
+ ListElement::createUnordered()
95
+ ->addItem(ListItem::create()->withText(Paragraph::create()->appendText('Item 1')))
96
+ ->addItem(ListItem::create()->withText(Div::create()->appendText('Item 2')))
97
+ ->addItem(ListItem::create()->withText(Span::create()->appendText('Item 3')));
98
+
99
+ $expected =
100
+ '<ul>'.
101
+ '<li><p>Item 1</p></li>'.
102
+ '<li><div>Item 2</div></li>'.
103
+ '<li><span>Item 3</span></li>'.
104
+ '</ul>';
105
+
106
+ $rendered = $list->render();
107
+ $this->assertEquals($expected, $rendered);
108
+ }
109
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/MapTest.php ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Elements\Map;
12
+ use Facebook\InstantArticles\Elements\GeoTag;
13
+ use Facebook\InstantArticles\Elements\Caption;
14
+
15
+ class MapTest extends \PHPUnit_Framework_TestCase
16
+ {
17
+ public function setUp()
18
+ {
19
+ }
20
+
21
+ public function testRenderWithGeotag()
22
+ {
23
+ $script =
24
+ '{'.
25
+ '"type": "Feature",'.
26
+ '"geometry": {'.
27
+ '"type": "Point",'.
28
+ '"coordinates": [23.166667, 89.216667]'.
29
+ '},'.
30
+ '"properties": {'.
31
+ '"title": "Jessore, Bangladesh",'.
32
+ '"radius": 750000,'.
33
+ '"pivot": true,'.
34
+ '"style": "satellite"'.
35
+ '}'.
36
+ '}';
37
+
38
+ $map =
39
+ Map::create()
40
+ ->withGeoTag(GeoTag::create()->withScript($script));
41
+
42
+ $expected =
43
+ '<figure class="op-map">'.
44
+ '<script type="application/json" class="op-geotag">'.
45
+ $script.
46
+ '</script>'.
47
+ '</figure>';
48
+
49
+ $rendered = $map->render();
50
+ $this->assertEquals($expected, $rendered);
51
+ }
52
+
53
+ public function testRenderWithGeotagAndCaption()
54
+ {
55
+ $script =
56
+ '{'.
57
+ '"type": "Feature",'.
58
+ '"geometry": {'.
59
+ '"type": "Point",'.
60
+ '"coordinates": [23.166667, 89.216667]'.
61
+ '},'.
62
+ '"properties": {'.
63
+ '"title": "Jessore, Bangladesh",'.
64
+ '"radius": 750000,'.
65
+ '"pivot": true,'.
66
+ '"style": "satellite"'.
67
+ '}'.
68
+ '}';
69
+
70
+ $map =
71
+ Map::create()
72
+ ->withGeoTag(GeoTag::create()->withScript($script))
73
+ ->withCaption(
74
+ Caption::create()
75
+ ->withTitle('Title of Image caption')
76
+ ->withCredit('Some caption to the image')
77
+ ->withPostion(Caption::POSITION_BELOW)
78
+ );
79
+
80
+ $expected =
81
+ '<figure class="op-map">'.
82
+ '<script type="application/json" class="op-geotag">'.
83
+ $script.
84
+ '</script>'.
85
+ '<figcaption class="op-vertical-below">'.
86
+ '<h1>Title of Image caption</h1>'.
87
+ '<cite>Some caption to the image</cite>'.
88
+ '</figcaption>'.
89
+ '</figure>';
90
+
91
+ $rendered = $map->render();
92
+ $this->assertEquals($expected, $rendered);
93
+ }
94
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/ParagraphTest.php ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Elements\Paragraph;
12
+ use Facebook\InstantArticles\Elements\Bold;
13
+ use Facebook\InstantArticles\Elements\LineBreak;
14
+ use Facebook\InstantArticles\Elements\Italic;
15
+ use Facebook\InstantArticles\Elements\Anchor;
16
+
17
+ class ParagraphTest extends \PHPUnit_Framework_TestCase
18
+ {
19
+ public function setUp()
20
+ {
21
+ }
22
+
23
+ public function testRenderBasic()
24
+ {
25
+ $paragraph =
26
+ Paragraph::create()
27
+ ->appendText('Some text to be within a paragraph for testing.');
28
+
29
+ $expected =
30
+ '<p>'.
31
+ 'Some text to be within a paragraph for testing.'.
32
+ '</p>';
33
+
34
+ $rendered = $paragraph->render();
35
+ $this->assertEquals($expected, $rendered);
36
+ }
37
+
38
+ public function testRenderWithUnescapedHTML()
39
+ {
40
+ $paragraph =
41
+ Paragraph::create()
42
+ ->appendText(
43
+ '<b>Some</b> text to be <i>within</i> a <em>paragraph</em> for <strong>testing.</strong>'
44
+ );
45
+
46
+ $expected =
47
+ '<p>'.
48
+ '&lt;b&gt;Some&lt;/b&gt; text to be &lt;i&gt;within&lt;/i&gt; '.
49
+ 'a &lt;em&gt;paragraph&lt;/em&gt; for &lt;strong&gt;testing.&lt;/strong&gt;'.
50
+ '</p>';
51
+
52
+ $rendered = $paragraph->render();
53
+ $this->assertEquals($expected, $rendered);
54
+ }
55
+
56
+ public function testRenderWithFormattedText()
57
+ {
58
+ $paragraph =
59
+ Paragraph::create()
60
+ ->appendText(Bold::create()->appendText('Some'))
61
+ ->appendText(' text to be ')
62
+ ->appendText(Italic::create()->appendText('within'))
63
+ ->appendText(' a ')
64
+ ->appendText(Italic::create()->appendText('paragraph'))
65
+ ->appendText(' for ')
66
+ ->appendText(Bold::create()->appendText('testing.'));
67
+
68
+ $expected =
69
+ '<p>'.
70
+ '<b>Some</b> text to be <i>within</i> a <i>paragraph</i> for <b>testing.</b>'.
71
+ '</p>';
72
+
73
+ $rendered = $paragraph->render();
74
+ $this->assertEquals($expected, $rendered);
75
+ }
76
+
77
+ public function testRenderWithLineBreak()
78
+ {
79
+ $paragraph =
80
+ Paragraph::create()
81
+ ->appendText('Some')
82
+ ->appendText(LineBreak::create())
83
+ ->appendText('line break');
84
+
85
+ $expected =
86
+ '<p>'.
87
+ 'Some'.
88
+ '<br/>line break'.
89
+ '</p>';
90
+
91
+ $rendered = $paragraph->render();
92
+ $this->assertEquals($expected, $rendered);
93
+ }
94
+
95
+ public function testRenderWithLink()
96
+ {
97
+ $paragraph =
98
+ Paragraph::create()
99
+ ->appendText('Some ')
100
+ ->appendText(
101
+ Anchor::create()
102
+ ->withHRef('http://foo.com')
103
+ ->appendText('link')
104
+ )
105
+ ->appendText('.');
106
+
107
+ $expected =
108
+ '<p>'.
109
+ 'Some <a href="http://foo.com">link</a>.'.
110
+ '</p>';
111
+
112
+ $rendered = $paragraph->render();
113
+ $this->assertEquals($expected, $rendered);
114
+ }
115
+
116
+ public function testRenderWithNestedFormattedText()
117
+ {
118
+ $paragraph =
119
+ Paragraph::create()
120
+ ->appendText(
121
+ Bold::create()
122
+ ->appendText('Some ')
123
+ ->appendText(Italic::create()->appendText('nested formatting'))
124
+ ->appendText('.')
125
+ );
126
+
127
+
128
+ $expected =
129
+ '<p>'.
130
+ '<b>Some <i>nested formatting</i>.</b>'.
131
+ '</p>';
132
+
133
+ $rendered = $paragraph->render();
134
+ $this->assertEquals($expected, $rendered);
135
+ }
136
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/PullquoteTest.php ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Elements\Pullquote;
12
+
13
+ class PullquoteTest extends \PHPUnit_Framework_TestCase
14
+ {
15
+ public function setUp()
16
+ {
17
+ }
18
+
19
+ public function testRenderBasic()
20
+ {
21
+ $analytics =
22
+ Pullquote::create()
23
+ ->appendText('Some text to be within an aside for testing.');
24
+
25
+ $expected =
26
+ '<aside>'.
27
+ 'Some text to be within an aside for testing.'.
28
+ '</aside>';
29
+
30
+ $rendered = $analytics->render();
31
+ $this->assertEquals($expected, $rendered);
32
+ }
33
+
34
+ public function testRenderWithBoldStrongItalicEm()
35
+ {
36
+ $analytics =
37
+ Pullquote::create()
38
+ ->appendText(Bold::create()->appendText('Some'))
39
+ ->appendText(' text to be ')
40
+ ->appendText(Italic::create()->appendText('within'))
41
+ ->appendText(' an ')
42
+ ->appendText(Italic::create()->appendText('aside'))
43
+ ->appendText(' for ')
44
+ ->appendText(Bold::create()->appendText('testing.'));
45
+
46
+ $expected =
47
+ '<aside>'.
48
+ '<b>Some</b> text to be <i>within</i> an <i>aside</i> for <b>testing.</b>'.
49
+ '</aside>';
50
+
51
+ $rendered = $analytics->render();
52
+ $this->assertEquals($expected, $rendered);
53
+ }
54
+
55
+ public function testRenderWithAttribution()
56
+ {
57
+ $analytics =
58
+ Pullquote::create()
59
+ ->appendText(Bold::create()->appendText('Some'))
60
+ ->appendText(' text to be ')
61
+ ->appendText(Italic::create()->appendText('within'))
62
+ ->appendText(' an ')
63
+ ->appendText(Italic::create()->appendText('aside'))
64
+ ->appendText(' for ')
65
+ ->appendText(Bold::create()->appendText('testing.'))
66
+ ->withAttribution('Some attribution');
67
+
68
+ $expected =
69
+ '<aside>'.
70
+ '<b>Some</b> text to be <i>within</i> an <i>aside</i> for <b>testing.</b>'.
71
+ '<cite>Some attribution</cite>'.
72
+ '</aside>';
73
+
74
+ $rendered = $analytics->render();
75
+ $this->assertEquals($expected, $rendered);
76
+ }
77
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/RelatedArticlesTest.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Elements\RelatedArticles;
12
+ use Facebook\InstantArticles\Elements\RelatedItem;
13
+
14
+ class RelatedArticlesTest extends \PHPUnit_Framework_TestCase
15
+ {
16
+ public function setUp()
17
+ {
18
+ }
19
+
20
+ public function testRenderBasic()
21
+ {
22
+ $element =
23
+ RelatedArticles::create()
24
+ ->addRelated(RelatedItem::create()->withURL('http://related.com/1'))
25
+ ->addRelated(RelatedItem::create()->withURL('http://related.com/2'))
26
+ ->addRelated(RelatedItem::create()->withURL('http://sponsored.com/1')->enableSponsored());
27
+
28
+ $expected =
29
+ '<ul class="op-related-articles">'.
30
+ '<li><a href="http://related.com/1"></a></li>'.
31
+ '<li><a href="http://related.com/2"></a></li>'.
32
+ '<li data-sponsored="true"><a href="http://sponsored.com/1"></a></li>'.
33
+ '</ul>';
34
+
35
+ $rendered = $element->render();
36
+ $this->assertEquals($expected, $rendered);
37
+ }
38
+
39
+ public function testRenderWithTitle()
40
+ {
41
+ $element =
42
+ RelatedArticles::create()
43
+ ->withTitle('Title for Related')
44
+ ->addRelated(RelatedItem::create()->withURL('http://related.com/1'))
45
+ ->addRelated(RelatedItem::create()->withURL('http://related.com/2'))
46
+ ->addRelated(RelatedItem::create()->withURL('http://sponsored.com/1')->enableSponsored());
47
+
48
+ $expected =
49
+ '<ul class="op-related-articles" title="Title for Related">'.
50
+ '<li><a href="http://related.com/1"></a></li>'.
51
+ '<li><a href="http://related.com/2"></a></li>'.
52
+ '<li data-sponsored="true"><a href="http://sponsored.com/1"></a></li>'.
53
+ '</ul>';
54
+
55
+ $rendered = $element->render();
56
+ $this->assertEquals($expected, $rendered);
57
+ }
58
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/SlideshowTest.php ADDED
@@ -0,0 +1,197 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Elements\Slideshow;
12
+ use Facebook\InstantArticles\Elements\Audio;
13
+ use Facebook\InstantArticles\Elements\Image;
14
+ use Facebook\InstantArticles\Elements\Caption;
15
+
16
+ class SlideshowTest extends \PHPUnit_Framework_TestCase
17
+ {
18
+ public function setUp()
19
+ {
20
+ }
21
+
22
+ public function testRenderBasic()
23
+ {
24
+ $slideshow =
25
+ SlideShow::create()
26
+ ->addImage(Image::create()->withURL('https://jpeg.org/images/jpegls-home.jpg'))
27
+ ->addImage(Image::create()->withURL('https://jpeg.org/images/jpegls-home2.jpg'))
28
+ ->addImage(Image::create()->withURL('https://jpeg.org/images/jpegls-home3.jpg'));
29
+
30
+ $expected =
31
+ '<figure class="op-slideshow">'.
32
+ '<figure>'.
33
+ '<img src="https://jpeg.org/images/jpegls-home.jpg"/>'.
34
+ '</figure>'.
35
+ '<figure>'.
36
+ '<img src="https://jpeg.org/images/jpegls-home2.jpg"/>'.
37
+ '</figure>'.
38
+ '<figure>'.
39
+ '<img src="https://jpeg.org/images/jpegls-home3.jpg"/>'.
40
+ '</figure>'.
41
+ '</figure>';
42
+
43
+ $rendered = $slideshow->render();
44
+ $this->assertEquals($expected, $rendered);
45
+ }
46
+
47
+ public function testRenderWithLikeAndComments()
48
+ {
49
+ $slideshow =
50
+ SlideShow::create()
51
+ ->addImage(
52
+ Image::create()
53
+ ->withURL('https://jpeg.org/images/jpegls-home.jpg')
54
+ ->enableLike()
55
+ )
56
+ ->addImage(
57
+ Image::create()
58
+ ->withURL('https://jpeg.org/images/jpegls-home2.jpg')
59
+ ->enableComments()
60
+ )
61
+ ->addImage(
62
+ Image::create()
63
+ ->withURL('https://jpeg.org/images/jpegls-home3.jpg')
64
+ ->enableComments()
65
+ ->enableLike()
66
+ );
67
+
68
+ $expected =
69
+ '<figure class="op-slideshow">'.
70
+ '<figure data-feedback="fb:likes">'.
71
+ '<img src="https://jpeg.org/images/jpegls-home.jpg"/>'.
72
+ '</figure>'.
73
+ '<figure data-feedback="fb:comments">'.
74
+ '<img src="https://jpeg.org/images/jpegls-home2.jpg"/>'.
75
+ '</figure>'.
76
+ '<figure data-feedback="fb:likes,fb:comments">'.
77
+ '<img src="https://jpeg.org/images/jpegls-home3.jpg"/>'.
78
+ '</figure>'.
79
+ '</figure>';
80
+
81
+ $rendered = $slideshow->render();
82
+ $this->assertEquals($expected, $rendered);
83
+ }
84
+
85
+ public function testRenderWithCaption()
86
+ {
87
+ $slideshow =
88
+ SlideShow::create()
89
+ ->addImage(Image::create()->withURL('https://jpeg.org/images/jpegls-home.jpg'))
90
+ ->addImage(Image::create()->withURL('https://jpeg.org/images/jpegls-home2.jpg'))
91
+ ->addImage(Image::create()->withURL('https://jpeg.org/images/jpegls-home3.jpg'))
92
+ ->withCaption(
93
+ Caption::create()
94
+ ->appendText('Some caption to the slideshow')
95
+ );
96
+
97
+ $expected =
98
+ '<figure class="op-slideshow">'.
99
+ '<figure>'.
100
+ '<img src="https://jpeg.org/images/jpegls-home.jpg"/>'.
101
+ '</figure>'.
102
+ '<figure>'.
103
+ '<img src="https://jpeg.org/images/jpegls-home2.jpg"/>'.
104
+ '</figure>'.
105
+ '<figure>'.
106
+ '<img src="https://jpeg.org/images/jpegls-home3.jpg"/>'.
107
+ '</figure>'.
108
+ '<figcaption>Some caption to the slideshow</figcaption>'.
109
+ '</figure>';
110
+
111
+ $rendered = $slideshow->render();
112
+ $this->assertEquals($expected, $rendered);
113
+ }
114
+
115
+ public function testRenderWithGeotag()
116
+ {
117
+ $geotag =
118
+ '{'.
119
+ '"type": "Feature",'.
120
+ '"geometry": {'.
121
+ '"type": "Point",'.
122
+ '"coordinates": [23.166667, 89.216667]'.
123
+ '},'.
124
+ '"properties": {'.
125
+ '"title": "Jessore, Bangladesh",'.
126
+ '"radius": 750000,'.
127
+ '"pivot": true,'.
128
+ '"style": "satellite"'.
129
+ '}'.
130
+ '}';
131
+
132
+ $slideshow =
133
+ SlideShow::create()
134
+ ->addImage(Image::create()->withURL('https://jpeg.org/images/jpegls-home.jpg'))
135
+ ->addImage(Image::create()->withURL('https://jpeg.org/images/jpegls-home2.jpg'))
136
+ ->addImage(Image::create()->withURL('https://jpeg.org/images/jpegls-home3.jpg'))
137
+ ->withMapGeoTag($geotag);
138
+
139
+ $expected =
140
+ '<figure class="op-slideshow">'.
141
+ '<figure>'.
142
+ '<img src="https://jpeg.org/images/jpegls-home.jpg"/>'.
143
+ '</figure>'.
144
+ '<figure>'.
145
+ '<img src="https://jpeg.org/images/jpegls-home2.jpg"/>'.
146
+ '</figure>'.
147
+ '<figure>'.
148
+ '<img src="https://jpeg.org/images/jpegls-home3.jpg"/>'.
149
+ '</figure>'.
150
+ '<script type="application/json" class="op-geotag">'.
151
+ $geotag.
152
+ '</script>'.
153
+ '</figure>';
154
+
155
+ $rendered = $slideshow->render();
156
+ $this->assertEquals($expected, $rendered);
157
+ }
158
+
159
+ public function testRenderWithAudio()
160
+ {
161
+ $audio =
162
+ Audio::create()
163
+ ->withURL('http://foo.com/mp3')
164
+ ->withTitle('audio title')
165
+ ->enableMuted()
166
+ ->enableAutoplay();
167
+
168
+ $expected_audio =
169
+ '<audio title="audio title" autoplay="autoplay" muted="muted">'.
170
+ '<source src="http://foo.com/mp3"/>'.
171
+ '</audio>';
172
+
173
+ $slideshow =
174
+ SlideShow::create()
175
+ ->addImage(Image::create()->withURL('https://jpeg.org/images/jpegls-home.jpg'))
176
+ ->addImage(Image::create()->withURL('https://jpeg.org/images/jpegls-home2.jpg'))
177
+ ->addImage(Image::create()->withURL('https://jpeg.org/images/jpegls-home3.jpg'))
178
+ ->withAudio($audio);
179
+
180
+ $expected =
181
+ '<figure class="op-slideshow">'.
182
+ '<figure>'.
183
+ '<img src="https://jpeg.org/images/jpegls-home.jpg"/>'.
184
+ '</figure>'.
185
+ '<figure>'.
186
+ '<img src="https://jpeg.org/images/jpegls-home2.jpg"/>'.
187
+ '</figure>'.
188
+ '<figure>'.
189
+ '<img src="https://jpeg.org/images/jpegls-home3.jpg"/>'.
190
+ '</figure>'.
191
+ $expected_audio.
192
+ '</figure>';
193
+
194
+ $rendered = $slideshow->render();
195
+ $this->assertEquals($expected, $rendered);
196
+ }
197
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/SocialEmbedTest.php ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Elements\SocialEmbed;
12
+ use Facebook\InstantArticles\Elements\Caption;
13
+
14
+ class SocialEmbedTest extends \PHPUnit_Framework_TestCase
15
+ {
16
+ public function setUp()
17
+ {
18
+ }
19
+
20
+ public function testRenderBasic()
21
+ {
22
+ $social_embed =
23
+ SocialEmbed::create()
24
+ ->withSource('http://foo.com');
25
+
26
+ $expected =
27
+ '<figure class="op-social">'.
28
+ '<iframe src="http://foo.com"></iframe>'.
29
+ '</figure>';
30
+
31
+ $rendered = $social_embed->render();
32
+ $this->assertEquals($expected, $rendered);
33
+ }
34
+
35
+ public function testRenderBasicWithCaption()
36
+ {
37
+ $social_embed =
38
+ SocialEmbed::create()
39
+ ->withSource('http://foo.com')
40
+ ->withCaption(
41
+ Caption::create()
42
+ ->appendText('Some caption to the embed')
43
+ );
44
+
45
+ $expected =
46
+ '<figure class="op-social">'.
47
+ '<iframe src="http://foo.com"></iframe>'.
48
+ '<figcaption>Some caption to the embed</figcaption>'.
49
+ '</figure>';
50
+
51
+ $rendered = $social_embed->render();
52
+ $this->assertEquals($expected, $rendered);
53
+ }
54
+
55
+ public function testRenderInline()
56
+ {
57
+ $inline =
58
+ '<h1>Some custom code</h1>'.
59
+ '<script>alert("test");</script>';
60
+ $document = new \DOMDocument();
61
+ $fragment = $document->createDocumentFragment();
62
+ $fragment->appendXML($inline);
63
+
64
+ $social_embed =
65
+ SocialEmbed::create()
66
+ ->withHTML($fragment);
67
+
68
+ $expected =
69
+ '<figure class="op-social">'.
70
+ '<iframe>'.
71
+ '<h1>Some custom code</h1>'.
72
+ '<script>alert("test");</script>'.
73
+ '</iframe>'.
74
+ '</figure>';
75
+
76
+ $rendered = $social_embed->render();
77
+ $this->assertEquals($expected, $rendered);
78
+ }
79
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/TimeTest.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Elements\Time;
12
+
13
+ class TimeTest extends \PHPUnit_Framework_TestCase
14
+ {
15
+ private $timeDate;
16
+
17
+ public function setUp()
18
+ {
19
+ date_default_timezone_set('UTC');
20
+ $this->timeDate = \DateTime::createFromFormat(
21
+ 'j-M-Y G:i:s',
22
+ '14-Aug-1984 19:30:00'
23
+ );
24
+ }
25
+
26
+ public function testRenderBasic()
27
+ {
28
+ $time =
29
+ Time::create(Time::PUBLISHED)
30
+ ->withDatetime($this->timeDate);
31
+
32
+ $expected =
33
+ '<time class="op-published" datetime="1984-08-14T19:30:00+00:00">'.
34
+ 'August 14th, 7:30pm'.
35
+ '</time>';
36
+
37
+ $rendered = $time->render();
38
+ $this->assertEquals($expected, $rendered);
39
+ }
40
+
41
+ public function testRenderModified()
42
+ {
43
+ $time =
44
+ Time::create(Time::PUBLISHED)
45
+ ->withDatetime($this->timeDate);
46
+
47
+ $expected =
48
+ '<time class="op-published" datetime="1984-08-14T19:30:00+00:00">'.
49
+ 'August 14th, 7:30pm'.
50
+ '</time>';
51
+
52
+ $rendered = $time->render();
53
+ $this->assertEquals($expected, $rendered);
54
+ }
55
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/Validators/TypeTest.php ADDED
@@ -0,0 +1,372 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Validators;
10
+
11
+ use Facebook\InstantArticles\Elements\Caption;
12
+ use Facebook\InstantArticles\Elements\Image;
13
+ use Facebook\InstantArticles\Elements\Video;
14
+ use Facebook\InstantArticles\Elements\InstantArticle;
15
+ use Facebook\InstantArticles\Elements\AnimatedGif;
16
+ use Facebook\InstantArticles\Elements\Element;
17
+ use Facebook\InstantArticles\Validators\Type;
18
+
19
+ /**
20
+ *
21
+ */
22
+ class TypeTest extends \PHPUnit_Framework_TestCase
23
+ {
24
+
25
+ /*
26
+ Type check tests ---------------
27
+ */
28
+
29
+ public function testIsType()
30
+ {
31
+ $result = Type::is(Caption::create(), array(Caption::getClassName()));
32
+ $this->assertTrue($result);
33
+ }
34
+
35
+ public function testIsTypeWithArray()
36
+ {
37
+ $result = Type::is(array(1, 2, 3), Type::ARRAY_TYPE);
38
+ $this->assertTrue($result);
39
+ }
40
+
41
+ public function testIsInSet()
42
+ {
43
+ $result = Type::is(
44
+ Caption::create(),
45
+ array(
46
+ Caption::getClassName(),
47
+ InstantArticle::getClassName(),
48
+ Video::getClassName(),
49
+ Image::getClassName()
50
+ )
51
+ );
52
+ $this->assertTrue($result);
53
+ }
54
+
55
+ public function testIsNotIn()
56
+ {
57
+ $result = Type::is(
58
+ Caption::create(),
59
+ array(
60
+ Image::getClassName()
61
+ )
62
+ );
63
+ $this->assertFalse($result);
64
+ }
65
+
66
+ public function testIsNotInException()
67
+ {
68
+ try {
69
+ $result = Type::enforce(
70
+ Caption::create(),
71
+ array(
72
+ Image::getClassName()
73
+ )
74
+ );
75
+ $this->fail('Should throw exception');
76
+ } catch (\Exception $e) {
77
+ // success
78
+ $this->assertInstanceOf('InvalidArgumentException', $e);
79
+ }
80
+ }
81
+
82
+ public function testIsNotInEmpty()
83
+ {
84
+ $result = Type::is(
85
+ Caption::create(),
86
+ array()
87
+ );
88
+ $this->assertFalse($result);
89
+ }
90
+
91
+ public function testIsNotInEmptyException()
92
+ {
93
+ try {
94
+ $result = Type::enforce(
95
+ Caption::create(),
96
+ array()
97
+ );
98
+ $this->fail('Should throw exception');
99
+ } catch (\Exception $e) {
100
+ // success
101
+ $this->assertInstanceOf('InvalidArgumentException', $e);
102
+ }
103
+ }
104
+
105
+ public function testIsNotInSet()
106
+ {
107
+ $result = Type::is(
108
+ Caption::create(),
109
+ array(
110
+ InstantArticle::getClassName(),
111
+ Video::getClassName(),
112
+ Image::getClassName()
113
+ )
114
+ );
115
+ $this->assertFalse($result);
116
+ }
117
+
118
+ public function testIsNotInSetException()
119
+ {
120
+ try {
121
+ $result = Type::enforce(
122
+ Caption::create(),
123
+ array(
124
+ InstantArticle::getClassName(),
125
+ Video::getClassName(),
126
+ Image::getClassName()
127
+ )
128
+ );
129
+ $this->fail('Should throw exception');
130
+ } catch (\Exception $e) {
131
+ // success
132
+ $this->assertInstanceOf('InvalidArgumentException', $e);
133
+ }
134
+ }
135
+
136
+ public function testIsInInheritance()
137
+ {
138
+ $result = Type::is(
139
+ AnimatedGif::create(),
140
+ array(
141
+ Image::getClassName()
142
+ )
143
+ );
144
+ $this->assertTrue($result);
145
+ }
146
+
147
+ public function testIsNotInInheritance()
148
+ {
149
+ $result = Type::is(
150
+ AnimatedGif::create(),
151
+ array(
152
+ Video::getClassName()
153
+ )
154
+ );
155
+ $this->assertFalse($result);
156
+ }
157
+
158
+ public function testIsNotInInheritanceException()
159
+ {
160
+ try {
161
+ $result = Type::enforce(
162
+ AnimatedGif::create(),
163
+ array(
164
+ Video::getClassName()
165
+ )
166
+ );
167
+ $this->fail('Should throw exception');
168
+ } catch (\Exception $e) {
169
+ // success
170
+ $this->assertInstanceOf('InvalidArgumentException', $e);
171
+ }
172
+ }
173
+
174
+ public function testIsString()
175
+ {
176
+ $result = Type::is('test', Type::STRING);
177
+ $this->assertTrue($result);
178
+ }
179
+
180
+ public function testIsNotString()
181
+ {
182
+ $result = Type::is(1, Type::STRING);
183
+ $this->assertFalse($result);
184
+ }
185
+
186
+ public function testIsNotStringException()
187
+ {
188
+ try {
189
+ $result = Type::enforce(1, Type::STRING);
190
+ $this->fail('Should throw exception');
191
+ } catch (\Exception $e) {
192
+ // success
193
+ $this->assertInstanceOf('InvalidArgumentException', $e);
194
+ }
195
+ }
196
+
197
+ public function testIsArrayOfString()
198
+ {
199
+ $result = Type::isArrayOf(array('1', '2'), Type::STRING);
200
+ $this->assertTrue($result);
201
+ }
202
+
203
+ public function testIsArrayOfObject()
204
+ {
205
+ $result =
206
+ Type::isArrayOf(
207
+ array(Image::create(), Image::create()),
208
+ Image::getClassName()
209
+ );
210
+ $this->assertTrue($result);
211
+ }
212
+
213
+ public function testIsArrayOfObjects()
214
+ {
215
+ $result =
216
+ Type::isArrayOf(
217
+ array(Image::create(), Video::create()),
218
+ array(Image::getClassName(), Video::getClassName())
219
+ );
220
+ $this->assertTrue($result);
221
+ }
222
+
223
+ public function testIsArrayInInheritance()
224
+ {
225
+ $result = Type::isArrayOf(
226
+ array(Image::create(), AnimatedGif::create()),
227
+ Image::getClassName()
228
+ );
229
+ $this->assertTrue($result);
230
+ }
231
+
232
+ public function testIsNotArrayInInheritance()
233
+ {
234
+ $result =
235
+ Type::isArrayOf(
236
+ array(Image::create(), Video::create()),
237
+ Image::getClassName()
238
+ );
239
+ $this->assertFalse($result);
240
+ }
241
+
242
+ public function testIsNotArrayInInheritanceException()
243
+ {
244
+ try {
245
+ $result =
246
+ Type::enforceArrayOf(
247
+ array(Image::create(), Video::create()),
248
+ Image::getClassName()
249
+ );
250
+ $this->fail('Should throw exception');
251
+ } catch (\Exception $e) {
252
+ // success
253
+ $this->assertInstanceOf('InvalidArgumentException', $e);
254
+ }
255
+ }
256
+
257
+ /*
258
+ Array size tests ---------------
259
+ */
260
+ public function testArraySize()
261
+ {
262
+ $result = Type::isArraySize(array(1,2,3), 3);
263
+ $this->assertTrue($result);
264
+ }
265
+
266
+ public function testArrayNotSize()
267
+ {
268
+ $result = Type::isArraySize(array(1,2,3), 2);
269
+ $this->assertFalse($result);
270
+ }
271
+
272
+ public function testArrayMinSizeExact()
273
+ {
274
+ $result = Type::isArraySizeGreaterThan(array(1,2,3), 3);
275
+ $this->assertTrue($result);
276
+ }
277
+
278
+ public function testArrayMinSizeMore()
279
+ {
280
+ $result = Type::isArraySizeGreaterThan(array(1,2,3), 2);
281
+ $this->assertTrue($result);
282
+ }
283
+
284
+ public function testArrayMinSizeFew()
285
+ {
286
+ $result = Type::isArraySizeGreaterThan(array(1,2,3), 4);
287
+ $this->assertFalse($result);
288
+ }
289
+
290
+ public function testEnforceArrayMinSizeException()
291
+ {
292
+ try {
293
+ $result = Type::enforceArraySizeGreaterThan(array(1,2,3), 4);
294
+ $this->fail('Should throw exception');
295
+ } catch (\Exception $e) {
296
+ $this->assertInstanceOf('InvalidArgumentException', $e);
297
+ }
298
+ }
299
+
300
+ public function testArrayMaxSizeExact()
301
+ {
302
+ $result = Type::isArraySizeLowerThan(array(1,2,3), 3);
303
+ $this->assertTrue($result);
304
+ }
305
+
306
+ public function testArrayMaxSizeFew()
307
+ {
308
+ $result = Type::isArraySizeLowerThan(array(1,2,3), 4);
309
+ $this->assertTrue($result);
310
+ }
311
+
312
+ public function testArrayMaxSizeMore()
313
+ {
314
+ $result = Type::isArraySizeLowerThan(array(1,2,3), 2);
315
+ $this->assertFalse($result);
316
+ }
317
+
318
+ public function testEnforceArrayMaxSizeException()
319
+ {
320
+ try {
321
+ $result = Type::enforceArraySizeLowerThan(array(1,2,3), 2);
322
+ $this->fail('Should throw exception');
323
+ } catch (\Exception $e) {
324
+ $this->assertInstanceOf('InvalidArgumentException', $e);
325
+ }
326
+ }
327
+
328
+ public function testIsWithinTrueString()
329
+ {
330
+ $result = Type::isWithin('x', array('x', 'y', 'z'));
331
+ $this->assertTrue($result);
332
+ }
333
+
334
+ public function testIsWithinTrueObj()
335
+ {
336
+ $image = Image::create();
337
+ $video = Video::create();
338
+ $result = Type::isWithin($image, array($image, $video, 'z'));
339
+ $this->assertTrue($result);
340
+ }
341
+
342
+ public function testIsWithinFalse()
343
+ {
344
+ $result = Type::isWithin('a', array('x', 'y', 'z'));
345
+ $this->assertFalse($result);
346
+ }
347
+
348
+ public function testIsWithinFalseObj()
349
+ {
350
+ $image = Image::create();
351
+ $video = Video::create();
352
+ $anotherImg = Image::create();
353
+ $result = Type::isWithin($image, array($anotherImg, $video, 'z'));
354
+ $this->assertFalse($result);
355
+ }
356
+
357
+ public function testEnforceWithinTrueString()
358
+ {
359
+ $result = Type::enforceWithin('x', array('x', 'y', 'z'));
360
+ $this->assertTrue($result);
361
+ }
362
+
363
+ public function testEnforceWithinExceptionString()
364
+ {
365
+ try {
366
+ $result = Type::enforceWithin('a', array('x', 'y', 'z'));
367
+ $this->fail('Should trhow exception');
368
+ } catch (\Exception $e) {
369
+ $this->assertInstanceOf('InvalidArgumentException', $e);
370
+ }
371
+ }
372
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/VideoTest.php ADDED
@@ -0,0 +1,257 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Elements\Video;
12
+ use Facebook\InstantArticles\Elements\Caption;
13
+
14
+ class VideoTest extends \PHPUnit_Framework_TestCase
15
+ {
16
+ public function setUp()
17
+ {
18
+ }
19
+
20
+ public function testRenderBasic()
21
+ {
22
+ $video =
23
+ Video::create()
24
+ ->withURL('http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4');
25
+
26
+ $expected =
27
+ '<figure>'.
28
+ '<video>'.
29
+ '<source src="http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4"/>'.
30
+ '</video>'.
31
+ '</figure>';
32
+
33
+ $rendered = $video->render();
34
+ $this->assertEquals($expected, $rendered);
35
+ }
36
+
37
+ public function testRenderWithAttribution()
38
+ {
39
+ $video =
40
+ Video::create()
41
+ ->withURL('http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4')
42
+ ->withAttribution('Some example test attribution');
43
+
44
+ $expected =
45
+ '<figure>'.
46
+ '<video>'.
47
+ '<source src="http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4"/>'.
48
+ '</video>'.
49
+ '<cite>'.
50
+ 'Some example test attribution'.
51
+ '</cite>'.
52
+ '</figure>';
53
+
54
+ $rendered = $video->render();
55
+ $this->assertEquals($expected, $rendered);
56
+ }
57
+
58
+ public function testRenderWithPresentation()
59
+ {
60
+ $video =
61
+ Video::create()
62
+ ->withURL('http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4')
63
+ ->withPresentation(Video::FULLSCREEN);
64
+
65
+ $expected =
66
+ '<figure data-mode="'.Video::FULLSCREEN.'">'.
67
+ '<video>'.
68
+ '<source src="http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4"/>'.
69
+ '</video>'.
70
+ '</figure>';
71
+
72
+ $rendered = $video->render();
73
+ $this->assertEquals($expected, $rendered);
74
+ }
75
+
76
+ public function testRenderWithControls()
77
+ {
78
+ $video =
79
+ Video::create()
80
+ ->withURL('http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4')
81
+ ->enableControls();
82
+
83
+ $expected =
84
+ '<figure>'.
85
+ '<video controls="controls">'.
86
+ '<source src="http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4"/>'.
87
+ '</video>'.
88
+ '</figure>';
89
+
90
+ $rendered = $video->render();
91
+ $this->assertEquals($expected, $rendered);
92
+ }
93
+
94
+ public function testRenderWithoutAutoplay()
95
+ {
96
+ $video =
97
+ Video::create()
98
+ ->withURL('http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4')
99
+ ->disableAutoplay();
100
+
101
+ $expected =
102
+ '<figure>'.
103
+ '<video data-fb-disable-autoplay="data-fb-disable-autoplay">'.
104
+ '<source src="http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4"/>'.
105
+ '</video>'.
106
+ '</figure>';
107
+
108
+ $rendered = $video->render();
109
+ $this->assertEquals($expected, $rendered);
110
+ }
111
+
112
+ public function testRenderWithCaption()
113
+ {
114
+ $video =
115
+ Video::create()
116
+ ->withURL('http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4')
117
+ ->withCaption(
118
+ Caption::create()
119
+ ->appendText('Some caption to the video')
120
+ );
121
+
122
+ $expected =
123
+ '<figure>'.
124
+ '<video>'.
125
+ '<source src="http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4"/>'.
126
+ '</video>'.
127
+ '<figcaption>Some caption to the video</figcaption>'.
128
+ '</figure>';
129
+
130
+ $rendered = $video->render();
131
+ $this->assertEquals($expected, $rendered);
132
+ }
133
+
134
+ public function testRenderWithLike()
135
+ {
136
+ $video =
137
+ Video::create()
138
+ ->withURL('http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4')
139
+ ->withCaption(
140
+ Caption::create()
141
+ ->appendText('Some caption to the video')
142
+ )
143
+ ->enableLike();
144
+
145
+ $expected =
146
+ '<figure data-feedback="fb:likes">'.
147
+ '<video>'.
148
+ '<source src="http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4"/>'.
149
+ '</video>'.
150
+ '<figcaption>Some caption to the video</figcaption>'.
151
+ '</figure>';
152
+
153
+ $rendered = $video->render();
154
+ $this->assertEquals($expected, $rendered);
155
+ }
156
+
157
+ public function testRenderWithComments()
158
+ {
159
+ $video =
160
+ Video::create()
161
+ ->withURL('http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4')
162
+ ->withCaption(
163
+ Caption::create()
164
+ ->appendText('Some caption to the video')
165
+ )
166
+ ->enableComments();
167
+
168
+ $expected =
169
+ '<figure data-feedback="fb:comments">'.
170
+ '<video>'.
171
+ '<source src="http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4"/>'.
172
+ '</video>'.
173
+ '<figcaption>Some caption to the video</figcaption>'.
174
+ '</figure>';
175
+
176
+ $rendered = $video->render();
177
+ $this->assertEquals($expected, $rendered);
178
+ }
179
+
180
+ public function testRenderWithLikeAndComments()
181
+ {
182
+ $video =
183
+ Video::create()
184
+ ->withURL('http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4')
185
+ ->withCaption(
186
+ Caption::create()
187
+ ->appendText('Some caption to the video')
188
+ )
189
+ ->enableLike()
190
+ ->enableComments();
191
+
192
+ $expected =
193
+ '<figure data-feedback="fb:likes,fb:comments">'.
194
+ '<video>'.
195
+ '<source src="http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4"/>'.
196
+ '</video>'.
197
+ '<figcaption>Some caption to the video</figcaption>'.
198
+ '</figure>';
199
+
200
+ $rendered = $video->render();
201
+ $this->assertEquals($expected, $rendered);
202
+ }
203
+
204
+ public function testRenderWithGeotag()
205
+ {
206
+ $geotag =
207
+ '{'.
208
+ '"type": "Feature",'.
209
+ '"geometry": {'.
210
+ '"type": "Point",'.
211
+ '"coordinates": [23.166667, 89.216667]'.
212
+ '},'.
213
+ '"properties": {'.
214
+ '"title": "Jessore, Bangladesh",'.
215
+ '"radius": 750000,'.
216
+ '"pivot": true,'.
217
+ '"style": "satellite"'.
218
+ '}'.
219
+ '}';
220
+
221
+ $video =
222
+ Video::create()
223
+ ->withURL('http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4')
224
+ ->withGeoTag(GeoTag::create()->withScript($geotag));
225
+
226
+ $expected =
227
+ '<figure>'.
228
+ '<video>'.
229
+ '<source src="http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4"/>'.
230
+ '</video>'.
231
+ '<script type="application/json" class="op-geotag">'.
232
+ $geotag.
233
+ '</script>'.
234
+ '</figure>';
235
+
236
+ $rendered = $video->render();
237
+ $this->assertEquals($expected, $rendered);
238
+ }
239
+
240
+ public function testRenderWithFeedCover()
241
+ {
242
+ $video =
243
+ Video::create()
244
+ ->withURL('http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4')
245
+ ->enableFeedCover();
246
+
247
+ $expected =
248
+ '<figure class="fb-feed-cover">'.
249
+ '<video>'.
250
+ '<source src="http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4"/>'.
251
+ '</video>'.
252
+ '</figure>';
253
+
254
+ $rendered = $video->render();
255
+ $this->assertEquals($expected, $rendered);
256
+ }
257
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/Example/SimpleTransformerTest.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
10
+
11
+ use Facebook\InstantArticles\Elements\Element;
12
+ use Facebook\InstantArticles\Elements\InstantArticle;
13
+ use Facebook\InstantArticles\Elements\Header;
14
+ use Facebook\InstantArticles\Elements\Time;
15
+ use Facebook\InstantArticles\Elements\Author;
16
+ use Facebook\InstantArticles\Elements\Image;
17
+ use Facebook\InstantArticles\Elements\Caption;
18
+ use Facebook\InstantArticles\Elements\Paragraph;
19
+ use Facebook\InstantArticles\Elements\SlideShow;
20
+ use Facebook\InstantArticles\Elements\Analytics;
21
+ use Facebook\InstantArticles\Elements\Ad;
22
+ use Facebook\InstantArticles\Elements\Footer;
23
+ use Facebook\InstantArticles\Elements\Bold;
24
+
25
+ use Facebook\InstantArticles\Transformer\Rules\ParagraphRule;
26
+ use Facebook\InstantArticles\Transformer\Rules\TextNodeRule;
27
+ use Facebook\InstantArticles\Transformer\Rules\ItalicRule;
28
+ use Facebook\InstantArticles\Transformer\Rules\PassThroughRule;
29
+ use Facebook\InstantArticles\Transformer\Rules\BoldRule;
30
+ use Facebook\InstantArticles\Transformer\Rules\ImageRule;
31
+ use Facebook\InstantArticles\Transformer\Rules\AuthorRule;
32
+
33
+ use Symfony\Component\CssSelector\CssSelectorConverter;
34
+
35
+ class SimpleTransformerTest extends \PHPUnit_Framework_TestCase
36
+ {
37
+ /**
38
+ * @var InstantArticle
39
+ */
40
+ private $article;
41
+ private $input;
42
+ public function setUp()
43
+ {
44
+ \Logger::configure(
45
+ array(
46
+ 'rootLogger' => array(
47
+ 'appenders' => array('facebook-instantarticles-transformer')
48
+ ),
49
+ 'appenders' => array(
50
+ 'facebook-instantarticles-transformer' => array(
51
+ 'class' => 'LoggerAppenderConsole',
52
+ 'threshold' => 'INFO',
53
+ 'layout' => array(
54
+ 'class' => 'LoggerLayoutSimple'
55
+ )
56
+ )
57
+ )
58
+ )
59
+ );
60
+ }
61
+
62
+ public function testSelfTransformerContent()
63
+ {
64
+ $json_file = file_get_contents("simple-rules.json", true);
65
+
66
+ $instant_article = InstantArticle::create();
67
+ $transformer = new Transformer();
68
+ $transformer->loadRules($json_file);
69
+
70
+ $html_file = file_get_contents("simple.html", true);
71
+
72
+ libxml_use_internal_errors(true);
73
+ $document = new \DOMDocument();
74
+ $document->loadHTML($html_file);
75
+ libxml_use_internal_errors(false);
76
+
77
+ $transformer->transform($instant_article, $document);
78
+ $instant_article->addMetaProperty('op:generator:version', '1.0.0');
79
+ $instant_article->addMetaProperty('op:transformer:version', '1.0.0');
80
+ $warnings = $transformer->getWarnings();
81
+ $result = $instant_article->render('', true)."\n";
82
+ $expected = file_get_contents("simple-ia.xml", true);
83
+
84
+ //var_dump($result);
85
+ // print_r($warnings);
86
+ $this->assertEquals($expected, $result);
87
+ }
88
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/Example/simple-ia.xml ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <html>
2
+ <head>
3
+ <link rel="canonical" href=""/>
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:transformer" content="facebook-instant-articles-sdk-php"/>
8
+ <meta property="op:transformer:version" content="1.0.0"/>
9
+ <meta property="op:markup_version" content="v1.0"/>
10
+ <meta property="fb:use_automatic_ad_placement" content="true"/>
11
+ </head>
12
+ <body>
13
+ <article>
14
+ <header>
15
+ <figure>
16
+ <img src="http://domain.com/image-header.png"/>
17
+ <figcaption>Some amazing moment captured by Photographer</figcaption>
18
+ </figure>
19
+ <h1>The article title</h1>
20
+ <h2>Sub Title</h2>
21
+ <address><a>Author name</a></address>
22
+ </header>
23
+ <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>
24
+ <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>
25
+ <figure>
26
+ <img src="http://domain.com/image-body.png"/>
27
+ <figcaption>Photographer</figcaption>
28
+ </figure>
29
+ <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>
30
+ </article>
31
+ </body>
32
+ </html>
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/Example/simple-rules.json ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "rules" :
3
+ [
4
+ {
5
+ "class": "TextNodeRule"
6
+ },
7
+ {
8
+ "class": "PassThroughRule",
9
+ "selector" : "html"
10
+ },
11
+ {
12
+ "class": "PassThroughRule",
13
+ "selector" : "head"
14
+ },
15
+ {
16
+ "class": "PassThroughRule",
17
+ "selector" : "script"
18
+ },
19
+ {
20
+ "class": "PassThroughRule",
21
+ "selector" : "body"
22
+ },
23
+ {
24
+ "class": "ItalicRule",
25
+ "selector" : "i"
26
+ },
27
+ {
28
+ "class": "BoldRule",
29
+ "selector" : "b"
30
+ },
31
+ {
32
+ "class": "ParagraphRule",
33
+ "selector" : "p"
34
+ },
35
+ {
36
+ "class": "HeaderTitleRule",
37
+ "selector" : "h1"
38
+ },
39
+ {
40
+ "class": "HeaderSubTitleRule",
41
+ "selector" : "h2"
42
+ },
43
+ {
44
+ "class": "HeaderRule",
45
+ "selector" : "div.header"
46
+ },
47
+ {
48
+ "class": "AuthorRule",
49
+ "selector" : "span.author",
50
+ "properties" : {
51
+ "author.name" : {
52
+ "type" : "string",
53
+ "selector" : "span"
54
+ }
55
+ }
56
+ },
57
+ {
58
+ "class": "CaptionRule",
59
+ "selector" : "div.image-caption"
60
+ },
61
+ {
62
+ "class": "CaptionRule",
63
+ "selector" : "//img[@alt]",
64
+ "properties" : {
65
+ "caption.default": {
66
+ "type": "string",
67
+ "selector": "img",
68
+ "attribute": "alt"
69
+ }
70
+ }
71
+ },
72
+ {
73
+ "class": "ImageRule",
74
+ "selector" : "div.image",
75
+ "properties" : {
76
+ "image.url" : {
77
+ "type" : "string",
78
+ "selector" : "img",
79
+ "attribute": "src"
80
+ },
81
+ "image.caption" : {
82
+ "type" : "element",
83
+ "selector" : "div.image"
84
+ }
85
+ }
86
+ },
87
+ {
88
+ "class": "HeaderImageRule",
89
+ "selector" : "div.hero-image",
90
+ "properties" : {
91
+ "image.url" : {
92
+ "type" : "string",
93
+ "selector" : "img",
94
+ "attribute": "src"
95
+ },
96
+ "image.caption" : {
97
+ "type" : "element",
98
+ "selector" : "div.image-caption"
99
+ }
100
+ }
101
+ }
102
+ ]
103
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/Example/simple.html ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <html>
2
+ <head>
3
+ <script type="text/javascript" href="http://domain.com/javascript.js" />
4
+ </head>
5
+ <body>
6
+ <div class="header">
7
+ <h1>The article title</h1>
8
+ <h2>Sub Title</h2>
9
+ <span class="author">Author name</span>
10
+ <div class="hero-image">
11
+ <img src="http://domain.com/image-header.png" />
12
+ <div class="image-caption">Some amazing moment captured by Photographer</div>
13
+ </div>
14
+ </div>
15
+ <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>
16
+ <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>
17
+ <div class="image">
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>
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/Rules/AuthorRuleTest.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\Transformer\Rules\AuthorRule;
12
+
13
+ class AuthorRuleTest extends \PHPUnit_Framework_TestCase
14
+ {
15
+ public function setUp()
16
+ {
17
+ }
18
+
19
+ public function testCreateFromProperties()
20
+ {
21
+ $author_rule = AuthorRule::createFrom(
22
+ array(
23
+ "class" => "Facebook\\InstantArticles\\Transformer\\Rules\\AuthorRule",
24
+ "selector" => "div.post-content > p > em",
25
+ "properties" => array(
26
+ "author.url" => array(
27
+ "type" => "string",
28
+ "selector" => "a",
29
+ "attribute" => "href"
30
+ ),
31
+ "author.description" => array(
32
+ "type" => "string",
33
+ "selector" => "#text:nth-child(2)"
34
+ )
35
+ )
36
+ )
37
+ );
38
+ $this->assertEquals(get_class($author_rule), AuthorRule::getClassName());
39
+ }
40
+
41
+ public function testCreate()
42
+ {
43
+ $author_rule = AuthorRule::create()
44
+ ->withSelector("div.post-content > p > em")
45
+ ->withProperty(
46
+ AuthorRule::PROPERTY_AUTHOR_URL,
47
+ array(
48
+ "type" => "string",
49
+ "selector" => "a",
50
+ "attribute" => "href"
51
+ )
52
+ )
53
+ ->withProperty(
54
+ AuthorRule::PROPERTY_AUTHOR_NAME,
55
+ array(
56
+ "type" => "string",
57
+ "selector" => "span"
58
+ )
59
+ );
60
+ $this->assertEquals(get_class($author_rule), AuthorRule::getClassName());
61
+ }
62
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/TransformerTest.php ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
10
+
11
+ use Facebook\InstantArticles\Elements\Element;
12
+ use Facebook\InstantArticles\Elements\InstantArticle;
13
+ use Facebook\InstantArticles\Elements\Header;
14
+ use Facebook\InstantArticles\Elements\Time;
15
+ use Facebook\InstantArticles\Elements\Author;
16
+ use Facebook\InstantArticles\Elements\Image;
17
+ use Facebook\InstantArticles\Elements\Caption;
18
+ use Facebook\InstantArticles\Elements\Paragraph;
19
+ use Facebook\InstantArticles\Elements\SlideShow;
20
+ use Facebook\InstantArticles\Elements\Analytics;
21
+ use Facebook\InstantArticles\Elements\Ad;
22
+ use Facebook\InstantArticles\Elements\Footer;
23
+ use Facebook\InstantArticles\Elements\Bold;
24
+
25
+ use Facebook\InstantArticles\Transformer\Rules\ParagraphRule;
26
+ use Facebook\InstantArticles\Transformer\Rules\TextNodeRule;
27
+ use Facebook\InstantArticles\Transformer\Rules\ItalicRule;
28
+ use Facebook\InstantArticles\Transformer\Rules\PassThroughRule;
29
+ use Facebook\InstantArticles\Transformer\Rules\BoldRule;
30
+ use Facebook\InstantArticles\Transformer\Rules\ImageRule;
31
+ use Facebook\InstantArticles\Transformer\Rules\AuthorRule;
32
+
33
+ use Symfony\Component\CssSelector\CssSelectorConverter;
34
+
35
+ class TransformerTest extends \PHPUnit_Framework_TestCase
36
+ {
37
+ public function setUp()
38
+ {
39
+ \Logger::configure(
40
+ array(
41
+ 'rootLogger' => array(
42
+ 'appenders' => array('facebook-instantarticles-transformer')
43
+ ),
44
+ 'appenders' => array(
45
+ 'facebook-instantarticles-transformer' => array(
46
+ 'class' => 'LoggerAppenderConsole',
47
+ 'threshold' => 'INFO',
48
+ 'layout' => array(
49
+ 'class' => 'LoggerLayoutSimple'
50
+ )
51
+ )
52
+ )
53
+ )
54
+ );
55
+ }
56
+
57
+ public function testSelfTransformerContent()
58
+ {
59
+ $json_file = file_get_contents("instant-article-example-rules.json", true);
60
+
61
+ $instant_article = InstantArticle::create();
62
+ $transformer = new Transformer();
63
+ $transformer->loadRules($json_file);
64
+
65
+ $html_file = file_get_contents("instant-article-example.html", true);
66
+
67
+ libxml_use_internal_errors(true);
68
+ $document = new \DOMDocument();
69
+ $document->loadXML($html_file);
70
+ libxml_use_internal_errors(false);
71
+
72
+ $transformer->transform($instant_article, $document);
73
+ $instant_article->addMetaProperty('op:generator:version', '1.0.0');
74
+ $instant_article->addMetaProperty('op:transformer:version', '1.0.0');
75
+ $warnings = $transformer->getWarnings();
76
+ $result = $instant_article->render('', true)."\n";
77
+
78
+ //var_dump($result);
79
+ // print_r($warnings);
80
+ $this->assertEquals($html_file, $result);
81
+ }
82
+
83
+ public function testTransformerAddAndGetRules()
84
+ {
85
+ $transformer = new Transformer();
86
+ $rule1 = new ParagraphRule();
87
+ $rule2 = new ItalicRule();
88
+ $transformer->addRule($rule1);
89
+ $transformer->addRule($rule2);
90
+ $this->assertEquals(array($rule2, $rule1), $transformer->getRules());
91
+ }
92
+
93
+ public function testTransformerSetRules()
94
+ {
95
+ $transformer = new Transformer();
96
+ $rule1 = new ParagraphRule();
97
+ $rule2 = new ItalicRule();
98
+ $transformer->setRules(array($rule1, $rule2));
99
+ $this->assertEquals(array($rule1, $rule2), $transformer->getRules());
100
+ }
101
+
102
+ public function testTransformerResetRules()
103
+ {
104
+ $transformer = new Transformer();
105
+ $rule1 = new ParagraphRule();
106
+ $rule2 = new ItalicRule();
107
+ $transformer->addRule($rule1);
108
+ $transformer->addRule($rule2);
109
+ $transformer->resetRules();
110
+ $this->assertEquals(array(), $transformer->getRules());
111
+ }
112
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/Warnings/InvalidSelectorTest.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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\InstantArticle;
12
+ use Facebook\InstantArticles\Transformer\Rules\SocialEmbedRule;
13
+
14
+ class InvalidSelectorTest extends \PHPUnit_Framework_TestCase
15
+ {
16
+ private $properties;
17
+
18
+ public function setUp()
19
+ {
20
+
21
+ }
22
+
23
+ public function testInvalidSelectorToString()
24
+ {
25
+
26
+ $json =
27
+ '{'.
28
+ '"class": "SocialEmbedRule",'.
29
+ '"selector" : "figure.op-social",'.
30
+ '"properties" : {'.
31
+ '"socialembed.url" : {'.
32
+ '"type" : "string",'.
33
+ '"selector" : "iframe",'.
34
+ '"attribute": "src"'.
35
+ '},'.
36
+ '"socialembed.iframe" : {'.
37
+ '"type" : "children",'.
38
+ '"selector" : "iframe"'.
39
+ '}'.
40
+ '}'.
41
+ '}';
42
+ $properties = json_decode($json, true);
43
+
44
+ $instant_article = InstantArticle::create();
45
+ $document = new \DOMDocument();
46
+ $node = $document->createElement('figcaption');
47
+ $rule = SocialEmbedRule::createFrom($properties);
48
+
49
+ $warning = new InvalidSelector('field a and b', $instant_article, $node, $rule);
50
+
51
+ $result = $warning->__toString();
52
+ $expected = 'Invalid selector for fields (field a and b). '.
53
+ 'The node being transformed was <figcaption> in the context of'.
54
+ ' InstantArticle within the Rule SocialEmbedRule with these'.
55
+ ' properties: { socialembed.url=StringGetter}';
56
+
57
+ $this->assertEquals($expected, $result);
58
+ }
59
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/instant-article-example-rules.json ADDED
@@ -0,0 +1,654 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "rules" :
3
+ [
4
+ {
5
+ "class": "TextNodeRule"
6
+ },
7
+ {
8
+ "class": "PassThroughRule",
9
+ "selector" : "html"
10
+ },
11
+ {
12
+ "class": "PassThroughRule",
13
+ "selector" : "head"
14
+ },
15
+ {
16
+ "class": "PassThroughRule",
17
+ "selector" : "body"
18
+ },
19
+ {
20
+ "class": "PassThroughRule",
21
+ "selector" : "article"
22
+ },
23
+ {
24
+ "class": "PassThroughRule",
25
+ "selector" : "div"
26
+ },
27
+ {
28
+ "class": "PassThroughRule",
29
+ "selector" : "span"
30
+ },
31
+ {
32
+ "class": "PassThroughRule",
33
+ "selector" : "p"
34
+ },
35
+ {
36
+ "class": "PassThroughRule",
37
+ "selector" : "aside"
38
+ },
39
+ {
40
+ "class": "AnchorRule",
41
+ "selector" : "a",
42
+ "properties" : {
43
+ "anchor.href" : {
44
+ "type" : "string",
45
+ "selector" : "a",
46
+ "attribute": "href"
47
+ },
48
+ "anchor.rel" : {
49
+ "type" : "string",
50
+ "selector" : "a",
51
+ "attribute": "rel"
52
+ }
53
+ }
54
+ },
55
+ {
56
+ "class": "ItalicRule",
57
+ "selector" : "i"
58
+ },
59
+ {
60
+ "class": "BoldRule",
61
+ "selector" : "b"
62
+ },
63
+ {
64
+ "class": "BoldRule",
65
+ "selector" : "strong"
66
+ },
67
+ {
68
+ "class": "ParagraphRule",
69
+ "selector" : "p"
70
+ },
71
+ {
72
+ "class": "ParagraphFooterRule",
73
+ "selector" : "p"
74
+ },
75
+ {
76
+ "class": "ListItemRule",
77
+ "selector" : "li"
78
+ },
79
+ {
80
+ "class": "ListElementRule",
81
+ "selector" : "ul"
82
+ },
83
+ {
84
+ "class": "ListElementRule",
85
+ "selector" : "ol"
86
+ },
87
+ {
88
+ "class": "BlockquoteRule",
89
+ "selector" : "blockquote"
90
+ },
91
+ {
92
+ "class": "H1Rule",
93
+ "selector" : "h1",
94
+ "properties" : {
95
+ "h1.class" : {
96
+ "type" : "string",
97
+ "selector" : "link",
98
+ "attribute": "class"
99
+ }
100
+ }
101
+ },
102
+ {
103
+ "class": "H1Rule",
104
+ "selector" : "title"
105
+ },
106
+ {
107
+ "class": "H2Rule",
108
+ "selector" : "h2",
109
+ "properties" : {
110
+ "h2.class" : {
111
+ "type" : "string",
112
+ "selector" : "link",
113
+ "attribute": "class"
114
+ }
115
+ }
116
+ },
117
+ {
118
+ "class": "HeaderRule",
119
+ "selector" : "header"
120
+ },
121
+ {
122
+ "class": "FooterRule",
123
+ "selector" : "footer"
124
+ },
125
+ {
126
+ "class": "RelatedArticlesRule",
127
+ "selector" : "ul.op-related-articles",
128
+ "properties" : {
129
+ "related.title" : {
130
+ "type" : "string",
131
+ "selector" : "ul.op-related-articles",
132
+ "attribute": "title"
133
+ }
134
+ }
135
+ },
136
+ {
137
+ "class": "FooterRelatedArticlesRule",
138
+ "selector" : "ul.op-related-articles",
139
+ "properties" : {
140
+ "related.title" : {
141
+ "type" : "string",
142
+ "selector" : "ul.op-related-articles",
143
+ "attribute": "title"
144
+ }
145
+ }
146
+ },
147
+ {
148
+ "class": "RelatedItemRule",
149
+ "selector" : "li",
150
+ "properties" : {
151
+ "related.sponsored" : {
152
+ "type" : "exists",
153
+ "selector" : "li",
154
+ "attribute": "data-sponsored"
155
+ },
156
+ "related.url" : {
157
+ "type" : "string",
158
+ "selector" : "a",
159
+ "attribute": "href"
160
+ }
161
+ }
162
+ },
163
+ {
164
+ "class": "InstantArticleRule",
165
+ "selector" : "head",
166
+ "properties" : {
167
+ "article.canonical" : {
168
+ "type" : "string",
169
+ "selector" : "link",
170
+ "attribute": "href"
171
+ },
172
+ "article.charset" : {
173
+ "type" : "xpath",
174
+ "selector" : "//meta[@charset]",
175
+ "attribute": "charset"
176
+ },
177
+ "article.markup.version" : {
178
+ "type" : "xpath",
179
+ "selector" : "//meta[@property='op:markup_version']",
180
+ "attribute": "content"
181
+ },
182
+ "article.auto.ad" : {
183
+ "type" : "xpath",
184
+ "selector" : "//meta[@property='fb:use_automatic_ad_placement']",
185
+ "attribute": "content"
186
+ }
187
+
188
+ }
189
+ },
190
+ {
191
+ "class": "HeaderTitleRule",
192
+ "selector" : "h1"
193
+ },
194
+ {
195
+ "class": "HeaderSubTitleRule",
196
+ "selector" : "h2"
197
+ },
198
+ {
199
+ "class": "HeaderKickerRule",
200
+ "selector" : "h3.op-kicker"
201
+ },
202
+ {
203
+ "class": "TimeRule",
204
+ "selector" : "time.op-modified",
205
+ "article.time_type": "op-modified",
206
+ "properties" : {
207
+ "article.time" : {
208
+ "type" : "string",
209
+ "selector" : "time",
210
+ "attribute": "datetime"
211
+ }
212
+ }
213
+ },
214
+ {
215
+ "class": "TimeRule",
216
+ "selector" : "time.op-published",
217
+ "article.time_type": "op-published",
218
+ "properties" : {
219
+ "article.time" : {
220
+ "type" : "string",
221
+ "selector" : "time",
222
+ "attribute": "datetime"
223
+ }
224
+ }
225
+ },
226
+ {
227
+ "class": "AuthorRule",
228
+ "selector" : "address",
229
+ "properties" : {
230
+ "author.url" : {
231
+ "type" : "string",
232
+ "selector" : "a",
233
+ "attribute": "href"
234
+ },
235
+ "author.name" : {
236
+ "type" : "string",
237
+ "selector" : "a"
238
+ },
239
+ "author.role_contribution" : {
240
+ "type" : "string",
241
+ "selector" : "a",
242
+ "attribute": "title"
243
+ },
244
+ "author.description" : {
245
+ "type" : "sibling",
246
+ "selector" : "a"
247
+ }
248
+ }
249
+ },
250
+ {
251
+ "class": "H1Rule",
252
+ "selector" : "h1",
253
+ "properties" : {
254
+ "op-left": {
255
+ "type": "exists",
256
+ "selector" : "h1.op-left"
257
+ },
258
+ "op-center": {
259
+ "type": "exists",
260
+ "selector" : "h1.op-center"
261
+ },
262
+ "op-right": {
263
+ "type": "exists",
264
+ "selector" : "h1.op-right"
265
+ },
266
+
267
+ "op-vertical-below": {
268
+ "type": "exists",
269
+ "selector" : "h1.op-vertical-below"
270
+ },
271
+ "op-vertical-center": {
272
+ "type": "exists",
273
+ "selector" : "h1.op-vertical-center"
274
+ },
275
+ "op-vertical-above": {
276
+ "type": "exists",
277
+ "selector" : "h1.op-vertical-above"
278
+ }
279
+ }
280
+ },
281
+ {
282
+ "class": "H2Rule",
283
+ "selector" : "h2",
284
+ "properties" : {
285
+ "op-left": {
286
+ "type": "exists",
287
+ "selector" : "h2.op-left"
288
+ },
289
+ "op-center": {
290
+ "type": "exists",
291
+ "selector" : "h2.op-center"
292
+ },
293
+ "op-right": {
294
+ "type": "exists",
295
+ "selector" : "h2.op-right"
296
+ },
297
+
298
+ "op-vertical-below": {
299
+ "type": "exists",
300
+ "selector" : "h2.op-vertical-below"
301
+ },
302
+ "op-vertical-center": {
303
+ "type": "exists",
304
+ "selector" : "h2.op-vertical-center"
305
+ },
306
+ "op-vertical-above": {
307
+ "type": "exists",
308
+ "selector" : "h2.op-vertical-above"
309
+ }
310
+ }
311
+ },
312
+ {
313
+ "class": "CaptionCreditRule",
314
+ "selector" : "cite",
315
+ "properties" : {
316
+ "op-left": {
317
+ "type": "exists",
318
+ "selector" : "cite.op-left"
319
+ },
320
+ "op-center": {
321
+ "type": "exists",
322
+ "selector" : "cite.op-center"
323
+ },
324
+ "op-right": {
325
+ "type": "exists",
326
+ "selector" : "cite.op-right"
327
+ },
328
+
329
+ "op-vertical-below": {
330
+ "type": "exists",
331
+ "selector" : "cite.op-vertical-below"
332
+ },
333
+ "op-vertical-center": {
334
+ "type": "exists",
335
+ "selector" : "cite.op-vertical-center"
336
+ },
337
+ "op-vertical-above": {
338
+ "type": "exists",
339
+ "selector" : "cite.op-vertical-above"
340
+ }
341
+ }
342
+ },
343
+ {
344
+ "class": "PullquoteCiteRule",
345
+ "selector" : "cite"
346
+ },
347
+ {
348
+ "class": "CaptionRule",
349
+ "selector" : "figcaption",
350
+ "properties" : {
351
+ "op-medium": {
352
+ "type": "exists",
353
+ "selector" : "figcaption.op-medium"
354
+ },
355
+ "op-large": {
356
+ "type": "exists",
357
+ "selector" : "figcaption.op-large"
358
+ },
359
+ "op-extra-large": {
360
+ "type": "exists",
361
+ "selector" : "figcaption.op-extra-large"
362
+ },
363
+
364
+ "op-left": {
365
+ "type": "exists",
366
+ "selector" : "figcaption.op-left"
367
+ },
368
+ "op-center": {
369
+ "type": "exists",
370
+ "selector" : "figcaption.op-center"
371
+ },
372
+ "op-right": {
373
+ "type": "exists",
374
+ "selector" : "figcaption.op-right"
375
+ },
376
+
377
+ "op-vertical-below": {
378
+ "type": "exists",
379
+ "selector" : "figcaption.op-vertical-below"
380
+ },
381
+ "op-vertical-center": {
382
+ "type": "exists",
383
+ "selector" : "figcaption.op-vertical-center"
384
+ },
385
+ "op-vertical-above": {
386
+ "type": "exists",
387
+ "selector" : "figcaption.op-vertical-above"
388
+ },
389
+ "caption.default": {
390
+ "type": "string",
391
+ "selector": "img",
392
+ "attribute": "alt"
393
+ }
394
+ }
395
+ },
396
+ {
397
+ "class": "AudioRule",
398
+ "selector" : "audio",
399
+ "properties" : {
400
+ "audio.url" : {
401
+ "type" : "string",
402
+ "selector" : "source",
403
+ "attribute": "src"
404
+ },
405
+ "audio.title" : {
406
+ "type" : "string",
407
+ "selector" : "audio",
408
+ "attribute": "title"
409
+ },
410
+ "audio.autoplay" : {
411
+ "type" : "string",
412
+ "selector" : "audio",
413
+ "attribute": "autoplay"
414
+ },
415
+ "audio.muted" : {
416
+ "type" : "string",
417
+ "selector" : "audio",
418
+ "attribute": "muted"
419
+ }
420
+ }
421
+ },
422
+ {
423
+ "class": "ImageRule",
424
+ "selector" : "figure",
425
+ "properties" : {
426
+ "image.url" : {
427
+ "type" : "string",
428
+ "selector" : "img",
429
+ "attribute": "src"
430
+ },
431
+ "image.like" : {
432
+ "type" : "exists",
433
+ "selector" : "figure[data-feedback*='fb:likes']",
434
+ "attribute": "data-feedback"
435
+ },
436
+ "image.comments" : {
437
+ "type" : "exists",
438
+ "selector" : "figure[data-feedback*='fb:comments']",
439
+ "attribute": "data-feedback"
440
+ }
441
+ }
442
+ },
443
+ {
444
+ "class": "VideoRule",
445
+ "selector" : "figure",
446
+ "containsChild": "video",
447
+ "properties" : {
448
+ "video.url" : {
449
+ "type" : "string",
450
+ "selector" : "source",
451
+ "attribute": "src"
452
+ },
453
+ "video.type" : {
454
+ "type" : "string",
455
+ "selector" : "source",
456
+ "attribute": "type"
457
+ },
458
+ "aspect-fit": {
459
+ "type": "exists",
460
+ "selector" : "figure[data-mode=aspect-fit]"
461
+ },
462
+ "aspect-fit-only": {
463
+ "type": "exists",
464
+ "selector" : "figure[data-mode=aspect-fit-only]"
465
+ },
466
+ "fullscreen": {
467
+ "type": "exists",
468
+ "selector" : "figure[data-mode=fullscreen]"
469
+ },
470
+ "non-interactive": {
471
+ "type": "exists",
472
+ "selector" : "figure[data-mode=non-interactive]"
473
+ },
474
+ "video.controls": {
475
+ "type": "exists",
476
+ "selector" : "video",
477
+ "attribute": "controls"
478
+ },
479
+ "video.playback": {
480
+ "type": "exists",
481
+ "selector" : "video",
482
+ "attribute": "data-fb-disable-autoplay"
483
+ },
484
+ "video.like" : {
485
+ "type" : "exists",
486
+ "selector" : "figure[data-feedback*='fb:likes']",
487
+ "attribute": "data-feedback"
488
+ },
489
+ "video.comments" : {
490
+ "type" : "exists",
491
+ "selector" : "figure[data-feedback*='fb:comments']",
492
+ "attribute": "data-feedback"
493
+ }
494
+ }
495
+ },
496
+ {
497
+ "class": "MapRule",
498
+ "selector" : "figure.op-map"
499
+ },
500
+ {
501
+ "class": "GeoTagRule",
502
+ "selector" : "script.op-geotag",
503
+ "properties" : {
504
+ "map.geotag" : {
505
+ "type" : "string",
506
+ "selector" : "script"
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",
528
+ "properties" : {
529
+ "no-margin" : {
530
+ "type" : "exists",
531
+ "selector" : "iframe.no-margin"
532
+ },
533
+ "column-width" : {
534
+ "type" : "exists",
535
+ "selector" : "iframe.column-width"
536
+ },
537
+ "interactive.url" : {
538
+ "type" : "string",
539
+ "selector" : "iframe",
540
+ "attribute": "src"
541
+ },
542
+ "interactive.height" : {
543
+ "type" : "int",
544
+ "selector" : "iframe",
545
+ "attribute": "height"
546
+ },
547
+ "interactive.iframe" : {
548
+ "type" : "children",
549
+ "selector" : "iframe"
550
+ }
551
+ }
552
+ },
553
+ {
554
+ "class": "HeaderImageRule",
555
+ "selector" : "figure",
556
+ "containsChild" : "img",
557
+ "properties" : {
558
+ "image.url" : {
559
+ "type" : "string",
560
+ "selector" : "img",
561
+ "attribute": "src"
562
+ }
563
+ }
564
+ },
565
+ {
566
+ "class": "SlideshowImageRule",
567
+ "selector" : "figure",
568
+ "properties" : {
569
+ "image.url" : {
570
+ "type" : "string",
571
+ "selector" : "img",
572
+ "attribute": "src"
573
+ },
574
+ "caption.title" : {
575
+ "type" : "string",
576
+ "selector" : "figcaption"
577
+ }
578
+ }
579
+ },
580
+ {
581
+ "class": "SlideshowRule",
582
+ "selector" : "figure.op-slideshow"
583
+ },
584
+ {
585
+ "class": "AdRule",
586
+ "selector" : "figure.op-ad",
587
+ "properties" : {
588
+ "ad.url" : {
589
+ "type" : "string",
590
+ "selector" : "iframe",
591
+ "attribute": "src"
592
+ },
593
+ "ad.height" : {
594
+ "type" : "int",
595
+ "selector" : "iframe",
596
+ "attribute": "height"
597
+ },
598
+ "ad.width" : {
599
+ "type" : "int",
600
+ "selector" : "iframe",
601
+ "attribute": "width"
602
+ },
603
+ "ad.embed" : {
604
+ "type" : "children",
605
+ "selector" : "iframe"
606
+ }
607
+ }
608
+ },
609
+ {
610
+ "class": "HeaderAdRule",
611
+ "selector" : "figure.op-ad",
612
+ "properties" : {
613
+ "ad.url" : {
614
+ "type" : "string",
615
+ "selector" : "iframe",
616
+ "attribute": "src"
617
+ },
618
+ "ad.height" : {
619
+ "type" : "int",
620
+ "selector" : "iframe",
621
+ "attribute": "height"
622
+ },
623
+ "ad.width" : {
624
+ "type" : "int",
625
+ "selector" : "iframe",
626
+ "attribute": "width"
627
+ },
628
+ "ad.embed" : {
629
+ "type" : "children",
630
+ "selector" : "iframe"
631
+ }
632
+ }
633
+ },
634
+ {
635
+ "class": "AnalyticsRule",
636
+ "selector" : "figure.op-tracker",
637
+ "properties" : {
638
+ "analytics.url" : {
639
+ "type" : "string",
640
+ "selector" : "iframe",
641
+ "attribute": "src"
642
+ },
643
+ "analytics.embed" : {
644
+ "type" : "children",
645
+ "selector" : "iframe"
646
+ }
647
+ }
648
+ },
649
+ {
650
+ "class": "PullquoteRule",
651
+ "selector" : "aside"
652
+ }
653
+ ]
654
+ }
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/instant-article-example.html ADDED
@@ -0,0 +1,200 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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:transformer" content="facebook-instant-articles-sdk-php"/>
8
+ <meta property="op:transformer:version" content="1.0.0"/>
9
+ <meta property="op:markup_version" content="v1.0"/>
10
+ <meta property="fb:use_automatic_ad_placement" content="true"/>
11
+ </head>
12
+ <body>
13
+ <article>
14
+ <header>
15
+ <figure>
16
+ <img src="https://jpeg.org/images/jpegls-home.jpg"/>
17
+ <figcaption><h1>Image Name</h1>Some text on text node<cite>Some caption to the image</cite></figcaption>
18
+ </figure>
19
+ <h1>Big Top Title</h1>
20
+ <h2>Smaller SubTitle</h2>
21
+ <time class="op-published" datetime="1984-08-14T19:30:00+00:00">August 14th, 7:30pm</time>
22
+ <time class="op-modified" datetime="2016-02-10T10:00:00+00:00">February 10th, 10:00am</time>
23
+ <address><a href="#" title="Title of author">Author Name</a>
24
+ Author more detailed description
25
+ Even more
26
+ </address>
27
+ <address><a href="http://facebook.com/author" rel="facebook">Author in FB</a>
28
+ Author user in facebook
29
+ </address>
30
+ <address><a title="PHP Programmer">Developer</a>
31
+ </address>
32
+ <h3 class="op-kicker">Some kicker of this article</h3>
33
+ </header>
34
+ <p>Some text to be within a paragraph for testing.</p>
35
+ <figure data-feedback="fb:likes">
36
+ <img src="http://mydomain.com/path/to/img.jpg"/>
37
+ <audio title="audio title" autoplay="autoplay" muted="muted">
38
+ <source src="http://foo.com/mp3"/>
39
+ </audio>
40
+ </figure>
41
+ <figure data-feedback="fb:comments">
42
+ <img src="http://mydomain.com/path/to/img.jpg"/>
43
+ <script type="application/json" class="op-geotag">
44
+ {
45
+ "type": "Feature",
46
+ "geometry": {
47
+ "type": "Point",
48
+ "coordinates": [23.166667, 89.216667]
49
+ },
50
+ "properties": {
51
+ "title": "Jessore, Bangladesh",
52
+ "radius": 750000,
53
+ "pivot": true,
54
+ "style": "satellite",
55
+ }
56
+ }
57
+ </script>
58
+ <audio title="audio title" autoplay="autoplay" muted="muted">
59
+ <source src="http://foo.com/mp3"/>
60
+ </audio>
61
+ </figure>
62
+ <figure data-feedback="fb:likes,fb:comments">
63
+ <img src="https://jpeg.org/images/jpegls-home.jpg"/>
64
+ <figcaption><h1>Image Name</h1>Some text on text node<cite>Some caption to the image</cite></figcaption>
65
+ </figure>
66
+ <p>Other text to be within a second paragraph for testing.</p>
67
+ <figure class="op-slideshow">
68
+ <figure>
69
+ <img src="https://jpeg.org/images/jpegls-home.jpg"/>
70
+ </figure>
71
+ <figure>
72
+ <img src="https://jpeg.org/images/jpegls-home2.jpg"/>
73
+ </figure>
74
+ <figure>
75
+ <img src="https://jpeg.org/images/jpegls-home3.jpg"/>
76
+ </figure>
77
+ <figcaption><h1>Image Name</h1>Some text on text node<cite>Some caption to the image</cite></figcaption>
78
+ <audio title="audio title" autoplay="autoplay" muted="muted">
79
+ <source src="http://foo.com/mp3"/>
80
+ </audio>
81
+ </figure>
82
+ <ol>
83
+ <li>First list item</li>
84
+ <li>One paragraph on the list</li>
85
+ <li>On the span</li>
86
+ <li>Text inside div?</li>
87
+ <li>Other paragraph on the li</li>
88
+ <li>Last list item</li>
89
+ </ol>
90
+ <p>Some text to be within a paragraph for testing.</p>
91
+ <figure class="op-interactive">
92
+ <iframe src="http://example.com/custom-interactive" class="column-width" height="60">
93
+ <h1>Some custom code</h1>
94
+ <script>alert("test");</script></iframe>
95
+ <figcaption>This graphic is awesome.</figcaption>
96
+ </figure>
97
+ <figure class="op-ad">
98
+ <iframe src="http://foo.com"></iframe>
99
+ </figure>
100
+ <blockquote>Some blockquotes creates <b>magic</b> in an article</blockquote>
101
+ <figure class="op-map">
102
+ <script type="application/json" class="op-geotag">
103
+ {
104
+ "type": "Feature",
105
+ "geometry":
106
+ {
107
+ "type": "Point",
108
+ "coordinates": [23.166667, 89.216667]
109
+ },
110
+ "properties":
111
+ {
112
+ "title": "Jessore, Bangladesh",
113
+ "radius": 750000,
114
+ "pivot": true,
115
+ "style": "satellite",
116
+ }
117
+ }
118
+ </script>
119
+ <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>
120
+
121
+
122
+ <cite class="op-vertical-center op-left">credit within caption</cite></figcaption>
123
+ <audio title="audio title" autoplay="autoplay" muted="muted">
124
+ <source src="http://foo.com/mp3"/>
125
+ </audio>
126
+ </figure>
127
+ <aside>
128
+ We can be more efficient about where we grow, what we grow, and how we grow.
129
+ <cite>Fruit Store Company</cite></aside>
130
+ <p>Other text to be within a second paragraph for testing.</p>
131
+ <figure class="op-tracker">
132
+ <iframe>
133
+ <h1>Some custom code</h1>
134
+ <script>alert("test");</script></iframe>
135
+ </figure>
136
+ <figure class="op-tracker">
137
+ <iframe>
138
+ <h1>Tracker with enclosing on the script</h1>
139
+ <div><script>alert("test");</script></div>
140
+ </iframe>
141
+ </figure>
142
+ <figure class="op-social">
143
+ <iframe>
144
+ <h1>Custom code for your social embed</h1>
145
+ <script>alert("test");</script></iframe>
146
+ </figure>
147
+ <figure data-mode="fullscreen" data-feedback="fb:likes,fb:comments">
148
+ <video data-fb-disable-autoplay="data-fb-disable-autoplay" controls="controls">
149
+ <source src="http://mydomain.com/path/to/video.mp4" type="video/mp4"/>
150
+ </video>
151
+ <figcaption class="op-vertical-below"><h1>Video 1 Title</h1>
152
+
153
+ <cite>Attribution Source</cite></figcaption>
154
+ <script type="application/json" class="op-geotag">
155
+ {
156
+ "type": "Feature",
157
+ "geometry": {
158
+ "type": "Point",
159
+ "coordinates": [ [23.166667, 89.216667], [23.166667, 89.216667] ]
160
+ },
161
+ "properties": {
162
+ "title": "Jessore, Bangladesh",
163
+ "radius": 750000,
164
+ "pivot": true,
165
+ "style": "satellite",
166
+ }
167
+ }
168
+ </script>
169
+ </figure>
170
+ <ul class="op-related-articles" title="The related ones in the middle">
171
+ <li>
172
+ <a href="http://example.com/article.html"></a>
173
+ </li>
174
+ <li data-sponsored="true">
175
+ <a href="http://example.com/sponsored-article.html"></a>
176
+ </li>
177
+ <li>
178
+ <a href="http://example.com/another-article.html"></a>
179
+ </li>
180
+ </ul>
181
+ <footer>
182
+ <aside>
183
+ <p>Some plaintext credits to<a href="http://facebook.com/author" rel="facebook">Author</a></p>
184
+ <p>Paragraph text as credits</p>
185
+ </aside>
186
+ <ul class="op-related-articles" title="The related ones in the footer">
187
+ <li>
188
+ <a href="http://example.com/article.html"></a>
189
+ </li>
190
+ <li data-sponsored="true">
191
+ <a href="http://example.com/sponsored-article.html"></a>
192
+ </li>
193
+ <li>
194
+ <a href="http://example.com/another-article.html"></a>
195
+ </li>
196
+ </ul>
197
+ </footer>
198
+ </article>
199
+ </body>
200
+ </html>
vendor/facebook/facebook-instant-articles-sdk-php/tests/bootstrap.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php
2
+ $autoloader = require __DIR__ . '/../vendor/autoload.php';
3
+ $autoloader->add('Facebook\\', __DIR__.'/../src');
vendor/facebook/php-sdk-v4/LICENSE ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright 2014 Facebook, Inc.
2
+
3
+ You are hereby granted a non-exclusive, worldwide, royalty-free license to
4
+ use, copy, modify, and distribute this software in source code or binary
5
+ form for use in connection with the web services and APIs provided by
6
+ Facebook.
7
+
8
+ As with any software that integrates with the Facebook platform, your use
9
+ of this software is subject to the Facebook Developer Principles and
10
+ Policies [http://developers.facebook.com/policy/]. This copyright notice
11
+ shall be included in all copies or substantial portions of the software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
16
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19
+ DEALINGS IN THE SOFTWARE.
vendor/facebook/php-sdk-v4/composer.json ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "facebook/php-sdk-v4",
3
+ "description": "Facebook SDK for PHP",
4
+ "keywords": ["facebook", "sdk"],
5
+ "type": "library",
6
+ "homepage": "https://github.com/facebook/facebook-php-sdk-v4",
7
+ "license": "Facebook Platform",
8
+ "authors": [
9
+ {
10
+ "name": "Facebook",
11
+ "homepage": "https://github.com/facebook/facebook-php-sdk-v4/contributors"
12
+ }
13
+ ],
14
+ "require": {
15
+ "php": ">=5.4.0",
16
+ "ext-mbstring": "*"
17
+ },
18
+ "require-dev": {
19
+ "phpunit/phpunit": "~4.0",
20
+ "mockery/mockery": "~0.8",
21
+ "guzzlehttp/guzzle": "~5.0"
22
+ },
23
+ "suggest": {
24
+ "guzzlehttp/guzzle": "Allows for implementation of the Guzzle HTTP client"
25
+ },
26
+ "autoload": {
27
+ "psr-4": {
28
+ "Facebook\\": "src/Facebook/"
29
+ }
30
+ },
31
+ "autoload-dev": {
32
+ "psr-4": {
33
+ "Facebook\\Tests\\": "tests/"
34
+ }
35
+ },
36
+ "extra": {
37
+ "branch-alias": {
38
+ "dev-master": "5.x-dev"
39
+ }
40
+ }
41
+ }
vendor/facebook/php-sdk-v4/src/Facebook/Authentication/AccessToken.php ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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\Authentication;
25
+
26
+ /**
27
+ * Class AccessToken
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class AccessToken
32
+ {
33
+ /**
34
+ * The access token value.
35
+ *
36
+ * @var string
37
+ */
38
+ protected $value = '';
39
+
40
+ /**
41
+ * Date when token expires.
42
+ *
43
+ * @var \DateTime|null
44
+ */
45
+ protected $expiresAt;
46
+
47
+ /**
48
+ * Create a new access token entity.
49
+ *
50
+ * @param string $accessToken
51
+ * @param int $expiresAt
52
+ */
53
+ public function __construct($accessToken, $expiresAt = 0)
54
+ {
55
+ $this->value = $accessToken;
56
+ if ($expiresAt) {
57
+ $this->setExpiresAtFromTimeStamp($expiresAt);
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Generate an app secret proof to sign a request to Graph.
63
+ *
64
+ * @param string $appSecret The app secret.
65
+ *
66
+ * @return string
67
+ */
68
+ public function getAppSecretProof($appSecret)
69
+ {
70
+ return hash_hmac('sha256', $this->value, $appSecret);
71
+ }
72
+
73
+ /**
74
+ * Getter for expiresAt.
75
+ *
76
+ * @return \DateTime|null
77
+ */
78
+ public function getExpiresAt()
79
+ {
80
+ return $this->expiresAt;
81
+ }
82
+
83
+ /**
84
+ * Determines whether or not this is an app access token.
85
+ *
86
+ * @return bool
87
+ */
88
+ public function isAppAccessToken()
89
+ {
90
+ return strpos($this->value, '|') !== false;
91
+ }
92
+
93
+ /**
94
+ * Determines whether or not this is a long-lived token.
95
+ *
96
+ * @return bool
97
+ */
98
+ public function isLongLived()
99
+ {
100
+ if ($this->expiresAt) {
101
+ return $this->expiresAt->getTimestamp() > time() + (60 * 60 * 2);
102
+ }
103
+
104
+ if ($this->isAppAccessToken()) {
105
+ return true;
106
+ }
107
+
108
+ return false;
109
+ }
110
+
111
+ /**
112
+ * Checks the expiration of the access token.
113
+ *
114
+ * @return boolean|null
115
+ */
116
+ public function isExpired()
117
+ {
118
+ if ($this->getExpiresAt() instanceof \DateTime) {
119
+ return $this->getExpiresAt()->getTimestamp() < time();
120
+ }
121
+
122
+ if ($this->isAppAccessToken()) {
123
+ return false;
124
+ }
125
+
126
+ return null;
127
+ }
128
+
129
+ /**
130
+ * Returns the access token as a string.
131
+ *
132
+ * @return string
133
+ */
134
+ public function getValue()
135
+ {
136
+ return $this->value;
137
+ }
138
+
139
+ /**
140
+ * Returns the access token as a string.
141
+ *
142
+ * @return string
143
+ */
144
+ public function __toString()
145
+ {
146
+ return $this->getValue();
147
+ }
148
+
149
+ /**
150
+ * Setter for expires_at.
151
+ *
152
+ * @param int $timeStamp
153
+ */
154
+ protected function setExpiresAtFromTimeStamp($timeStamp)
155
+ {
156
+ $dt = new \DateTime();
157
+ $dt->setTimestamp($timeStamp);
158
+ $this->expiresAt = $dt;
159
+ }
160
+ }
vendor/facebook/php-sdk-v4/src/Facebook/Authentication/AccessTokenMetadata.php ADDED
@@ -0,0 +1,390 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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\Authentication;
25
+
26
+ use Facebook\Exceptions\FacebookSDKException;
27
+
28
+ /**
29
+ * Class AccessTokenMetadata
30
+ *
31
+ * Represents metadata from an access token.
32
+ *
33
+ * @package Facebook
34
+ * @see https://developers.facebook.com/docs/graph-api/reference/debug_token
35
+ */
36
+ class AccessTokenMetadata
37
+ {
38
+ /**
39
+ * The access token metadata.
40
+ *
41
+ * @var array
42
+ */
43
+ protected $metadata = [];
44
+
45
+ /**
46
+ * Properties that should be cast as DateTime objects.
47
+ *
48
+ * @var array
49
+ */
50
+ protected static $dateProperties = ['expires_at', 'issued_at'];
51
+
52
+ /**
53
+ * @param array $metadata
54
+ *
55
+ * @throws FacebookSDKException
56
+ */
57
+ public function __construct(array $metadata)
58
+ {
59
+ if (!isset($metadata['data'])) {
60
+ throw new FacebookSDKException('Unexpected debug token response data.', 401);
61
+ }
62
+
63
+ $this->metadata = $metadata['data'];
64
+
65
+ $this->castTimestampsToDateTime();
66
+ }
67
+
68
+ /**
69
+ * Returns a value from the metadata.
70
+ *
71
+ * @param string $field The property to retrieve.
72
+ * @param mixed $default The default to return if the property doesn't exist.
73
+ *
74
+ * @return mixed
75
+ */
76
+ public function getField($field, $default = null)
77
+ {
78
+ if (isset($this->metadata[$field])) {
79
+ return $this->metadata[$field];
80
+ }
81
+
82
+ return $default;
83
+ }
84
+
85
+ /**
86
+ * Returns a value from the metadata.
87
+ *
88
+ * @param string $field The property to retrieve.
89
+ * @param mixed $default The default to return if the property doesn't exist.
90
+ *
91
+ * @return mixed
92
+ *
93
+ * @deprecated 5.0.0 getProperty() has been renamed to getField()
94
+ * @todo v6: Remove this method
95
+ */
96
+ public function getProperty($field, $default = null)
97
+ {
98
+ return $this->getField($field, $default);
99
+ }
100
+
101
+ /**
102
+ * Returns a value from a child property in the metadata.
103
+ *
104
+ * @param string $parentField The parent property.
105
+ * @param string $field The property to retrieve.
106
+ * @param mixed $default The default to return if the property doesn't exist.
107
+ *
108
+ * @return mixed
109
+ */
110
+ public function getChildProperty($parentField, $field, $default = null)
111
+ {
112
+ if (!isset($this->metadata[$parentField])) {
113
+ return $default;
114
+ }
115
+
116
+ if (!isset($this->metadata[$parentField][$field])) {
117
+ return $default;
118
+ }
119
+
120
+ return $this->metadata[$parentField][$field];
121
+ }
122
+
123
+ /**
124
+ * Returns a value from the error metadata.
125
+ *
126
+ * @param string $field The property to retrieve.
127
+ * @param mixed $default The default to return if the property doesn't exist.
128
+ *
129
+ * @return mixed
130
+ */
131
+ public function getErrorProperty($field, $default = null)
132
+ {
133
+ return $this->getChildProperty('error', $field, $default);
134
+ }
135
+
136
+ /**
137
+ * Returns a value from the "metadata" metadata. *Brain explodes*
138
+ *
139
+ * @param string $field The property to retrieve.
140
+ * @param mixed $default The default to return if the property doesn't exist.
141
+ *
142
+ * @return mixed
143
+ */
144
+ public function getMetadataProperty($field, $default = null)
145
+ {
146
+ return $this->getChildProperty('metadata', $field, $default);
147
+ }
148
+
149
+ /**
150
+ * The ID of the application this access token is for.
151
+ *
152
+ * @return string|null
153
+ */
154
+ public function getAppId()
155
+ {
156
+ return $this->getField('app_id');
157
+ }
158
+
159
+ /**
160
+ * Name of the application this access token is for.
161
+ *
162
+ * @return string|null
163
+ */
164
+ public function getApplication()
165
+ {
166
+ return $this->getField('application');
167
+ }
168
+
169
+ /**
170
+ * Any error that a request to the graph api
171
+ * would return due to the access token.
172
+ *
173
+ * @return bool|null
174
+ */
175
+ public function isError()
176
+ {
177
+ return $this->getField('error') !== null;
178
+ }
179
+
180
+ /**
181
+ * The error code for the error.
182
+ *
183
+ * @return int|null
184
+ */
185
+ public function getErrorCode()
186
+ {
187
+ return $this->getErrorProperty('code');
188
+ }
189
+
190
+ /**
191
+ * The error message for the error.
192
+ *
193
+ * @return string|null
194
+ */
195
+ public function getErrorMessage()
196
+ {
197
+ return $this->getErrorProperty('message');
198
+ }
199
+
200
+ /**
201
+ * The error subcode for the error.
202
+ *
203
+ * @return int|null
204
+ */
205
+ public function getErrorSubcode()
206
+ {
207
+ return $this->getErrorProperty('subcode');
208
+ }
209
+
210
+ /**
211
+ * DateTime when this access token expires.
212
+ *
213
+ * @return \DateTime|null
214
+ */
215
+ public function getExpiresAt()
216
+ {
217
+ return $this->getField('expires_at');
218
+ }
219
+
220
+ /**
221
+ * Whether the access token is still valid or not.
222
+ *
223
+ * @return boolean|null
224
+ */
225
+ public function getIsValid()
226
+ {
227
+ return $this->getField('is_valid');
228
+ }
229
+
230
+ /**
231
+ * DateTime when this access token was issued.
232
+ *
233
+ * Note that the issued_at field is not returned
234
+ * for short-lived access tokens.
235
+ *
236
+ * @see https://developers.facebook.com/docs/facebook-login/access-tokens#debug
237
+ *
238
+ * @return \DateTime|null
239
+ */
240
+ public function getIssuedAt()
241
+ {
242
+ return $this->getField('issued_at');
243
+ }
244
+
245
+ /**
246
+ * General metadata associated with the access token.
247
+ * Can contain data like 'sso', 'auth_type', 'auth_nonce'.
248
+ *
249
+ * @return array|null
250
+ */
251
+ public function getMetadata()
252
+ {
253
+ return $this->getField('metadata');
254
+ }
255
+
256
+ /**
257
+ * The 'sso' child property from the 'metadata' parent property.
258
+ *
259
+ * @return string|null
260
+ */
261
+ public function getSso()
262
+ {
263
+ return $this->getMetadataProperty('sso');
264
+ }
265
+
266
+ /**
267
+ * The 'auth_type' child property from the 'metadata' parent property.
268
+ *
269
+ * @return string|null
270
+ */
271
+ public function getAuthType()
272
+ {
273
+ return $this->getMetadataProperty('auth_type');
274
+ }
275
+
276
+ /**
277
+ * The 'auth_nonce' child property from the 'metadata' parent property.
278
+ *
279
+ * @return string|null
280
+ */
281
+ public function getAuthNonce()
282
+ {
283
+ return $this->getMetadataProperty('auth_nonce');
284
+ }
285
+
286
+ /**
287
+ * For impersonated access tokens, the ID of
288
+ * the page this token contains.
289
+ *
290
+ * @return string|null
291
+ */
292
+ public function getProfileId()
293
+ {
294
+ return $this->getField('profile_id');
295
+ }
296
+
297
+ /**
298
+ * List of permissions that the user has granted for
299
+ * the app in this access token.
300
+ *
301
+ * @return array
302
+ */
303
+ public function getScopes()
304
+ {
305
+ return $this->getField('scopes');
306
+ }
307
+
308
+ /**
309
+ * The ID of the user this access token is for.
310
+ *
311
+ * @return string|null
312
+ */
313
+ public function getUserId()
314
+ {
315
+ return $this->getField('user_id');
316
+ }
317
+
318
+ /**
319
+ * Ensures the app ID from the access token
320
+ * metadata is what we expect.
321
+ *
322
+ * @param string $appId
323
+ *
324
+ * @throws FacebookSDKException
325
+ */
326
+ public function validateAppId($appId)
327
+ {
328
+ if ($this->getAppId() !== $appId) {
329
+ throw new FacebookSDKException('Access token metadata contains unexpected app ID.', 401);
330
+ }
331
+ }
332
+
333
+ /**
334
+ * Ensures the user ID from the access token
335
+ * metadata is what we expect.
336
+ *
337
+ * @param string $userId
338
+ *
339
+ * @throws FacebookSDKException
340
+ */
341
+ public function validateUserId($userId)
342
+ {
343
+ if ($this->getUserId() !== $userId) {
344
+ throw new FacebookSDKException('Access token metadata contains unexpected user ID.', 401);
345
+ }
346
+ }
347
+
348
+ /**
349
+ * Ensures the access token has not expired yet.
350
+ *
351
+ * @throws FacebookSDKException
352
+ */
353
+ public function validateExpiration()
354
+ {
355
+ if (!$this->getExpiresAt() instanceof \DateTime) {
356
+ return;
357
+ }
358
+
359
+ if ($this->getExpiresAt()->getTimestamp() < time()) {
360
+ throw new FacebookSDKException('Inspection of access token metadata shows that the access token has expired.', 401);
361
+ }
362
+ }
363
+
364
+ /**
365
+ * Converts a unix timestamp into a DateTime entity.
366
+ *
367
+ * @param int $timestamp
368
+ *
369
+ * @return \DateTime
370
+ */
371
+ private function convertTimestampToDateTime($timestamp)
372
+ {
373
+ $dt = new \DateTime();
374
+ $dt->setTimestamp($timestamp);
375
+
376
+ return $dt;
377
+ }
378
+
379
+ /**
380
+ * Casts the unix timestamps as DateTime entities.
381
+ */
382
+ private function castTimestampsToDateTime()
383
+ {
384
+ foreach (static::$dateProperties as $key) {
385
+ if (isset($this->metadata[$key]) && $this->metadata[$key] !== 0) {
386
+ $this->metadata[$key] = $this->convertTimestampToDateTime($this->metadata[$key]);
387
+ }
388
+ }
389
+ }
390
+ }
vendor/facebook/php-sdk-v4/src/Facebook/Authentication/OAuth2Client.php ADDED
@@ -0,0 +1,292 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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\Authentication;
25
+
26
+ use Facebook\Facebook;
27
+ use Facebook\FacebookApp;
28
+ use Facebook\FacebookRequest;
29
+ use Facebook\FacebookResponse;
30
+ use Facebook\FacebookClient;
31
+ use Facebook\Exceptions\FacebookResponseException;
32
+ use Facebook\Exceptions\FacebookSDKException;
33
+
34
+ /**
35
+ * Class OAuth2Client
36
+ *
37
+ * @package Facebook
38
+ */
39
+ class OAuth2Client
40
+ {
41
+ /**
42
+ * @const string The base authorization URL.
43
+ */
44
+ const BASE_AUTHORIZATION_URL = 'https://www.facebook.com';
45
+
46
+ /**
47
+ * The FacebookApp entity.
48
+ *
49
+ * @var FacebookApp
50
+ */
51
+ protected $app;
52
+
53
+ /**
54
+ * The Facebook client.
55
+ *
56
+ * @var FacebookClient
57
+ */
58
+ protected $client;
59
+
60
+ /**
61
+ * The version of the Graph API to use.
62
+ *
63
+ * @var string
64
+ */
65
+ protected $graphVersion;
66
+
67
+ /**
68
+ * The last request sent to Graph.
69
+ *
70
+ * @var FacebookRequest|null
71
+ */
72
+ protected $lastRequest;
73
+
74
+ /**
75
+ * @param FacebookApp $app
76
+ * @param FacebookClient $client
77
+ * @param string|null $graphVersion The version of the Graph API to use.
78
+ */
79
+ public function __construct(FacebookApp $app, FacebookClient $client, $graphVersion = null)
80
+ {
81
+ $this->app = $app;
82
+ $this->client = $client;
83
+ $this->graphVersion = $graphVersion ?: Facebook::DEFAULT_GRAPH_VERSION;
84
+ }
85
+
86
+ /**
87
+ * Returns the last FacebookRequest that was sent.
88
+ * Useful for debugging and testing.
89
+ *
90
+ * @return FacebookRequest|null
91
+ */
92
+ public function getLastRequest()
93
+ {
94
+ return $this->lastRequest;
95
+ }
96
+
97
+ /**
98
+ * Get the metadata associated with the access token.
99
+ *
100
+ * @param AccessToken|string $accessToken The access token to debug.
101
+ *
102
+ * @return AccessTokenMetadata
103
+ */
104
+ public function debugToken($accessToken)
105
+ {
106
+ $accessToken = $accessToken instanceof AccessToken ? $accessToken->getValue() : $accessToken;
107
+ $params = ['input_token' => $accessToken];
108
+
109
+ $this->lastRequest = new FacebookRequest(
110
+ $this->app,
111
+ $this->app->getAccessToken(),
112
+ 'GET',
113
+ '/debug_token',
114
+ $params,
115
+ null,
116
+ $this->graphVersion
117
+ );
118
+ $response = $this->client->sendRequest($this->lastRequest);
119
+ $metadata = $response->getDecodedBody();
120
+
121
+ return new AccessTokenMetadata($metadata);
122
+ }
123
+
124
+ /**
125
+ * Generates an authorization URL to begin the process of authenticating a user.
126
+ *
127
+ * @param string $redirectUrl The callback URL to redirect to.
128
+ * @param array $scope An array of permissions to request.
129
+ * @param string $state The CSPRNG-generated CSRF value.
130
+ * @param array $params An array of parameters to generate URL.
131
+ * @param string $separator The separator to use in http_build_query().
132
+ *
133
+ * @return string
134
+ */
135
+ public function getAuthorizationUrl($redirectUrl, $state, array $scope = [], array $params = [], $separator = '&')
136
+ {
137
+ $params += [
138
+ 'client_id' => $this->app->getId(),
139
+ 'state' => $state,
140
+ 'response_type' => 'code',
141
+ 'sdk' => 'php-sdk-' . Facebook::VERSION,
142
+ 'redirect_uri' => $redirectUrl,
143
+ 'scope' => implode(',', $scope)
144
+ ];
145
+
146
+ return static::BASE_AUTHORIZATION_URL . '/' . $this->graphVersion . '/dialog/oauth?' . http_build_query($params, null, $separator);
147
+ }
148
+
149
+ /**
150
+ * Get a valid access token from a code.
151
+ *
152
+ * @param string $code
153
+ * @param string $redirectUri
154
+ *
155
+ * @return AccessToken
156
+ *
157
+ * @throws FacebookSDKException
158
+ */
159
+ public function getAccessTokenFromCode($code, $redirectUri = '')
160
+ {
161
+ $params = [
162
+ 'code' => $code,
163
+ 'redirect_uri' => $redirectUri,
164
+ ];
165
+
166
+ return $this->requestAnAccessToken($params);
167
+ }
168
+
169
+ /**
170
+ * Exchanges a short-lived access token with a long-lived access token.
171
+ *
172
+ * @param AccessToken|string $accessToken
173
+ *
174
+ * @return AccessToken
175
+ *
176
+ * @throws FacebookSDKException
177
+ */
178
+ public function getLongLivedAccessToken($accessToken)
179
+ {
180
+ $accessToken = $accessToken instanceof AccessToken ? $accessToken->getValue() : $accessToken;
181
+ $params = [
182
+ 'grant_type' => 'fb_exchange_token',
183
+ 'fb_exchange_token' => $accessToken,
184
+ ];
185
+
186
+ return $this->requestAnAccessToken($params);
187
+ }
188
+
189
+ /**
190
+ * Get a valid code from an access token.
191
+ *
192
+ * @param AccessToken|string $accessToken
193
+ * @param string $redirectUri
194
+ *
195
+ * @return AccessToken
196
+ *
197
+ * @throws FacebookSDKException
198
+ */
199
+ public function getCodeFromLongLivedAccessToken($accessToken, $redirectUri = '')
200
+ {
201
+ $params = [
202
+ 'redirect_uri' => $redirectUri,
203
+ ];
204
+
205
+ $response = $this->sendRequestWithClientParams('/oauth/client_code', $params, $accessToken);
206
+ $data = $response->getDecodedBody();
207
+
208
+ if (!isset($data['code'])) {
209
+ throw new FacebookSDKException('Code was not returned from Graph.', 401);
210
+ }
211
+
212
+ return $data['code'];
213
+ }
214
+
215
+ /**
216
+ * Send a request to the OAuth endpoint.
217
+ *
218
+ * @param array $params
219
+ *
220
+ * @return AccessToken
221
+ *
222
+ * @throws FacebookSDKException
223
+ */
224
+ protected function requestAnAccessToken(array $params)
225
+ {
226
+ $response = $this->sendRequestWithClientParams('/oauth/access_token', $params);
227
+ $data = $response->getDecodedBody();
228
+
229
+ if (!isset($data['access_token'])) {
230
+ throw new FacebookSDKException('Access token was not returned from Graph.', 401);
231
+ }
232
+
233
+ // Graph returns two different key names for expiration time
234
+ // on the same endpoint. Doh! :/
235
+ $expiresAt = 0;
236
+ if (isset($data['expires'])) {
237
+ // For exchanging a short lived token with a long lived token.
238
+ // The expiration time in seconds will be returned as "expires".
239
+ $expiresAt = time() + $data['expires'];
240
+ } elseif (isset($data['expires_in'])) {
241
+ // For exchanging a code for a short lived access token.
242
+ // The expiration time in seconds will be returned as "expires_in".
243
+ // See: https://developers.facebook.com/docs/facebook-login/access-tokens#long-via-code
244
+ $expiresAt = time() + $data['expires_in'];
245
+ }
246
+
247
+ return new AccessToken($data['access_token'], $expiresAt);
248
+ }
249
+
250
+ /**
251
+ * Send a request to Graph with an app access token.
252
+ *
253
+ * @param string $endpoint
254
+ * @param array $params
255
+ * @param AccessToken|string|null $accessToken
256
+ *
257
+ * @return FacebookResponse
258
+ *
259
+ * @throws FacebookResponseException
260
+ */
261
+ protected function sendRequestWithClientParams($endpoint, array $params, $accessToken = null)
262
+ {
263
+ $params += $this->getClientParams();
264
+
265
+ $accessToken = $accessToken ?: $this->app->getAccessToken();
266
+
267
+ $this->lastRequest = new FacebookRequest(
268
+ $this->app,
269
+ $accessToken,
270
+ 'GET',
271
+ $endpoint,
272
+ $params,
273
+ null,
274
+ $this->graphVersion
275
+ );
276
+
277
+ return $this->client->sendRequest($this->lastRequest);
278
+ }
279
+
280
+ /**
281
+ * Returns the client_* params for OAuth requests.
282
+ *
283
+ * @return array
284
+ */
285
+ protected function getClientParams()
286
+ {
287
+ return [
288
+ 'client_id' => $this->app->getId(),
289
+ 'client_secret' => $this->app->getSecret(),
290
+ ];
291
+ }
292
+ }
vendor/facebook/php-sdk-v4/src/Facebook/Exceptions/FacebookAuthenticationException.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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\Exceptions;
25
+
26
+ /**
27
+ * Class FacebookAuthenticationException
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class FacebookAuthenticationException extends FacebookSDKException
32
+ {
33
+ }
vendor/facebook/php-sdk-v4/src/Facebook/Exceptions/FacebookAuthorizationException.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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\Exceptions;
25
+
26
+ /**
27
+ * Class FacebookAuthorizationException
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class FacebookAuthorizationException extends FacebookSDKException
32
+ {
33
+ }
vendor/facebook/php-sdk-v4/src/Facebook/Exceptions/FacebookClientException.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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\Exceptions;
25
+
26
+ /**
27
+ * Class FacebookClientException
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class FacebookClientException extends FacebookSDKException
32
+ {
33
+ }
vendor/facebook/php-sdk-v4/src/Facebook/Exceptions/FacebookOtherException.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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\Exceptions;
25
+
26
+ /**
27
+ * Class FacebookOtherException
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class FacebookOtherException extends FacebookSDKException
32
+ {
33
+ }
vendor/facebook/php-sdk-v4/src/Facebook/Exceptions/FacebookResponseException.php ADDED
@@ -0,0 +1,214 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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\Exceptions;
25
+
26
+ use Facebook\FacebookResponse;
27
+
28
+ /**
29
+ * Class FacebookResponseException
30
+ *
31
+ * @package Facebook
32
+ */
33
+ class FacebookResponseException extends FacebookSDKException
34
+ {
35
+ /**
36
+ * @var FacebookResponse The response that threw the exception.
37
+ */
38
+ protected $response;
39
+
40
+ /**
41
+ * @var array Decoded response.
42
+ */
43
+ protected $responseData;
44
+
45
+ /**
46
+ * Creates a FacebookResponseException.
47
+ *
48
+ * @param FacebookResponse $response The response that threw the exception.
49
+ * @param FacebookSDKException $previousException The more detailed exception.
50
+ */
51
+ public function __construct(FacebookResponse $response, FacebookSDKException $previousException = null)
52
+ {
53
+ $this->response = $response;
54
+ $this->responseData = $response->getDecodedBody();
55
+
56
+ $errorMessage = $this->get('message', 'Unknown error from Graph.');
57
+ $errorCode = $this->get('code', -1);
58
+
59
+ parent::__construct($errorMessage, $errorCode, $previousException);
60
+ }
61
+
62
+ /**
63
+ * A factory for creating the appropriate exception based on the response from Graph.
64
+ *
65
+ * @param FacebookResponse $response The response that threw the exception.
66
+ *
67
+ * @return FacebookResponseException
68
+ */
69
+ public static function create(FacebookResponse $response)
70
+ {
71
+ $data = $response->getDecodedBody();
72
+
73
+ if (!isset($data['error']['code']) && isset($data['code'])) {
74
+ $data = ['error' => $data];
75
+ }
76
+
77
+ $code = isset($data['error']['code']) ? $data['error']['code'] : null;
78
+ $message = isset($data['error']['message']) ? $data['error']['message'] : 'Unknown error from Graph.';
79
+
80
+ if (isset($data['error']['error_subcode'])) {
81
+ switch ($data['error']['error_subcode']) {
82
+ // Other authentication issues
83
+ case 458:
84
+ case 459:
85
+ case 460:
86
+ case 463:
87
+ case 464:
88
+ case 467:
89
+ return new static($response, new FacebookAuthenticationException($message, $code));
90
+ // Video upload resumable error
91
+ case 1363030:
92
+ case 1363019:
93
+ case 1363037:
94
+ case 1363033:
95
+ case 1363021:
96
+ case 1363041:
97
+ return new static($response, new FacebookResumableUploadException($message, $code));
98
+ }
99
+ }
100
+
101
+ switch ($code) {
102
+ // Login status or token expired, revoked, or invalid
103
+ case 100:
104
+ case 102:
105
+ case 190:
106
+ return new static($response, new FacebookAuthenticationException($message, $code));
107
+
108
+ // Server issue, possible downtime
109
+ case 1:
110
+ case 2:
111
+ return new static($response, new FacebookServerException($message, $code));
112
+
113
+ // API Throttling
114
+ case 4:
115
+ case 17:
116
+ case 341:
117
+ return new static($response, new FacebookThrottleException($message, $code));
118
+
119
+ // Duplicate Post
120
+ case 506:
121
+ return new static($response, new FacebookClientException($message, $code));
122
+ }
123
+
124
+ // Missing Permissions
125
+ if ($code == 10 || ($code >= 200 && $code <= 299)) {
126
+ return new static($response, new FacebookAuthorizationException($message, $code));
127
+ }
128
+
129
+ // OAuth authentication error
130
+ if (isset($data['error']['type']) && $data['error']['type'] === 'OAuthException') {
131
+ return new static($response, new FacebookAuthenticationException($message, $code));
132
+ }
133
+
134
+ // All others
135
+ return new static($response, new FacebookOtherException($message, $code));
136
+ }
137
+
138
+ /**
139
+ * Checks isset and returns that or a default value.
140
+ *
141
+ * @param string $key
142
+ * @param mixed $default
143
+ *
144
+ * @return mixed
145
+ */
146
+ private function get($key, $default = null)
147
+ {
148
+ if (isset($this->responseData['error'][$key])) {
149
+ return $this->responseData['error'][$key];
150
+ }
151
+
152
+ return $default;
153
+ }
154
+
155
+ /**
156
+ * Returns the HTTP status code
157
+ *
158
+ * @return int
159
+ */
160
+ public function getHttpStatusCode()
161
+ {
162
+ return $this->response->getHttpStatusCode();
163
+ }
164
+
165
+ /**
166
+ * Returns the sub-error code
167
+ *
168
+ * @return int
169
+ */
170
+ public function getSubErrorCode()
171
+ {
172
+ return $this->get('error_subcode', -1);
173
+ }
174
+
175
+ /**
176
+ * Returns the error type
177
+ *
178
+ * @return string
179
+ */
180
+ public function getErrorType()
181
+ {
182
+ return $this->get('type', '');
183
+ }
184
+
185
+ /**
186
+ * Returns the raw response used to create the exception.
187
+ *
188
+ * @return string
189
+ */
190
+ public function getRawResponse()
191
+ {
192
+ return $this->response->getBody();
193
+ }
194
+
195
+ /**
196
+ * Returns the decoded response used to create the exception.
197
+ *
198
+ * @return array
199
+ */
200
+ public function getResponseData()
201
+ {
202
+ return $this->responseData;
203
+ }
204
+
205
+ /**
206
+ * Returns the response entity used to create the exception.
207
+ *
208
+ * @return FacebookResponse
209
+ */
210
+ public function getResponse()
211
+ {
212
+ return $this->response;
213
+ }
214
+ }
vendor/facebook/php-sdk-v4/src/Facebook/Exceptions/FacebookResumableUploadException.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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\Exceptions;
25
+
26
+ /**
27
+ * Class FacebookResumableUploadException
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class FacebookResumableUploadException extends FacebookSDKException
32
+ {
33
+ }
vendor/facebook/php-sdk-v4/src/Facebook/Exceptions/FacebookSDKException.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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\Exceptions;
25
+
26
+ /**
27
+ * Class FacebookSDKException
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class FacebookSDKException extends \Exception
32
+ {
33
+ }
vendor/facebook/php-sdk-v4/src/Facebook/Exceptions/FacebookServerException.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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\Exceptions;
25
+
26
+ /**
27
+ * Class FacebookServerException
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class FacebookServerException extends FacebookSDKException
32
+ {
33
+ }
vendor/facebook/php-sdk-v4/src/Facebook/Exceptions/FacebookThrottleException.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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\Exceptions;
25
+
26
+ /**
27
+ * Class FacebookThrottleException
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class FacebookThrottleException extends FacebookSDKException
32
+ {
33
+ }
vendor/facebook/php-sdk-v4/src/Facebook/Facebook.php ADDED
@@ -0,0 +1,614 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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;
25
+
26
+ use Facebook\Authentication\AccessToken;
27
+ use Facebook\Authentication\OAuth2Client;
28
+ use Facebook\FileUpload\FacebookFile;
29
+ use Facebook\FileUpload\FacebookResumableUploader;
30
+ use Facebook\FileUpload\FacebookTransferChunk;
31
+ use Facebook\FileUpload\FacebookVideo;
32
+ use Facebook\GraphNodes\GraphEdge;
33
+ use Facebook\Url\UrlDetectionInterface;
34
+ use Facebook\Url\FacebookUrlDetectionHandler;
35
+ use Facebook\PseudoRandomString\PseudoRandomStringGeneratorFactory;
36
+ use Facebook\PseudoRandomString\PseudoRandomStringGeneratorInterface;
37
+ use Facebook\HttpClients\HttpClientsFactory;
38
+ use Facebook\PersistentData\PersistentDataFactory;
39
+ use Facebook\PersistentData\PersistentDataInterface;
40
+ use Facebook\Helpers\FacebookCanvasHelper;
41
+ use Facebook\Helpers\FacebookJavaScriptHelper;
42
+ use Facebook\Helpers\FacebookPageTabHelper;
43
+ use Facebook\Helpers\FacebookRedirectLoginHelper;
44
+ use Facebook\Exceptions\FacebookSDKException;
45
+
46
+ /**
47
+ * Class Facebook
48
+ *
49
+ * @package Facebook
50
+ */
51
+ class Facebook
52
+ {
53
+ /**
54
+ * @const string Version number of the Facebook PHP SDK.
55
+ */
56
+ const VERSION = '5.1.2';
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.
65
+ */
66
+ const APP_ID_ENV_NAME = 'FACEBOOK_APP_ID';
67
+
68
+ /**
69
+ * @const string The name of the environment variable that contains the app secret.
70
+ */
71
+ const APP_SECRET_ENV_NAME = 'FACEBOOK_APP_SECRET';
72
+
73
+ /**
74
+ * @var FacebookApp The FacebookApp entity.
75
+ */
76
+ protected $app;
77
+
78
+ /**
79
+ * @var FacebookClient The Facebook client service.
80
+ */
81
+ protected $client;
82
+
83
+ /**
84
+ * @var OAuth2Client The OAuth 2.0 client service.
85
+ */
86
+ protected $oAuth2Client;
87
+
88
+ /**
89
+ * @var UrlDetectionInterface|null The URL detection handler.
90
+ */
91
+ protected $urlDetectionHandler;
92
+
93
+ /**
94
+ * @var PseudoRandomStringGeneratorInterface|null The cryptographically secure pseudo-random string generator.
95
+ */
96
+ protected $pseudoRandomStringGenerator;
97
+
98
+ /**
99
+ * @var AccessToken|null The default access token to use with requests.
100
+ */
101
+ protected $defaultAccessToken;
102
+
103
+ /**
104
+ * @var string|null The default Graph version we want to use.
105
+ */
106
+ protected $defaultGraphVersion;
107
+
108
+ /**
109
+ * @var PersistentDataInterface|null The persistent data handler.
110
+ */
111
+ protected $persistentDataHandler;
112
+
113
+ /**
114
+ * @var FacebookResponse|FacebookBatchResponse|null Stores the last request made to Graph.
115
+ */
116
+ protected $lastResponse;
117
+
118
+ /**
119
+ * Instantiates a new Facebook super-class object.
120
+ *
121
+ * @param array $config
122
+ *
123
+ * @throws FacebookSDKException
124
+ */
125
+ public function __construct(array $config = [])
126
+ {
127
+ $config = array_merge([
128
+ 'app_id' => getenv(static::APP_ID_ENV_NAME),
129
+ 'app_secret' => getenv(static::APP_SECRET_ENV_NAME),
130
+ 'default_graph_version' => static::DEFAULT_GRAPH_VERSION,
131
+ 'enable_beta_mode' => false,
132
+ 'http_client_handler' => null,
133
+ 'persistent_data_handler' => null,
134
+ 'pseudo_random_string_generator' => null,
135
+ 'url_detection_handler' => null,
136
+ ], $config);
137
+
138
+ if (!$config['app_id']) {
139
+ throw new FacebookSDKException('Required "app_id" key not supplied in config and could not find fallback environment variable "' . static::APP_ID_ENV_NAME . '"');
140
+ }
141
+ if (!$config['app_secret']) {
142
+ throw new FacebookSDKException('Required "app_secret" key not supplied in config and could not find fallback environment variable "' . static::APP_SECRET_ENV_NAME . '"');
143
+ }
144
+
145
+ $this->app = new FacebookApp($config['app_id'], $config['app_secret']);
146
+ $this->client = new FacebookClient(
147
+ HttpClientsFactory::createHttpClient($config['http_client_handler']),
148
+ $config['enable_beta_mode']
149
+ );
150
+ $this->pseudoRandomStringGenerator = PseudoRandomStringGeneratorFactory::createPseudoRandomStringGenerator(
151
+ $config['pseudo_random_string_generator']
152
+ );
153
+ $this->setUrlDetectionHandler($config['url_detection_handler'] ?: new FacebookUrlDetectionHandler());
154
+ $this->persistentDataHandler = PersistentDataFactory::createPersistentDataHandler(
155
+ $config['persistent_data_handler']
156
+ );
157
+
158
+ if (isset($config['default_access_token'])) {
159
+ $this->setDefaultAccessToken($config['default_access_token']);
160
+ }
161
+
162
+ // @todo v6: Throw an InvalidArgumentException if "default_graph_version" is not set
163
+ $this->defaultGraphVersion = $config['default_graph_version'];
164
+ }
165
+
166
+ /**
167
+ * Returns the FacebookApp entity.
168
+ *
169
+ * @return FacebookApp
170
+ */
171
+ public function getApp()
172
+ {
173
+ return $this->app;
174
+ }
175
+
176
+ /**
177
+ * Returns the FacebookClient service.
178
+ *
179
+ * @return FacebookClient
180
+ */
181
+ public function getClient()
182
+ {
183
+ return $this->client;
184
+ }
185
+
186
+ /**
187
+ * Returns the OAuth 2.0 client service.
188
+ *
189
+ * @return OAuth2Client
190
+ */
191
+ public function getOAuth2Client()
192
+ {
193
+ if (!$this->oAuth2Client instanceof OAuth2Client) {
194
+ $app = $this->getApp();
195
+ $client = $this->getClient();
196
+ $this->oAuth2Client = new OAuth2Client($app, $client, $this->defaultGraphVersion);
197
+ }
198
+
199
+ return $this->oAuth2Client;
200
+ }
201
+
202
+ /**
203
+ * Returns the last response returned from Graph.
204
+ *
205
+ * @return FacebookResponse|FacebookBatchResponse|null
206
+ */
207
+ public function getLastResponse()
208
+ {
209
+ return $this->lastResponse;
210
+ }
211
+
212
+ /**
213
+ * Returns the URL detection handler.
214
+ *
215
+ * @return UrlDetectionInterface
216
+ */
217
+ public function getUrlDetectionHandler()
218
+ {
219
+ return $this->urlDetectionHandler;
220
+ }
221
+
222
+ /**
223
+ * Changes the URL detection handler.
224
+ *
225
+ * @param UrlDetectionInterface $urlDetectionHandler
226
+ */
227
+ private function setUrlDetectionHandler(UrlDetectionInterface $urlDetectionHandler)
228
+ {
229
+ $this->urlDetectionHandler = $urlDetectionHandler;
230
+ }
231
+
232
+ /**
233
+ * Returns the default AccessToken entity.
234
+ *
235
+ * @return AccessToken|null
236
+ */
237
+ public function getDefaultAccessToken()
238
+ {
239
+ return $this->defaultAccessToken;
240
+ }
241
+
242
+ /**
243
+ * Sets the default access token to use with requests.
244
+ *
245
+ * @param AccessToken|string $accessToken The access token to save.
246
+ *
247
+ * @throws \InvalidArgumentException
248
+ */
249
+ public function setDefaultAccessToken($accessToken)
250
+ {
251
+ if (is_string($accessToken)) {
252
+ $this->defaultAccessToken = new AccessToken($accessToken);
253
+
254
+ return;
255
+ }
256
+
257
+ if ($accessToken instanceof AccessToken) {
258
+ $this->defaultAccessToken = $accessToken;
259
+
260
+ return;
261
+ }
262
+
263
+ throw new \InvalidArgumentException('The default access token must be of type "string" or Facebook\AccessToken');
264
+ }
265
+
266
+ /**
267
+ * Returns the default Graph version.
268
+ *
269
+ * @return string
270
+ */
271
+ public function getDefaultGraphVersion()
272
+ {
273
+ return $this->defaultGraphVersion;
274
+ }
275
+
276
+ /**
277
+ * Returns the redirect login helper.
278
+ *
279
+ * @return FacebookRedirectLoginHelper
280
+ */
281
+ public function getRedirectLoginHelper()
282
+ {
283
+ return new FacebookRedirectLoginHelper(
284
+ $this->getOAuth2Client(),
285
+ $this->persistentDataHandler,
286
+ $this->urlDetectionHandler,
287
+ $this->pseudoRandomStringGenerator
288
+ );
289
+ }
290
+
291
+ /**
292
+ * Returns the JavaScript helper.
293
+ *
294
+ * @return FacebookJavaScriptHelper
295
+ */
296
+ public function getJavaScriptHelper()
297
+ {
298
+ return new FacebookJavaScriptHelper($this->app, $this->client, $this->defaultGraphVersion);
299
+ }
300
+
301
+ /**
302
+ * Returns the canvas helper.
303
+ *
304
+ * @return FacebookCanvasHelper
305
+ */
306
+ public function getCanvasHelper()
307
+ {
308
+ return new FacebookCanvasHelper($this->app, $this->client, $this->defaultGraphVersion);
309
+ }
310
+
311
+ /**
312
+ * Returns the page tab helper.
313
+ *
314
+ * @return FacebookPageTabHelper
315
+ */
316
+ public function getPageTabHelper()
317
+ {
318
+ return new FacebookPageTabHelper($this->app, $this->client, $this->defaultGraphVersion);
319
+ }
320
+
321
+ /**
322
+ * Sends a GET request to Graph and returns the result.
323
+ *
324
+ * @param string $endpoint
325
+ * @param AccessToken|string|null $accessToken
326
+ * @param string|null $eTag
327
+ * @param string|null $graphVersion
328
+ *
329
+ * @return FacebookResponse
330
+ *
331
+ * @throws FacebookSDKException
332
+ */
333
+ public function get($endpoint, $accessToken = null, $eTag = null, $graphVersion = null)
334
+ {
335
+ return $this->sendRequest(
336
+ 'GET',
337
+ $endpoint,
338
+ $params = [],
339
+ $accessToken,
340
+ $eTag,
341
+ $graphVersion
342
+ );
343
+ }
344
+
345
+ /**
346
+ * Sends a POST request to Graph and returns the result.
347
+ *
348
+ * @param string $endpoint
349
+ * @param array $params
350
+ * @param AccessToken|string|null $accessToken
351
+ * @param string|null $eTag
352
+ * @param string|null $graphVersion
353
+ *
354
+ * @return FacebookResponse
355
+ *
356
+ * @throws FacebookSDKException
357
+ */
358
+ public function post($endpoint, array $params = [], $accessToken = null, $eTag = null, $graphVersion = null)
359
+ {
360
+ return $this->sendRequest(
361
+ 'POST',
362
+ $endpoint,
363
+ $params,
364
+ $accessToken,
365
+ $eTag,
366
+ $graphVersion
367
+ );
368
+ }
369
+
370
+ /**
371
+ * Sends a DELETE request to Graph and returns the result.
372
+ *
373
+ * @param string $endpoint
374
+ * @param array $params
375
+ * @param AccessToken|string|null $accessToken
376
+ * @param string|null $eTag
377
+ * @param string|null $graphVersion
378
+ *
379
+ * @return FacebookResponse
380
+ *
381
+ * @throws FacebookSDKException
382
+ */
383
+ public function delete($endpoint, array $params = [], $accessToken = null, $eTag = null, $graphVersion = null)
384
+ {
385
+ return $this->sendRequest(
386
+ 'DELETE',
387
+ $endpoint,
388
+ $params,
389
+ $accessToken,
390
+ $eTag,
391
+ $graphVersion
392
+ );
393
+ }
394
+
395
+ /**
396
+ * Sends a request to Graph for the next page of results.
397
+ *
398
+ * @param GraphEdge $graphEdge The GraphEdge to paginate over.
399
+ *
400
+ * @return GraphEdge|null
401
+ *
402
+ * @throws FacebookSDKException
403
+ */
404
+ public function next(GraphEdge $graphEdge)
405
+ {
406
+ return $this->getPaginationResults($graphEdge, 'next');
407
+ }
408
+
409
+ /**
410
+ * Sends a request to Graph for the previous page of results.
411
+ *
412
+ * @param GraphEdge $graphEdge The GraphEdge to paginate over.
413
+ *
414
+ * @return GraphEdge|null
415
+ *
416
+ * @throws FacebookSDKException
417
+ */
418
+ public function previous(GraphEdge $graphEdge)
419
+ {
420
+ return $this->getPaginationResults($graphEdge, 'previous');
421
+ }
422
+
423
+ /**
424
+ * Sends a request to Graph for the next page of results.
425
+ *
426
+ * @param GraphEdge $graphEdge The GraphEdge to paginate over.
427
+ * @param string $direction The direction of the pagination: next|previous.
428
+ *
429
+ * @return GraphEdge|null
430
+ *
431
+ * @throws FacebookSDKException
432
+ */
433
+ public function getPaginationResults(GraphEdge $graphEdge, $direction)
434
+ {
435
+ $paginationRequest = $graphEdge->getPaginationRequest($direction);
436
+ if (!$paginationRequest) {
437
+ return null;
438
+ }
439
+
440
+ $this->lastResponse = $this->client->sendRequest($paginationRequest);
441
+
442
+ // Keep the same GraphNode subclass
443
+ $subClassName = $graphEdge->getSubClassName();
444
+ $graphEdge = $this->lastResponse->getGraphEdge($subClassName, false);
445
+
446
+ return count($graphEdge) > 0 ? $graphEdge : null;
447
+ }
448
+
449
+ /**
450
+ * Sends a request to Graph and returns the result.
451
+ *
452
+ * @param string $method
453
+ * @param string $endpoint
454
+ * @param array $params
455
+ * @param AccessToken|string|null $accessToken
456
+ * @param string|null $eTag
457
+ * @param string|null $graphVersion
458
+ *
459
+ * @return FacebookResponse
460
+ *
461
+ * @throws FacebookSDKException
462
+ */
463
+ public function sendRequest($method, $endpoint, array $params = [], $accessToken = null, $eTag = null, $graphVersion = null)
464
+ {
465
+ $accessToken = $accessToken ?: $this->defaultAccessToken;
466
+ $graphVersion = $graphVersion ?: $this->defaultGraphVersion;
467
+ $request = $this->request($method, $endpoint, $params, $accessToken, $eTag, $graphVersion);
468
+
469
+ return $this->lastResponse = $this->client->sendRequest($request);
470
+ }
471
+
472
+ /**
473
+ * Sends a batched request to Graph and returns the result.
474
+ *
475
+ * @param array $requests
476
+ * @param AccessToken|string|null $accessToken
477
+ * @param string|null $graphVersion
478
+ *
479
+ * @return FacebookBatchResponse
480
+ *
481
+ * @throws FacebookSDKException
482
+ */
483
+ public function sendBatchRequest(array $requests, $accessToken = null, $graphVersion = null)
484
+ {
485
+ $accessToken = $accessToken ?: $this->defaultAccessToken;
486
+ $graphVersion = $graphVersion ?: $this->defaultGraphVersion;
487
+ $batchRequest = new FacebookBatchRequest(
488
+ $this->app,
489
+ $requests,
490
+ $accessToken,
491
+ $graphVersion
492
+ );
493
+
494
+ return $this->lastResponse = $this->client->sendBatchRequest($batchRequest);
495
+ }
496
+
497
+ /**
498
+ * Instantiates a new FacebookRequest entity.
499
+ *
500
+ * @param string $method
501
+ * @param string $endpoint
502
+ * @param array $params
503
+ * @param AccessToken|string|null $accessToken
504
+ * @param string|null $eTag
505
+ * @param string|null $graphVersion
506
+ *
507
+ * @return FacebookRequest
508
+ *
509
+ * @throws FacebookSDKException
510
+ */
511
+ public function request($method, $endpoint, array $params = [], $accessToken = null, $eTag = null, $graphVersion = null)
512
+ {
513
+ $accessToken = $accessToken ?: $this->defaultAccessToken;
514
+ $graphVersion = $graphVersion ?: $this->defaultGraphVersion;
515
+
516
+ return new FacebookRequest(
517
+ $this->app,
518
+ $accessToken,
519
+ $method,
520
+ $endpoint,
521
+ $params,
522
+ $eTag,
523
+ $graphVersion
524
+ );
525
+ }
526
+
527
+ /**
528
+ * Factory to create FacebookFile's.
529
+ *
530
+ * @param string $pathToFile
531
+ *
532
+ * @return FacebookFile
533
+ *
534
+ * @throws FacebookSDKException
535
+ */
536
+ public function fileToUpload($pathToFile)
537
+ {
538
+ return new FacebookFile($pathToFile);
539
+ }
540
+
541
+ /**
542
+ * Factory to create FacebookVideo's.
543
+ *
544
+ * @param string $pathToFile
545
+ *
546
+ * @return FacebookVideo
547
+ *
548
+ * @throws FacebookSDKException
549
+ */
550
+ public function videoToUpload($pathToFile)
551
+ {
552
+ return new FacebookVideo($pathToFile);
553
+ }
554
+
555
+ /**
556
+ * Upload a video in chunks.
557
+ *
558
+ * @param int $target The id of the target node before the /videos edge.
559
+ * @param string $pathToFile The full path to the file.
560
+ * @param array $metadata The metadata associated with the video file.
561
+ * @param string|null $accessToken The access token.
562
+ * @param int $maxTransferTries The max times to retry a failed upload chunk.
563
+ * @param string|null $graphVersion The Graph API version to use.
564
+ *
565
+ * @return array
566
+ *
567
+ * @throws FacebookSDKException
568
+ */
569
+ public function uploadVideo($target, $pathToFile, $metadata = [], $accessToken = null, $maxTransferTries = 5, $graphVersion = null)
570
+ {
571
+ $accessToken = $accessToken ?: $this->defaultAccessToken;
572
+ $graphVersion = $graphVersion ?: $this->defaultGraphVersion;
573
+
574
+ $uploader = new FacebookResumableUploader($this->app, $this->client, $accessToken, $graphVersion);
575
+ $endpoint = '/'.$target.'/videos';
576
+ $file = $this->videoToUpload($pathToFile);
577
+ $chunk = $uploader->start($endpoint, $file);
578
+
579
+ do {
580
+ $chunk = $this->maxTriesTransfer($uploader, $endpoint, $chunk, $maxTransferTries);
581
+ } while (!$chunk->isLastChunk());
582
+
583
+ return [
584
+ 'video_id' => $chunk->getVideoId(),
585
+ 'success' => $uploader->finish($endpoint, $chunk->getUploadSessionId(), $metadata),
586
+ ];
587
+ }
588
+
589
+ /**
590
+ * Attempts to upload a chunk of a file in $retryCountdown tries.
591
+ *
592
+ * @param FacebookResumableUploader $uploader
593
+ * @param string $endpoint
594
+ * @param FacebookTransferChunk $chunk
595
+ * @param int $retryCountdown
596
+ *
597
+ * @return FacebookTransferChunk
598
+ *
599
+ * @throws FacebookSDKException
600
+ */
601
+ private function maxTriesTransfer(FacebookResumableUploader $uploader, $endpoint, FacebookTransferChunk $chunk, $retryCountdown)
602
+ {
603
+ $newChunk = $uploader->transfer($endpoint, $chunk, $retryCountdown < 1);
604
+
605
+ if ($newChunk !== $chunk) {
606
+ return $newChunk;
607
+ }
608
+
609
+ $retryCountdown--;
610
+
611
+ // If transfer() returned the same chunk entity, the transfer failed but is resumable.
612
+ return $this->maxTriesTransfer($uploader, $endpoint, $chunk, $retryCountdown);
613
+ }
614
+ }
vendor/facebook/php-sdk-v4/src/Facebook/FacebookApp.php ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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;
25
+
26
+ use Facebook\Authentication\AccessToken;
27
+
28
+ class FacebookApp implements \Serializable
29
+ {
30
+ /**
31
+ * @var string The app ID.
32
+ */
33
+ protected $id;
34
+
35
+ /**
36
+ * @var string The app secret.
37
+ */
38
+ protected $secret;
39
+
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
+
50
+ /**
51
+ * Returns the app ID.
52
+ *
53
+ * @return string
54
+ */
55
+ public function getId()
56
+ {
57
+ return $this->id;
58
+ }
59
+
60
+ /**
61
+ * Returns the app secret.
62
+ *
63
+ * @return string
64
+ */
65
+ public function getSecret()
66
+ {
67
+ return $this->secret;
68
+ }
69
+
70
+ /**
71
+ * Returns an app access token.
72
+ *
73
+ * @return AccessToken
74
+ */
75
+ public function getAccessToken()
76
+ {
77
+ return new AccessToken($this->id . '|' . $this->secret);
78
+ }
79
+
80
+ /**
81
+ * Serializes the FacebookApp entity as a string.
82
+ *
83
+ * @return string
84
+ */
85
+ public function serialize()
86
+ {
87
+ return serialize([$this->id, $this->secret]);
88
+ }
89
+
90
+ /**
91
+ * Unserializes a string as a FacebookApp entity.
92
+ *
93
+ * @param string $serialized
94
+ */
95
+ public function unserialize($serialized)
96
+ {
97
+ list($id, $secret) = unserialize($serialized);
98
+
99
+ $this->__construct($id, $secret);
100
+ }
101
+ }
vendor/facebook/php-sdk-v4/src/Facebook/FacebookBatchRequest.php ADDED
@@ -0,0 +1,303 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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;
25
+
26
+ use ArrayIterator;
27
+ use IteratorAggregate;
28
+ use ArrayAccess;
29
+ use Facebook\Authentication\AccessToken;
30
+ use Facebook\Exceptions\FacebookSDKException;
31
+
32
+ /**
33
+ * Class BatchRequest
34
+ *
35
+ * @package Facebook
36
+ */
37
+ class FacebookBatchRequest extends FacebookRequest implements IteratorAggregate, ArrayAccess
38
+ {
39
+ /**
40
+ * @var array An array of FacebookRequest entities to send.
41
+ */
42
+ protected $requests;
43
+
44
+ /**
45
+ * @var array An array of files to upload.
46
+ */
47
+ protected $attachedFiles;
48
+
49
+ /**
50
+ * Creates a new Request entity.
51
+ *
52
+ * @param FacebookApp|null $app
53
+ * @param array $requests
54
+ * @param AccessToken|string|null $accessToken
55
+ * @param string|null $graphVersion
56
+ */
57
+ public function __construct(FacebookApp $app = null, array $requests = [], $accessToken = null, $graphVersion = null)
58
+ {
59
+ parent::__construct($app, $accessToken, 'POST', '', [], null, $graphVersion);
60
+
61
+ $this->add($requests);
62
+ }
63
+
64
+ /**
65
+ * A a new request to the array.
66
+ *
67
+ * @param FacebookRequest|array $request
68
+ * @param string|null $name
69
+ *
70
+ * @return FacebookBatchRequest
71
+ *
72
+ * @throws \InvalidArgumentException
73
+ */
74
+ public function add($request, $name = null)
75
+ {
76
+ if (is_array($request)) {
77
+ foreach ($request as $key => $req) {
78
+ $this->add($req, $key);
79
+ }
80
+
81
+ return $this;
82
+ }
83
+
84
+ if (!$request instanceof FacebookRequest) {
85
+ throw new \InvalidArgumentException('Argument for add() must be of type array or FacebookRequest.');
86
+ }
87
+
88
+ $this->addFallbackDefaults($request);
89
+ $requestToAdd = [
90
+ 'name' => $name,
91
+ 'request' => $request,
92
+ ];
93
+
94
+ // File uploads
95
+ $attachedFiles = $this->extractFileAttachments($request);
96
+ if ($attachedFiles) {
97
+ $requestToAdd['attached_files'] = $attachedFiles;
98
+ }
99
+ $this->requests[] = $requestToAdd;
100
+
101
+ return $this;
102
+ }
103
+
104
+ /**
105
+ * Ensures that the FacebookApp and access token fall back when missing.
106
+ *
107
+ * @param FacebookRequest $request
108
+ *
109
+ * @throws FacebookSDKException
110
+ */
111
+ public function addFallbackDefaults(FacebookRequest $request)
112
+ {
113
+ if (!$request->getApp()) {
114
+ $app = $this->getApp();
115
+ if (!$app) {
116
+ throw new FacebookSDKException('Missing FacebookApp on FacebookRequest and no fallback detected on FacebookBatchRequest.');
117
+ }
118
+ $request->setApp($app);
119
+ }
120
+
121
+ if (!$request->getAccessToken()) {
122
+ $accessToken = $this->getAccessToken();
123
+ if (!$accessToken) {
124
+ throw new FacebookSDKException('Missing access token on FacebookRequest and no fallback detected on FacebookBatchRequest.');
125
+ }
126
+ $request->setAccessToken($accessToken);
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Extracts the files from a request.
132
+ *
133
+ * @param FacebookRequest $request
134
+ *
135
+ * @return string|null
136
+ *
137
+ * @throws FacebookSDKException
138
+ */
139
+ public function extractFileAttachments(FacebookRequest $request)
140
+ {
141
+ if (!$request->containsFileUploads()) {
142
+ return null;
143
+ }
144
+
145
+ $files = $request->getFiles();
146
+ $fileNames = [];
147
+ foreach ($files as $file) {
148
+ $fileName = uniqid();
149
+ $this->addFile($fileName, $file);
150
+ $fileNames[] = $fileName;
151
+ }
152
+
153
+ $request->resetFiles();
154
+
155
+ // @TODO Does Graph support multiple uploads on one endpoint?
156
+ return implode(',', $fileNames);
157
+ }
158
+
159
+ /**
160
+ * Return the FacebookRequest entities.
161
+ *
162
+ * @return array
163
+ */
164
+ public function getRequests()
165
+ {
166
+ return $this->requests;
167
+ }
168
+
169
+ /**
170
+ * Prepares the requests to be sent as a batch request.
171
+ *
172
+ * @return string
173
+ */
174
+ public function prepareRequestsForBatch()
175
+ {
176
+ $this->validateBatchRequestCount();
177
+
178
+ $params = [
179
+ 'batch' => $this->convertRequestsToJson(),
180
+ 'include_headers' => true,
181
+ ];
182
+ $this->setParams($params);
183
+ }
184
+
185
+ /**
186
+ * Converts the requests into a JSON(P) string.
187
+ *
188
+ * @return string
189
+ */
190
+ public function convertRequestsToJson()
191
+ {
192
+ $requests = [];
193
+ foreach ($this->requests as $request) {
194
+ $attachedFiles = isset($request['attached_files']) ? $request['attached_files'] : null;
195
+ $requests[] = $this->requestEntityToBatchArray($request['request'], $request['name'], $attachedFiles);
196
+ }
197
+
198
+ return json_encode($requests);
199
+ }
200
+
201
+ /**
202
+ * Validate the request count before sending them as a batch.
203
+ *
204
+ * @throws FacebookSDKException
205
+ */
206
+ public function validateBatchRequestCount()
207
+ {
208
+ $batchCount = count($this->requests);
209
+ if ($batchCount === 0) {
210
+ throw new FacebookSDKException('There are no batch requests to send.');
211
+ } elseif ($batchCount > 50) {
212
+ // Per: https://developers.facebook.com/docs/graph-api/making-multiple-requests#limits
213
+ throw new FacebookSDKException('You cannot send more than 50 batch requests at a time.');
214
+ }
215
+ }
216
+
217
+ /**
218
+ * Converts a Request entity into an array that is batch-friendly.
219
+ *
220
+ * @param FacebookRequest $request The request entity to convert.
221
+ * @param string|null $requestName The name of the request.
222
+ * @param string|null $attachedFiles Names of files associated with the request.
223
+ *
224
+ * @return array
225
+ */
226
+ public function requestEntityToBatchArray(FacebookRequest $request, $requestName = null, $attachedFiles = null)
227
+ {
228
+ $compiledHeaders = [];
229
+ $headers = $request->getHeaders();
230
+ foreach ($headers as $name => $value) {
231
+ $compiledHeaders[] = $name . ': ' . $value;
232
+ }
233
+
234
+ $batch = [
235
+ 'headers' => $compiledHeaders,
236
+ 'method' => $request->getMethod(),
237
+ 'relative_url' => $request->getUrl(),
238
+ ];
239
+
240
+ // Since file uploads are moved to the root request of a batch request,
241
+ // the child requests will always be URL-encoded.
242
+ $body = $request->getUrlEncodedBody()->getBody();
243
+ if ($body) {
244
+ $batch['body'] = $body;
245
+ }
246
+
247
+ if (isset($requestName)) {
248
+ $batch['name'] = $requestName;
249
+ }
250
+
251
+ if (isset($attachedFiles)) {
252
+ $batch['attached_files'] = $attachedFiles;
253
+ }
254
+
255
+ // @TODO Add support for "omit_response_on_success"
256
+ // @TODO Add support for "depends_on"
257
+ // @TODO Add support for JSONP with "callback"
258
+
259
+ return $batch;
260
+ }
261
+
262
+ /**
263
+ * Get an iterator for the items.
264
+ *
265
+ * @return ArrayIterator
266
+ */
267
+ public function getIterator()
268
+ {
269
+ return new ArrayIterator($this->requests);
270
+ }
271
+
272
+ /**
273
+ * @inheritdoc
274
+ */
275
+ public function offsetSet($offset, $value)
276
+ {
277
+ $this->add($value, $offset);
278
+ }
279
+
280
+ /**
281
+ * @inheritdoc
282
+ */
283
+ public function offsetExists($offset)
284
+ {
285
+ return isset($this->requests[$offset]);
286
+ }
287
+
288
+ /**
289
+ * @inheritdoc
290
+ */
291
+ public function offsetUnset($offset)
292
+ {
293
+ unset($this->requests[$offset]);
294
+ }
295
+
296
+ /**
297
+ * @inheritdoc
298
+ */
299
+ public function offsetGet($offset)
300
+ {
301
+ return isset($this->requests[$offset]) ? $this->requests[$offset] : null;
302
+ }
303
+ }
vendor/facebook/php-sdk-v4/src/Facebook/FacebookBatchResponse.php ADDED
@@ -0,0 +1,174 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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;
25
+
26
+ use ArrayIterator;
27
+ use IteratorAggregate;
28
+ use ArrayAccess;
29
+
30
+ /**
31
+ * Class FacebookBatchResponse
32
+ *
33
+ * @package Facebook
34
+ */
35
+ class FacebookBatchResponse extends FacebookResponse implements IteratorAggregate, ArrayAccess
36
+ {
37
+ /**
38
+ * @var FacebookBatchRequest The original entity that made the batch request.
39
+ */
40
+ protected $batchRequest;
41
+
42
+ /**
43
+ * @var array An array of FacebookResponse entities.
44
+ */
45
+ protected $responses = [];
46
+
47
+ /**
48
+ * Creates a new Response entity.
49
+ *
50
+ * @param FacebookBatchRequest $batchRequest
51
+ * @param FacebookResponse $response
52
+ */
53
+ public function __construct(FacebookBatchRequest $batchRequest, FacebookResponse $response)
54
+ {
55
+ $this->batchRequest = $batchRequest;
56
+
57
+ $request = $response->getRequest();
58
+ $body = $response->getBody();
59
+ $httpStatusCode = $response->getHttpStatusCode();
60
+ $headers = $response->getHeaders();
61
+ parent::__construct($request, $body, $httpStatusCode, $headers);
62
+
63
+ $responses = $response->getDecodedBody();
64
+ $this->setResponses($responses);
65
+ }
66
+
67
+ /**
68
+ * Returns an array of FacebookResponse entities.
69
+ *
70
+ * @return array
71
+ */
72
+ public function getResponses()
73
+ {
74
+ return $this->responses;
75
+ }
76
+
77
+ /**
78
+ * The main batch response will be an array of requests so
79
+ * we need to iterate over all the responses.
80
+ *
81
+ * @param array $responses
82
+ */
83
+ public function setResponses(array $responses)
84
+ {
85
+ $this->responses = [];
86
+
87
+ foreach ($responses as $key => $graphResponse) {
88
+ $this->addResponse($key, $graphResponse);
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Add a response to the list.
94
+ *
95
+ * @param int $key
96
+ * @param array|null $response
97
+ */
98
+ public function addResponse($key, $response)
99
+ {
100
+ $originalRequestName = isset($this->batchRequest[$key]['name']) ? $this->batchRequest[$key]['name'] : $key;
101
+ $originalRequest = isset($this->batchRequest[$key]['request']) ? $this->batchRequest[$key]['request'] : null;
102
+
103
+ $httpResponseBody = isset($response['body']) ? $response['body'] : null;
104
+ $httpResponseCode = isset($response['code']) ? $response['code'] : null;
105
+ // @TODO With PHP 5.5 support, this becomes array_column($response['headers'], 'value', 'name')
106
+ $httpResponseHeaders = isset($response['headers']) ? $this->normalizeBatchHeaders($response['headers']) : [];
107
+
108
+ $this->responses[$originalRequestName] = new FacebookResponse(
109
+ $originalRequest,
110
+ $httpResponseBody,
111
+ $httpResponseCode,
112
+ $httpResponseHeaders
113
+ );
114
+ }
115
+
116
+ /**
117
+ * @inheritdoc
118
+ */
119
+ public function getIterator()
120
+ {
121
+ return new ArrayIterator($this->responses);
122
+ }
123
+
124
+ /**
125
+ * @inheritdoc
126
+ */
127
+ public function offsetSet($offset, $value)
128
+ {
129
+ $this->addResponse($offset, $value);
130
+ }
131
+
132
+ /**
133
+ * @inheritdoc
134
+ */
135
+ public function offsetExists($offset)
136
+ {
137
+ return isset($this->responses[$offset]);
138
+ }
139
+
140
+ /**
141
+ * @inheritdoc
142
+ */
143
+ public function offsetUnset($offset)
144
+ {
145
+ unset($this->responses[$offset]);
146
+ }
147
+
148
+ /**
149
+ * @inheritdoc
150
+ */
151
+ public function offsetGet($offset)
152
+ {
153
+ return isset($this->responses[$offset]) ? $this->responses[$offset] : null;
154
+ }
155
+
156
+ /**
157
+ * Converts the batch header array into a standard format.
158
+ * @TODO replace with array_column() when PHP 5.5 is supported.
159
+ *
160
+ * @param array $batchHeaders
161
+ *
162
+ * @return array
163
+ */
164
+ private function normalizeBatchHeaders(array $batchHeaders)
165
+ {
166
+ $headers = [];
167
+
168
+ foreach ($batchHeaders as $header) {
169
+ $headers[$header['name']] = $header['value'];
170
+ }
171
+
172
+ return $headers;
173
+ }
174
+ }
vendor/facebook/php-sdk-v4/src/Facebook/FacebookClient.php ADDED
@@ -0,0 +1,250 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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;
25
+
26
+ use Facebook\HttpClients\FacebookHttpClientInterface;
27
+ use Facebook\HttpClients\FacebookCurlHttpClient;
28
+ use Facebook\HttpClients\FacebookStreamHttpClient;
29
+ use Facebook\Exceptions\FacebookSDKException;
30
+
31
+ /**
32
+ * Class FacebookClient
33
+ *
34
+ * @package Facebook
35
+ */
36
+ class FacebookClient
37
+ {
38
+ /**
39
+ * @const string Production Graph API URL.
40
+ */
41
+ const BASE_GRAPH_URL = 'https://graph.facebook.com';
42
+
43
+ /**
44
+ * @const string Graph API URL for video uploads.
45
+ */
46
+ const BASE_GRAPH_VIDEO_URL = 'https://graph-video.facebook.com';
47
+
48
+ /**
49
+ * @const string Beta Graph API URL.
50
+ */
51
+ const BASE_GRAPH_URL_BETA = 'https://graph.beta.facebook.com';
52
+
53
+ /**
54
+ * @const string Beta Graph API URL for video uploads.
55
+ */
56
+ const BASE_GRAPH_VIDEO_URL_BETA = 'https://graph-video.beta.facebook.com';
57
+
58
+ /**
59
+ * @const int The timeout in seconds for a normal request.
60
+ */
61
+ const DEFAULT_REQUEST_TIMEOUT = 60;
62
+
63
+ /**
64
+ * @const int The timeout in seconds for a request that contains file uploads.
65
+ */
66
+ const DEFAULT_FILE_UPLOAD_REQUEST_TIMEOUT = 3600;
67
+
68
+ /**
69
+ * @const int The timeout in seconds for a request that contains video uploads.
70
+ */
71
+ const DEFAULT_VIDEO_UPLOAD_REQUEST_TIMEOUT = 7200;
72
+
73
+ /**
74
+ * @var bool Toggle to use Graph beta url.
75
+ */
76
+ protected $enableBetaMode = false;
77
+
78
+ /**
79
+ * @var FacebookHttpClientInterface HTTP client handler.
80
+ */
81
+ protected $httpClientHandler;
82
+
83
+ /**
84
+ * @var int The number of calls that have been made to Graph.
85
+ */
86
+ public static $requestCount = 0;
87
+
88
+ /**
89
+ * Instantiates a new FacebookClient object.
90
+ *
91
+ * @param FacebookHttpClientInterface|null $httpClientHandler
92
+ * @param boolean $enableBeta
93
+ */
94
+ public function __construct(FacebookHttpClientInterface $httpClientHandler = null, $enableBeta = false)
95
+ {
96
+ $this->httpClientHandler = $httpClientHandler ?: $this->detectHttpClientHandler();
97
+ $this->enableBetaMode = $enableBeta;
98
+ }
99
+
100
+ /**
101
+ * Sets the HTTP client handler.
102
+ *
103
+ * @param FacebookHttpClientInterface $httpClientHandler
104
+ */
105
+ public function setHttpClientHandler(FacebookHttpClientInterface $httpClientHandler)
106
+ {
107
+ $this->httpClientHandler = $httpClientHandler;
108
+ }
109
+
110
+ /**
111
+ * Returns the HTTP client handler.
112
+ *
113
+ * @return FacebookHttpClientInterface
114
+ */
115
+ public function getHttpClientHandler()
116
+ {
117
+ return $this->httpClientHandler;
118
+ }
119
+
120
+ /**
121
+ * Detects which HTTP client handler to use.
122
+ *
123
+ * @return FacebookHttpClientInterface
124
+ */
125
+ public function detectHttpClientHandler()
126
+ {
127
+ return extension_loaded('curl') ? new FacebookCurlHttpClient() : new FacebookStreamHttpClient();
128
+ }
129
+
130
+ /**
131
+ * Toggle beta mode.
132
+ *
133
+ * @param boolean $betaMode
134
+ */
135
+ public function enableBetaMode($betaMode = true)
136
+ {
137
+ $this->enableBetaMode = $betaMode;
138
+ }
139
+
140
+ /**
141
+ * Returns the base Graph URL.
142
+ *
143
+ * @param boolean $postToVideoUrl Post to the video API if videos are being uploaded.
144
+ *
145
+ * @return string
146
+ */
147
+ public function getBaseGraphUrl($postToVideoUrl = false)
148
+ {
149
+ if ($postToVideoUrl) {
150
+ return $this->enableBetaMode ? static::BASE_GRAPH_VIDEO_URL_BETA : static::BASE_GRAPH_VIDEO_URL;
151
+ }
152
+
153
+ return $this->enableBetaMode ? static::BASE_GRAPH_URL_BETA : static::BASE_GRAPH_URL;
154
+ }
155
+
156
+ /**
157
+ * Prepares the request for sending to the client handler.
158
+ *
159
+ * @param FacebookRequest $request
160
+ *
161
+ * @return array
162
+ */
163
+ public function prepareRequestMessage(FacebookRequest $request)
164
+ {
165
+ $postToVideoUrl = $request->containsVideoUploads();
166
+ $url = $this->getBaseGraphUrl($postToVideoUrl) . $request->getUrl();
167
+
168
+ // If we're sending files they should be sent as multipart/form-data
169
+ if ($request->containsFileUploads()) {
170
+ $requestBody = $request->getMultipartBody();
171
+ $request->setHeaders([
172
+ 'Content-Type' => 'multipart/form-data; boundary=' . $requestBody->getBoundary(),
173
+ ]);
174
+ } else {
175
+ $requestBody = $request->getUrlEncodedBody();
176
+ $request->setHeaders([
177
+ 'Content-Type' => 'application/x-www-form-urlencoded',
178
+ ]);
179
+ }
180
+
181
+ return [
182
+ $url,
183
+ $request->getMethod(),
184
+ $request->getHeaders(),
185
+ $requestBody->getBody(),
186
+ ];
187
+ }
188
+
189
+ /**
190
+ * Makes the request to Graph and returns the result.
191
+ *
192
+ * @param FacebookRequest $request
193
+ *
194
+ * @return FacebookResponse
195
+ *
196
+ * @throws FacebookSDKException
197
+ */
198
+ public function sendRequest(FacebookRequest $request)
199
+ {
200
+ if (get_class($request) === 'Facebook\FacebookRequest') {
201
+ $request->validateAccessToken();
202
+ }
203
+
204
+ list($url, $method, $headers, $body) = $this->prepareRequestMessage($request);
205
+
206
+ // Since file uploads can take a while, we need to give more time for uploads
207
+ $timeOut = static::DEFAULT_REQUEST_TIMEOUT;
208
+ if ($request->containsFileUploads()) {
209
+ $timeOut = static::DEFAULT_FILE_UPLOAD_REQUEST_TIMEOUT;
210
+ } elseif ($request->containsVideoUploads()) {
211
+ $timeOut = static::DEFAULT_VIDEO_UPLOAD_REQUEST_TIMEOUT;
212
+ }
213
+
214
+ // Should throw `FacebookSDKException` exception on HTTP client error.
215
+ // Don't catch to allow it to bubble up.
216
+ $rawResponse = $this->httpClientHandler->send($url, $method, $body, $headers, $timeOut);
217
+
218
+ static::$requestCount++;
219
+
220
+ $returnResponse = new FacebookResponse(
221
+ $request,
222
+ $rawResponse->getBody(),
223
+ $rawResponse->getHttpResponseCode(),
224
+ $rawResponse->getHeaders()
225
+ );
226
+
227
+ if ($returnResponse->isError()) {
228
+ throw $returnResponse->getThrownException();
229
+ }
230
+
231
+ return $returnResponse;
232
+ }
233
+
234
+ /**
235
+ * Makes a batched request to Graph and returns the result.
236
+ *
237
+ * @param FacebookBatchRequest $request
238
+ *
239
+ * @return FacebookBatchResponse
240
+ *
241
+ * @throws FacebookSDKException
242
+ */
243
+ public function sendBatchRequest(FacebookBatchRequest $request)
244
+ {
245
+ $request->prepareRequestsForBatch();
246
+ $facebookResponse = $this->sendRequest($request);
247
+
248
+ return new FacebookBatchResponse($request, $facebookResponse);
249
+ }
250
+ }
vendor/facebook/php-sdk-v4/src/Facebook/FacebookRequest.php ADDED
@@ -0,0 +1,536 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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;
25
+
26
+ use Facebook\Authentication\AccessToken;
27
+ use Facebook\Url\FacebookUrlManipulator;
28
+ use Facebook\FileUpload\FacebookFile;
29
+ use Facebook\FileUpload\FacebookVideo;
30
+ use Facebook\Http\RequestBodyMultipart;
31
+ use Facebook\Http\RequestBodyUrlEncoded;
32
+ use Facebook\Exceptions\FacebookSDKException;
33
+
34
+ /**
35
+ * Class Request
36
+ *
37
+ * @package Facebook
38
+ */
39
+ class FacebookRequest
40
+ {
41
+ /**
42
+ * @var FacebookApp The Facebook app entity.
43
+ */
44
+ protected $app;
45
+
46
+ /**
47
+ * @var string|null The access token to use for this request.
48
+ */
49
+ protected $accessToken;
50
+
51
+ /**
52
+ * @var string The HTTP method for this request.
53
+ */
54
+ protected $method;
55
+
56
+ /**
57
+ * @var string The Graph endpoint for this request.
58
+ */
59
+ protected $endpoint;
60
+
61
+ /**
62
+ * @var array The headers to send with this request.
63
+ */
64
+ protected $headers = [];
65
+
66
+ /**
67
+ * @var array The parameters to send with this request.
68
+ */
69
+ protected $params = [];
70
+
71
+ /**
72
+ * @var array The files to send with this request.
73
+ */
74
+ protected $files = [];
75
+
76
+ /**
77
+ * @var string ETag to send with this request.
78
+ */
79
+ protected $eTag;
80
+
81
+ /**
82
+ * @var string Graph version to use for this request.
83
+ */
84
+ protected $graphVersion;
85
+
86
+ /**
87
+ * Creates a new Request entity.
88
+ *
89
+ * @param FacebookApp|null $app
90
+ * @param AccessToken|string|null $accessToken
91
+ * @param string|null $method
92
+ * @param string|null $endpoint
93
+ * @param array|null $params
94
+ * @param string|null $eTag
95
+ * @param string|null $graphVersion
96
+ */
97
+ public function __construct(FacebookApp $app = null, $accessToken = null, $method = null, $endpoint = null, array $params = [], $eTag = null, $graphVersion = null)
98
+ {
99
+ $this->setApp($app);
100
+ $this->setAccessToken($accessToken);
101
+ $this->setMethod($method);
102
+ $this->setEndpoint($endpoint);
103
+ $this->setParams($params);
104
+ $this->setETag($eTag);
105
+ $this->graphVersion = $graphVersion ?: Facebook::DEFAULT_GRAPH_VERSION;
106
+ }
107
+
108
+ /**
109
+ * Set the access token for this request.
110
+ *
111
+ * @param AccessToken|string
112
+ *
113
+ * @return FacebookRequest
114
+ */
115
+ public function setAccessToken($accessToken)
116
+ {
117
+ $this->accessToken = $accessToken;
118
+ if ($accessToken instanceof AccessToken) {
119
+ $this->accessToken = $accessToken->getValue();
120
+ }
121
+
122
+ return $this;
123
+ }
124
+
125
+ /**
126
+ * Sets the access token with one harvested from a URL or POST params.
127
+ *
128
+ * @param string $accessToken The access token.
129
+ *
130
+ * @return FacebookRequest
131
+ *
132
+ * @throws FacebookSDKException
133
+ */
134
+ public function setAccessTokenFromParams($accessToken)
135
+ {
136
+ $existingAccessToken = $this->getAccessToken();
137
+ if (!$existingAccessToken) {
138
+ $this->setAccessToken($accessToken);
139
+ } elseif ($accessToken !== $existingAccessToken) {
140
+ throw new FacebookSDKException('Access token mismatch. The access token provided in the FacebookRequest and the one provided in the URL or POST params do not match.');
141
+ }
142
+
143
+ return $this;
144
+ }
145
+
146
+ /**
147
+ * Return the access token for this request.
148
+ *
149
+ * @return string|null
150
+ */
151
+ public function getAccessToken()
152
+ {
153
+ return $this->accessToken;
154
+ }
155
+
156
+ /**
157
+ * Return the access token for this request an an AccessToken entity.
158
+ *
159
+ * @return AccessToken|null
160
+ */
161
+ public function getAccessTokenEntity()
162
+ {
163
+ return $this->accessToken ? new AccessToken($this->accessToken) : null;
164
+ }
165
+
166
+ /**
167
+ * Set the FacebookApp entity used for this request.
168
+ *
169
+ * @param FacebookApp|null $app
170
+ */
171
+ public function setApp(FacebookApp $app = null)
172
+ {
173
+ $this->app = $app;
174
+ }
175
+
176
+ /**
177
+ * Return the FacebookApp entity used for this request.
178
+ *
179
+ * @return FacebookApp
180
+ */
181
+ public function getApp()
182
+ {
183
+ return $this->app;
184
+ }
185
+
186
+ /**
187
+ * Generate an app secret proof to sign this request.
188
+ *
189
+ * @return string|null
190
+ */
191
+ public function getAppSecretProof()
192
+ {
193
+ if (!$accessTokenEntity = $this->getAccessTokenEntity()) {
194
+ return null;
195
+ }
196
+
197
+ return $accessTokenEntity->getAppSecretProof($this->app->getSecret());
198
+ }
199
+
200
+ /**
201
+ * Validate that an access token exists for this request.
202
+ *
203
+ * @throws FacebookSDKException
204
+ */
205
+ public function validateAccessToken()
206
+ {
207
+ $accessToken = $this->getAccessToken();
208
+ if (!$accessToken) {
209
+ throw new FacebookSDKException('You must provide an access token.');
210
+ }
211
+ }
212
+
213
+ /**
214
+ * Set the HTTP method for this request.
215
+ *
216
+ * @param string
217
+ *
218
+ * @return FacebookRequest
219
+ */
220
+ public function setMethod($method)
221
+ {
222
+ $this->method = strtoupper($method);
223
+ }
224
+
225
+ /**
226
+ * Return the HTTP method for this request.
227
+ *
228
+ * @return string
229
+ */
230
+ public function getMethod()
231
+ {
232
+ return $this->method;
233
+ }
234
+
235
+ /**
236
+ * Validate that the HTTP method is set.
237
+ *
238
+ * @throws FacebookSDKException
239
+ */
240
+ public function validateMethod()
241
+ {
242
+ if (!$this->method) {
243
+ throw new FacebookSDKException('HTTP method not specified.');
244
+ }
245
+
246
+ if (!in_array($this->method, ['GET', 'POST', 'DELETE'])) {
247
+ throw new FacebookSDKException('Invalid HTTP method specified.');
248
+ }
249
+ }
250
+
251
+ /**
252
+ * Set the endpoint for this request.
253
+ *
254
+ * @param string
255
+ *
256
+ * @return FacebookRequest
257
+ *
258
+ * @throws FacebookSDKException
259
+ */
260
+ public function setEndpoint($endpoint)
261
+ {
262
+ // Harvest the access token from the endpoint to keep things in sync
263
+ $params = FacebookUrlManipulator::getParamsAsArray($endpoint);
264
+ if (isset($params['access_token'])) {
265
+ $this->setAccessTokenFromParams($params['access_token']);
266
+ }
267
+
268
+ // Clean the token & app secret proof from the endpoint.
269
+ $filterParams = ['access_token', 'appsecret_proof'];
270
+ $this->endpoint = FacebookUrlManipulator::removeParamsFromUrl($endpoint, $filterParams);
271
+
272
+ return $this;
273
+ }
274
+
275
+ /**
276
+ * Return the HTTP method for this request.
277
+ *
278
+ * @return string
279
+ */
280
+ public function getEndpoint()
281
+ {
282
+ // For batch requests, this will be empty
283
+ return $this->endpoint;
284
+ }
285
+
286
+ /**
287
+ * Generate and return the headers for this request.
288
+ *
289
+ * @return array
290
+ */
291
+ public function getHeaders()
292
+ {
293
+ $headers = static::getDefaultHeaders();
294
+
295
+ if ($this->eTag) {
296
+ $headers['If-None-Match'] = $this->eTag;
297
+ }
298
+
299
+ return array_merge($this->headers, $headers);
300
+ }
301
+
302
+ /**
303
+ * Set the headers for this request.
304
+ *
305
+ * @param array $headers
306
+ */
307
+ public function setHeaders(array $headers)
308
+ {
309
+ $this->headers = array_merge($this->headers, $headers);
310
+ }
311
+
312
+ /**
313
+ * Sets the eTag value.
314
+ *
315
+ * @param string $eTag
316
+ */
317
+ public function setETag($eTag)
318
+ {
319
+ $this->eTag = $eTag;
320
+ }
321
+
322
+ /**
323
+ * Set the params for this request.
324
+ *
325
+ * @param array $params
326
+ *
327
+ * @return FacebookRequest
328
+ *
329
+ * @throws FacebookSDKException
330
+ */
331
+ public function setParams(array $params = [])
332
+ {
333
+ if (isset($params['access_token'])) {
334
+ $this->setAccessTokenFromParams($params['access_token']);
335
+ }
336
+
337
+ // Don't let these buggers slip in.
338
+ unset($params['access_token'], $params['appsecret_proof']);
339
+
340
+ // @TODO Refactor code above with this
341
+ //$params = $this->sanitizeAuthenticationParams($params);
342
+ $params = $this->sanitizeFileParams($params);
343
+ $this->dangerouslySetParams($params);
344
+
345
+ return $this;
346
+ }
347
+
348
+ /**
349
+ * Set the params for this request without filtering them first.
350
+ *
351
+ * @param array $params
352
+ *
353
+ * @return FacebookRequest
354
+ */
355
+ public function dangerouslySetParams(array $params = [])
356
+ {
357
+ $this->params = array_merge($this->params, $params);
358
+
359
+ return $this;
360
+ }
361
+
362
+ /**
363
+ * Iterate over the params and pull out the file uploads.
364
+ *
365
+ * @param array $params
366
+ *
367
+ * @return array
368
+ */
369
+ public function sanitizeFileParams(array $params)
370
+ {
371
+ foreach ($params as $key => $value) {
372
+ if ($value instanceof FacebookFile) {
373
+ $this->addFile($key, $value);
374
+ unset($params[$key]);
375
+ }
376
+ }
377
+
378
+ return $params;
379
+ }
380
+
381
+ /**
382
+ * Add a file to be uploaded.
383
+ *
384
+ * @param string $key
385
+ * @param FacebookFile $file
386
+ */
387
+ public function addFile($key, FacebookFile $file)
388
+ {
389
+ $this->files[$key] = $file;
390
+ }
391
+
392
+ /**
393
+ * Removes all the files from the upload queue.
394
+ */
395
+ public function resetFiles()
396
+ {
397
+ $this->files = [];
398
+ }
399
+
400
+ /**
401
+ * Get the list of files to be uploaded.
402
+ *
403
+ * @return array
404
+ */
405
+ public function getFiles()
406
+ {
407
+ return $this->files;
408
+ }
409
+
410
+ /**
411
+ * Let's us know if there is a file upload with this request.
412
+ *
413
+ * @return boolean
414
+ */
415
+ public function containsFileUploads()
416
+ {
417
+ return !empty($this->files);
418
+ }
419
+
420
+ /**
421
+ * Let's us know if there is a video upload with this request.
422
+ *
423
+ * @return boolean
424
+ */
425
+ public function containsVideoUploads()
426
+ {
427
+ foreach ($this->files as $file) {
428
+ if ($file instanceof FacebookVideo) {
429
+ return true;
430
+ }
431
+ }
432
+
433
+ return false;
434
+ }
435
+
436
+ /**
437
+ * Returns the body of the request as multipart/form-data.
438
+ *
439
+ * @return RequestBodyMultipart
440
+ */
441
+ public function getMultipartBody()
442
+ {
443
+ $params = $this->getPostParams();
444
+
445
+ return new RequestBodyMultipart($params, $this->files);
446
+ }
447
+
448
+ /**
449
+ * Returns the body of the request as URL-encoded.
450
+ *
451
+ * @return RequestBodyUrlEncoded
452
+ */
453
+ public function getUrlEncodedBody()
454
+ {
455
+ $params = $this->getPostParams();
456
+
457
+ return new RequestBodyUrlEncoded($params);
458
+ }
459
+
460
+ /**
461
+ * Generate and return the params for this request.
462
+ *
463
+ * @return array
464
+ */
465
+ public function getParams()
466
+ {
467
+ $params = $this->params;
468
+
469
+ $accessToken = $this->getAccessToken();
470
+ if ($accessToken) {
471
+ $params['access_token'] = $accessToken;
472
+ $params['appsecret_proof'] = $this->getAppSecretProof();
473
+ }
474
+
475
+ return $params;
476
+ }
477
+
478
+ /**
479
+ * Only return params on POST requests.
480
+ *
481
+ * @return array
482
+ */
483
+ public function getPostParams()
484
+ {
485
+ if ($this->getMethod() === 'POST') {
486
+ return $this->getParams();
487
+ }
488
+
489
+ return [];
490
+ }
491
+
492
+ /**
493
+ * The graph version used for this request.
494
+ *
495
+ * @return string
496
+ */
497
+ public function getGraphVersion()
498
+ {
499
+ return $this->graphVersion;
500
+ }
501
+
502
+ /**
503
+ * Generate and return the URL for this request.
504
+ *
505
+ * @return string
506
+ */
507
+ public function getUrl()
508
+ {
509
+ $this->validateMethod();
510
+
511
+ $graphVersion = FacebookUrlManipulator::forceSlashPrefix($this->graphVersion);
512
+ $endpoint = FacebookUrlManipulator::forceSlashPrefix($this->getEndpoint());
513
+
514
+ $url = $graphVersion . $endpoint;
515
+
516
+ if ($this->getMethod() !== 'POST') {
517
+ $params = $this->getParams();
518
+ $url = FacebookUrlManipulator::appendParamsToUrl($url, $params);
519
+ }
520
+
521
+ return $url;
522
+ }
523
+
524
+ /**
525
+ * Return the default headers that every request should use.
526
+ *
527
+ * @return array
528
+ */
529
+ public static function getDefaultHeaders()
530
+ {
531
+ return [
532
+ 'User-Agent' => 'fb-php-' . Facebook::VERSION,
533
+ 'Accept-Encoding' => '*',
534
+ ];
535
+ }
536
+ }
vendor/facebook/php-sdk-v4/src/Facebook/FacebookResponse.php ADDED
@@ -0,0 +1,410 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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;
25
+
26
+ use Facebook\GraphNodes\GraphNodeFactory;
27
+ use Facebook\Exceptions\FacebookResponseException;
28
+ use Facebook\Exceptions\FacebookSDKException;
29
+
30
+ /**
31
+ * Class FacebookResponse
32
+ *
33
+ * @package Facebook
34
+ */
35
+ class FacebookResponse
36
+ {
37
+ /**
38
+ * @var int The HTTP status code response from Graph.
39
+ */
40
+ protected $httpStatusCode;
41
+
42
+ /**
43
+ * @var array The headers returned from Graph.
44
+ */
45
+ protected $headers;
46
+
47
+ /**
48
+ * @var string The raw body of the response from Graph.
49
+ */
50
+ protected $body;
51
+
52
+ /**
53
+ * @var array The decoded body of the Graph response.
54
+ */
55
+ protected $decodedBody = [];
56
+
57
+ /**
58
+ * @var FacebookRequest The original request that returned this response.
59
+ */
60
+ protected $request;
61
+
62
+ /**
63
+ * @var FacebookSDKException The exception thrown by this request.
64
+ */
65
+ protected $thrownException;
66
+
67
+ /**
68
+ * Creates a new Response entity.
69
+ *
70
+ * @param FacebookRequest $request
71
+ * @param string|null $body
72
+ * @param int|null $httpStatusCode
73
+ * @param array|null $headers
74
+ */
75
+ public function __construct(FacebookRequest $request, $body = null, $httpStatusCode = null, array $headers = [])
76
+ {
77
+ $this->request = $request;
78
+ $this->body = $body;
79
+ $this->httpStatusCode = $httpStatusCode;
80
+ $this->headers = $headers;
81
+
82
+ $this->decodeBody();
83
+ }
84
+
85
+ /**
86
+ * Return the original request that returned this response.
87
+ *
88
+ * @return FacebookRequest
89
+ */
90
+ public function getRequest()
91
+ {
92
+ return $this->request;
93
+ }
94
+
95
+ /**
96
+ * Return the FacebookApp entity used for this response.
97
+ *
98
+ * @return FacebookApp
99
+ */
100
+ public function getApp()
101
+ {
102
+ return $this->request->getApp();
103
+ }
104
+
105
+ /**
106
+ * Return the access token that was used for this response.
107
+ *
108
+ * @return string|null
109
+ */
110
+ public function getAccessToken()
111
+ {
112
+ return $this->request->getAccessToken();
113
+ }
114
+
115
+ /**
116
+ * Return the HTTP status code for this response.
117
+ *
118
+ * @return int
119
+ */
120
+ public function getHttpStatusCode()
121
+ {
122
+ return $this->httpStatusCode;
123
+ }
124
+
125
+ /**
126
+ * Return the HTTP headers for this response.
127
+ *
128
+ * @return array
129
+ */
130
+ public function getHeaders()
131
+ {
132
+ return $this->headers;
133
+ }
134
+
135
+ /**
136
+ * Return the raw body response.
137
+ *
138
+ * @return string
139
+ */
140
+ public function getBody()
141
+ {
142
+ return $this->body;
143
+ }
144
+
145
+ /**
146
+ * Return the decoded body response.
147
+ *
148
+ * @return array
149
+ */
150
+ public function getDecodedBody()
151
+ {
152
+ return $this->decodedBody;
153
+ }
154
+
155
+ /**
156
+ * Get the app secret proof that was used for this response.
157
+ *
158
+ * @return string|null
159
+ */
160
+ public function getAppSecretProof()
161
+ {
162
+ return $this->request->getAppSecretProof();
163
+ }
164
+
165
+ /**
166
+ * Get the ETag associated with the response.
167
+ *
168
+ * @return string|null
169
+ */
170
+ public function getETag()
171
+ {
172
+ return isset($this->headers['ETag']) ? $this->headers['ETag'] : null;
173
+ }
174
+
175
+ /**
176
+ * Get the version of Graph that returned this response.
177
+ *
178
+ * @return string|null
179
+ */
180
+ public function getGraphVersion()
181
+ {
182
+ return isset($this->headers['Facebook-API-Version']) ? $this->headers['Facebook-API-Version'] : null;
183
+ }
184
+
185
+ /**
186
+ * Returns true if Graph returned an error message.
187
+ *
188
+ * @return boolean
189
+ */
190
+ public function isError()
191
+ {
192
+ return isset($this->decodedBody['error']);
193
+ }
194
+
195
+ /**
196
+ * Throws the exception.
197
+ *
198
+ * @throws FacebookSDKException
199
+ */
200
+ public function throwException()
201
+ {
202
+ throw $this->thrownException;
203
+ }
204
+
205
+ /**
206
+ * Instantiates an exception to be thrown later.
207
+ */
208
+ public function makeException()
209
+ {
210
+ $this->thrownException = FacebookResponseException::create($this);
211
+ }
212
+
213
+ /**
214
+ * Returns the exception that was thrown for this request.
215
+ *
216
+ * @return FacebookSDKException|null
217
+ */
218
+ public function getThrownException()
219
+ {
220
+ return $this->thrownException;
221
+ }
222
+
223
+ /**
224
+ * Convert the raw response into an array if possible.
225
+ *
226
+ * Graph will return 2 types of responses:
227
+ * - JSON(P)
228
+ * Most responses from Graph are JSON(P)
229
+ * - application/x-www-form-urlencoded key/value pairs
230
+ * Happens on the `/oauth/access_token` endpoint when exchanging
231
+ * a short-lived access token for a long-lived access token
232
+ * - And sometimes nothing :/ but that'd be a bug.
233
+ */
234
+ public function decodeBody()
235
+ {
236
+ $this->decodedBody = json_decode($this->body, true);
237
+
238
+ if ($this->decodedBody === null) {
239
+ $this->decodedBody = [];
240
+ parse_str($this->body, $this->decodedBody);
241
+ } elseif (is_bool($this->decodedBody)) {
242
+ // Backwards compatibility for Graph < 2.1.
243
+ // Mimics 2.1 responses.
244
+ // @TODO Remove this after Graph 2.0 is no longer supported
245
+ $this->decodedBody = ['success' => $this->decodedBody];
246
+ } elseif (is_numeric($this->decodedBody)) {
247
+ $this->decodedBody = ['id' => $this->decodedBody];
248
+ }
249
+
250
+ if (!is_array($this->decodedBody)) {
251
+ $this->decodedBody = [];
252
+ }
253
+
254
+ if ($this->isError()) {
255
+ $this->makeException();
256
+ }
257
+ }
258
+
259
+ /**
260
+ * Instantiate a new GraphObject from response.
261
+ *
262
+ * @param string|null $subclassName The GraphNode subclass to cast to.
263
+ *
264
+ * @return \Facebook\GraphNodes\GraphObject
265
+ *
266
+ * @throws FacebookSDKException
267
+ *
268
+ * @deprecated 5.0.0 getGraphObject() has been renamed to getGraphNode()
269
+ * @todo v6: Remove this method
270
+ */
271
+ public function getGraphObject($subclassName = null)
272
+ {
273
+ return $this->getGraphNode($subclassName);
274
+ }
275
+
276
+ /**
277
+ * Instantiate a new GraphNode from response.
278
+ *
279
+ * @param string|null $subclassName The GraphNode subclass to cast to.
280
+ *
281
+ * @return \Facebook\GraphNodes\GraphNode
282
+ *
283
+ * @throws FacebookSDKException
284
+ */
285
+ public function getGraphNode($subclassName = null)
286
+ {
287
+ $factory = new GraphNodeFactory($this);
288
+
289
+ return $factory->makeGraphNode($subclassName);
290
+ }
291
+
292
+ /**
293
+ * Convenience method for creating a GraphAlbum collection.
294
+ *
295
+ * @return \Facebook\GraphNodes\GraphAlbum
296
+ *
297
+ * @throws FacebookSDKException
298
+ */
299
+ public function getGraphAlbum()
300
+ {
301
+ $factory = new GraphNodeFactory($this);
302
+
303
+ return $factory->makeGraphAlbum();
304
+ }
305
+
306
+ /**
307
+ * Convenience method for creating a GraphPage collection.
308
+ *
309
+ * @return \Facebook\GraphNodes\GraphPage
310
+ *
311
+ * @throws FacebookSDKException
312
+ */
313
+ public function getGraphPage()
314
+ {
315
+ $factory = new GraphNodeFactory($this);
316
+
317
+ return $factory->makeGraphPage();
318
+ }
319
+
320
+ /**
321
+ * Convenience method for creating a GraphSessionInfo collection.
322
+ *
323
+ * @return \Facebook\GraphNodes\GraphSessionInfo
324
+ *
325
+ * @throws FacebookSDKException
326
+ */
327
+ public function getGraphSessionInfo()
328
+ {
329
+ $factory = new GraphNodeFactory($this);
330
+
331
+ return $factory->makeGraphSessionInfo();
332
+ }
333
+
334
+ /**
335
+ * Convenience method for creating a GraphUser collection.
336
+ *
337
+ * @return \Facebook\GraphNodes\GraphUser
338
+ *
339
+ * @throws FacebookSDKException
340
+ */
341
+ public function getGraphUser()
342
+ {
343
+ $factory = new GraphNodeFactory($this);
344
+
345
+ return $factory->makeGraphUser();
346
+ }
347
+
348
+ /**
349
+ * Convenience method for creating a GraphEvent collection.
350
+ *
351
+ * @return \Facebook\GraphNodes\GraphEvent
352
+ *
353
+ * @throws FacebookSDKException
354
+ */
355
+ public function getGraphEvent()
356
+ {
357
+ $factory = new GraphNodeFactory($this);
358
+
359
+ return $factory->makeGraphEvent();
360
+ }
361
+
362
+ /**
363
+ * Convenience method for creating a GraphGroup collection.
364
+ *
365
+ * @return \Facebook\GraphNodes\GraphGroup
366
+ *
367
+ * @throws FacebookSDKException
368
+ */
369
+ public function getGraphGroup()
370
+ {
371
+ $factory = new GraphNodeFactory($this);
372
+
373
+ return $factory->makeGraphGroup();
374
+ }
375
+
376
+ /**
377
+ * Instantiate a new GraphList from response.
378
+ *
379
+ * @param string|null $subclassName The GraphNode subclass to cast list items to.
380
+ * @param boolean $auto_prefix Toggle to auto-prefix the subclass name.
381
+ *
382
+ * @return \Facebook\GraphNodes\GraphList
383
+ *
384
+ * @throws FacebookSDKException
385
+ *
386
+ * @deprecated 5.0.0 getGraphList() has been renamed to getGraphEdge()
387
+ * @todo v6: Remove this method
388
+ */
389
+ public function getGraphList($subclassName = null, $auto_prefix = true)
390
+ {
391
+ return $this->getGraphEdge($subclassName, $auto_prefix);
392
+ }
393
+
394
+ /**
395
+ * Instantiate a new GraphEdge from response.
396
+ *
397
+ * @param string|null $subclassName The GraphNode subclass to cast list items to.
398
+ * @param boolean $auto_prefix Toggle to auto-prefix the subclass name.
399
+ *
400
+ * @return \Facebook\GraphNodes\GraphEdge
401
+ *
402
+ * @throws FacebookSDKException
403
+ */
404
+ public function getGraphEdge($subclassName = null, $auto_prefix = true)
405
+ {
406
+ $factory = new GraphNodeFactory($this);
407
+
408
+ return $factory->makeGraphEdge($subclassName, $auto_prefix);
409
+ }
410
+ }
vendor/facebook/php-sdk-v4/src/Facebook/FileUpload/FacebookFile.php ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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\FileUpload;
25
+
26
+ use Facebook\Exceptions\FacebookSDKException;
27
+
28
+ /**
29
+ * Class FacebookFile
30
+ *
31
+ * @package Facebook
32
+ */
33
+ class FacebookFile
34
+ {
35
+ /**
36
+ * @var string The path to the file on the system.
37
+ */
38
+ protected $path;
39
+
40
+ /**
41
+ * @var int The maximum bytes to read. Defaults to -1 (read all the remaining buffer).
42
+ */
43
+ private $maxLength;
44
+
45
+ /**
46
+ * @var int Seek to the specified offset before reading. If this number is negative, no seeking will occur and reading will start from the current position.
47
+ */
48
+ private $offset;
49
+
50
+ /**
51
+ * @var resource The stream pointing to the file.
52
+ */
53
+ protected $stream;
54
+
55
+ /**
56
+ * Creates a new FacebookFile entity.
57
+ *
58
+ * @param string $filePath
59
+ * @param int $maxLength
60
+ * @param int $offset
61
+ *
62
+ * @throws FacebookSDKException
63
+ */
64
+ public function __construct($filePath, $maxLength = -1, $offset = -1)
65
+ {
66
+ $this->path = $filePath;
67
+ $this->maxLength = $maxLength;
68
+ $this->offset = $offset;
69
+ $this->open();
70
+ }
71
+
72
+ /**
73
+ * Closes the stream when destructed.
74
+ */
75
+ public function __destruct()
76
+ {
77
+ $this->close();
78
+ }
79
+
80
+ /**
81
+ * Opens a stream for the file.
82
+ *
83
+ * @throws FacebookSDKException
84
+ */
85
+ public function open()
86
+ {
87
+ if (!$this->isRemoteFile($this->path) && !is_readable($this->path)) {
88
+ throw new FacebookSDKException('Failed to create FacebookFile entity. Unable to read resource: ' . $this->path . '.');
89
+ }
90
+
91
+ $this->stream = fopen($this->path, 'r');
92
+
93
+ if (!$this->stream) {
94
+ throw new FacebookSDKException('Failed to create FacebookFile entity. Unable to open resource: ' . $this->path . '.');
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Stops the file stream.
100
+ */
101
+ public function close()
102
+ {
103
+ if (is_resource($this->stream)) {
104
+ fclose($this->stream);
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Return the contents of the file.
110
+ *
111
+ * @return string
112
+ */
113
+ public function getContents()
114
+ {
115
+ return stream_get_contents($this->stream, $this->maxLength, $this->offset);
116
+ }
117
+
118
+ /**
119
+ * Return the name of the file.
120
+ *
121
+ * @return string
122
+ */
123
+ public function getFileName()
124
+ {
125
+ return basename($this->path);
126
+ }
127
+
128
+ /**
129
+ * Return the path of the file.
130
+ *
131
+ * @return string
132
+ */
133
+ public function getFilePath()
134
+ {
135
+ return $this->path;
136
+ }
137
+
138
+ /**
139
+ * Return the size of the file.
140
+ *
141
+ * @return int
142
+ */
143
+ public function getSize()
144
+ {
145
+ return filesize($this->path);
146
+ }
147
+
148
+ /**
149
+ * Return the mimetype of the file.
150
+ *
151
+ * @return string
152
+ */
153
+ public function getMimetype()
154
+ {
155
+ return Mimetypes::getInstance()->fromFilename($this->path) ?: 'text/plain';
156
+ }
157
+
158
+ /**
159
+ * Returns true if the path to the file is remote.
160
+ *
161
+ * @param string $pathToFile
162
+ *
163
+ * @return boolean
164
+ */
165
+ protected function isRemoteFile($pathToFile)
166
+ {
167
+ return preg_match('/^(https?|ftp):\/\/.*/', $pathToFile) === 1;
168
+ }
169
+ }
vendor/facebook/php-sdk-v4/src/Facebook/FileUpload/FacebookResumableUploader.php ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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\FileUpload;
25
+
26
+ use Facebook\Authentication\AccessToken;
27
+ use Facebook\Exceptions\FacebookResponseException;
28
+ use Facebook\Exceptions\FacebookResumableUploadException;
29
+ use Facebook\Exceptions\FacebookSDKException;
30
+ use Facebook\FacebookApp;
31
+ use Facebook\FacebookClient;
32
+ use Facebook\FacebookRequest;
33
+
34
+ /**
35
+ * Class FacebookResumableUploader
36
+ *
37
+ * @package Facebook
38
+ */
39
+ class FacebookResumableUploader
40
+ {
41
+ /**
42
+ * @var FacebookApp
43
+ */
44
+ protected $app;
45
+
46
+ /**
47
+ * @var string
48
+ */
49
+ protected $accessToken;
50
+
51
+ /**
52
+ * @var FacebookClient The Facebook client service.
53
+ */
54
+ protected $client;
55
+
56
+ /**
57
+ * @var string Graph version to use for this request.
58
+ */
59
+ protected $graphVersion;
60
+
61
+ /**
62
+ * @param FacebookApp $app
63
+ * @param FacebookClient $client
64
+ * @param AccessToken|string|null $accessToken
65
+ * @param string $graphVersion
66
+ */
67
+ public function __construct(FacebookApp $app, FacebookClient $client, $accessToken, $graphVersion)
68
+ {
69
+ $this->app = $app;
70
+ $this->client = $client;
71
+ $this->accessToken = $accessToken;
72
+ $this->graphVersion = $graphVersion;
73
+ }
74
+
75
+ /**
76
+ * Upload by chunks - start phase
77
+ *
78
+ * @param string $endpoint
79
+ * @param FacebookFile $file
80
+ *
81
+ * @return FacebookTransferChunk
82
+ *
83
+ * @throws FacebookSDKException
84
+ */
85
+ public function start($endpoint, FacebookFile $file)
86
+ {
87
+ $params = [
88
+ 'upload_phase' => 'start',
89
+ 'file_size' => $file->getSize(),
90
+ ];
91
+ $response = $this->sendUploadRequest($endpoint, $params);
92
+
93
+ return new FacebookTransferChunk($file, $response['upload_session_id'], $response['video_id'], $response['start_offset'], $response['end_offset']);
94
+ }
95
+
96
+ /**
97
+ * Upload by chunks - transfer phase
98
+ *
99
+ * @param string $endpoint
100
+ * @param FacebookTransferChunk $chunk
101
+ * @param boolean $allowToThrow
102
+ *
103
+ * @return FacebookTransferChunk
104
+ *
105
+ * @throws FacebookResponseException
106
+ */
107
+ public function transfer($endpoint, FacebookTransferChunk $chunk, $allowToThrow = false)
108
+ {
109
+ $params = [
110
+ 'upload_phase' => 'transfer',
111
+ 'upload_session_id' => $chunk->getUploadSessionId(),
112
+ 'start_offset' => $chunk->getStartOffset(),
113
+ 'video_file_chunk' => $chunk->getPartialFile(),
114
+ ];
115
+
116
+ try {
117
+ $response = $this->sendUploadRequest($endpoint, $params);
118
+ } catch (FacebookResponseException $e) {
119
+ $preException = $e->getPrevious();
120
+ if ($allowToThrow || !$preException instanceof FacebookResumableUploadException) {
121
+ throw $e;
122
+ }
123
+
124
+ // Return the same chunk entity so it can be retried.
125
+ return $chunk;
126
+ }
127
+
128
+ return new FacebookTransferChunk($chunk->getFile(), $chunk->getUploadSessionId(), $chunk->getVideoId(), $response['start_offset'], $response['end_offset']);
129
+ }
130
+
131
+ /**
132
+ * Upload by chunks - finish phase
133
+ *
134
+ * @param string $endpoint
135
+ * @param string $uploadSessionId
136
+ * @param array $metadata The metadata associated with the file.
137
+ *
138
+ * @return boolean
139
+ *
140
+ * @throws FacebookSDKException
141
+ */
142
+ public function finish($endpoint, $uploadSessionId, $metadata = [])
143
+ {
144
+ $params = array_merge($metadata, [
145
+ 'upload_phase' => 'finish',
146
+ 'upload_session_id' => $uploadSessionId,
147
+ ]);
148
+ $response = $this->sendUploadRequest($endpoint, $params);
149
+
150
+ return $response['success'];
151
+ }
152
+
153
+ /**
154
+ * Helper to make a FacebookRequest and send it.
155
+ *
156
+ * @param string $endpoint The endpoint to POST to.
157
+ * @param array $params The params to send with the request.
158
+ *
159
+ * @return array
160
+ */
161
+ private function sendUploadRequest($endpoint, $params = [])
162
+ {
163
+ $request = new FacebookRequest($this->app, $this->accessToken, 'POST', $endpoint, $params, null, $this->graphVersion);
164
+
165
+ return $this->client->sendRequest($request)->getDecodedBody();
166
+ }
167
+ }
vendor/facebook/php-sdk-v4/src/Facebook/FileUpload/FacebookTransferChunk.php ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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\FileUpload;
25
+
26
+ /**
27
+ * Class FacebookTransferChunk
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class FacebookTransferChunk
32
+ {
33
+ /**
34
+ * @var FacebookFile The file to chunk during upload.
35
+ */
36
+ private $file;
37
+
38
+ /**
39
+ * @var int The ID of the upload session.
40
+ */
41
+ private $uploadSessionId;
42
+
43
+ /**
44
+ * @var int Start byte position of the next file chunk.
45
+ */
46
+ private $startOffset;
47
+
48
+ /**
49
+ * @var int End byte position of the next file chunk.
50
+ */
51
+ private $endOffset;
52
+
53
+ /**
54
+ * @var int The ID of the video.
55
+ */
56
+ private $videoId;
57
+
58
+ /**
59
+ * @param FacebookFile $file
60
+ * @param int $uploadSessionId
61
+ * @param int $videoId
62
+ * @param int $startOffset
63
+ * @param int $endOffset
64
+ */
65
+ public function __construct(FacebookFile $file, $uploadSessionId, $videoId, $startOffset, $endOffset)
66
+ {
67
+ $this->file = $file;
68
+ $this->uploadSessionId = $uploadSessionId;
69
+ $this->videoId = $videoId;
70
+ $this->startOffset = $startOffset;
71
+ $this->endOffset = $endOffset;
72
+ }
73
+
74
+ /**
75
+ * Return the file entity.
76
+ *
77
+ * @return FacebookFile
78
+ */
79
+ public function getFile()
80
+ {
81
+ return $this->file;
82
+ }
83
+
84
+ /**
85
+ * Return a FacebookFile entity with partial content.
86
+ *
87
+ * @return FacebookFile
88
+ */
89
+ public function getPartialFile()
90
+ {
91
+ $maxLength = $this->endOffset - $this->startOffset;
92
+
93
+ return new FacebookFile($this->file->getFilePath(), $maxLength, $this->startOffset);
94
+ }
95
+
96
+ /**
97
+ * Return upload session Id
98
+ *
99
+ * @return int
100
+ */
101
+ public function getUploadSessionId()
102
+ {
103
+ return $this->uploadSessionId;
104
+ }
105
+
106
+ /**
107
+ * Check whether is the last chunk
108
+ *
109
+ * @return bool
110
+ */
111
+ public function isLastChunk()
112
+ {
113
+ return $this->startOffset === $this->endOffset;
114
+ }
115
+
116
+ /**
117
+ * @return int
118
+ */
119
+ public function getStartOffset()
120
+ {
121
+ return $this->startOffset;
122
+ }
123
+
124
+ /**
125
+ * Get uploaded video Id
126
+ *
127
+ * @return int
128
+ */
129
+ public function getVideoId()
130
+ {
131
+ return $this->videoId;
132
+ }
133
+ }
vendor/facebook/php-sdk-v4/src/Facebook/FileUpload/FacebookVideo.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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\FileUpload;
25
+
26
+ /**
27
+ * Class FacebookVideo
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class FacebookVideo extends FacebookFile
32
+ {
33
+ }
vendor/facebook/php-sdk-v4/src/Facebook/FileUpload/Mimetypes.php ADDED
@@ -0,0 +1,987 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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\FileUpload;
25
+
26
+ /**
27
+ * Provides mappings of file extensions to mimetypes
28
+ *
29
+ * Taken from Guzzle
30
+ *
31
+ * @see https://github.com/guzzle/guzzle/blob/master/src/Mimetypes.php
32
+ *
33
+ * @link http://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x/conf/mime.types
34
+ */
35
+ class Mimetypes
36
+ {
37
+ /** @var self */
38
+ protected static $instance;
39
+
40
+ /** @var array Mapping of extension to mimetype */
41
+ protected $mimetypes = [
42
+ '3dml' => 'text/vnd.in3d.3dml',
43
+ '3g2' => 'video/3gpp2',
44
+ '3gp' => 'video/3gpp',
45
+ '7z' => 'application/x-7z-compressed',
46
+ 'aab' => 'application/x-authorware-bin',
47
+ 'aac' => 'audio/x-aac',
48
+ 'aam' => 'application/x-authorware-map',
49
+ 'aas' => 'application/x-authorware-seg',
50
+ 'abw' => 'application/x-abiword',
51
+ 'ac' => 'application/pkix-attr-cert',
52
+ 'acc' => 'application/vnd.americandynamics.acc',
53
+ 'ace' => 'application/x-ace-compressed',
54
+ 'acu' => 'application/vnd.acucobol',
55
+ 'acutc' => 'application/vnd.acucorp',
56
+ 'adp' => 'audio/adpcm',
57
+ 'aep' => 'application/vnd.audiograph',
58
+ 'afm' => 'application/x-font-type1',
59
+ 'afp' => 'application/vnd.ibm.modcap',
60
+ 'ahead' => 'application/vnd.ahead.space',
61
+ 'ai' => 'application/postscript',
62
+ 'aif' => 'audio/x-aiff',
63
+ 'aifc' => 'audio/x-aiff',
64
+ 'aiff' => 'audio/x-aiff',
65
+ 'air' => 'application/vnd.adobe.air-application-installer-package+zip',
66
+ 'ait' => 'application/vnd.dvb.ait',
67
+ 'ami' => 'application/vnd.amiga.ami',
68
+ 'apk' => 'application/vnd.android.package-archive',
69
+ 'application' => 'application/x-ms-application',
70
+ 'apr' => 'application/vnd.lotus-approach',
71
+ 'asa' => 'text/plain',
72
+ 'asax' => 'application/octet-stream',
73
+ 'asc' => 'application/pgp-signature',
74
+ 'ascx' => 'text/plain',
75
+ 'asf' => 'video/x-ms-asf',
76
+ 'ashx' => 'text/plain',
77
+ 'asm' => 'text/x-asm',
78
+ 'asmx' => 'text/plain',
79
+ 'aso' => 'application/vnd.accpac.simply.aso',
80
+ 'asp' => 'text/plain',
81
+ 'aspx' => 'text/plain',
82
+ 'asx' => 'video/x-ms-asf',
83
+ 'atc' => 'application/vnd.acucorp',
84
+ 'atom' => 'application/atom+xml',
85
+ 'atomcat' => 'application/atomcat+xml',
86
+ 'atomsvc' => 'application/atomsvc+xml',
87
+ 'atx' => 'application/vnd.antix.game-component',
88
+ 'au' => 'audio/basic',
89
+ 'avi' => 'video/x-msvideo',
90
+ 'aw' => 'application/applixware',
91
+ 'axd' => 'text/plain',
92
+ 'azf' => 'application/vnd.airzip.filesecure.azf',
93
+ 'azs' => 'application/vnd.airzip.filesecure.azs',
94
+ 'azw' => 'application/vnd.amazon.ebook',
95
+ 'bat' => 'application/x-msdownload',
96
+ 'bcpio' => 'application/x-bcpio',
97
+ 'bdf' => 'application/x-font-bdf',
98
+ 'bdm' => 'application/vnd.syncml.dm+wbxml',
99
+ 'bed' => 'application/vnd.realvnc.bed',
100
+ 'bh2' => 'application/vnd.fujitsu.oasysprs',
101
+ 'bin' => 'application/octet-stream',
102
+ 'bmi' => 'application/vnd.bmi',
103
+ 'bmp' => 'image/bmp',
104
+ 'book' => 'application/vnd.framemaker',
105
+ 'box' => 'application/vnd.previewsystems.box',
106
+ 'boz' => 'application/x-bzip2',
107
+ 'bpk' => 'application/octet-stream',
108
+ 'btif' => 'image/prs.btif',
109
+ 'bz' => 'application/x-bzip',
110
+ 'bz2' => 'application/x-bzip2',
111
+ 'c' => 'text/x-c',
112
+ 'c11amc' => 'application/vnd.cluetrust.cartomobile-config',
113
+ 'c11amz' => 'application/vnd.cluetrust.cartomobile-config-pkg',
114
+ 'c4d' => 'application/vnd.clonk.c4group',
115
+ 'c4f' => 'application/vnd.clonk.c4group',
116
+ 'c4g' => 'application/vnd.clonk.c4group',
117
+ 'c4p' => 'application/vnd.clonk.c4group',
118
+ 'c4u' => 'application/vnd.clonk.c4group',
119
+ 'cab' => 'application/vnd.ms-cab-compressed',
120
+ 'car' => 'application/vnd.curl.car',
121
+ 'cat' => 'application/vnd.ms-pki.seccat',
122
+ 'cc' => 'text/x-c',
123
+ 'cct' => 'application/x-director',
124
+ 'ccxml' => 'application/ccxml+xml',
125
+ 'cdbcmsg' => 'application/vnd.contact.cmsg',
126
+ 'cdf' => 'application/x-netcdf',
127
+ 'cdkey' => 'application/vnd.mediastation.cdkey',
128
+ 'cdmia' => 'application/cdmi-capability',
129
+ 'cdmic' => 'application/cdmi-container',
130
+ 'cdmid' => 'application/cdmi-domain',
131
+ 'cdmio' => 'application/cdmi-object',
132
+ 'cdmiq' => 'application/cdmi-queue',
133
+ 'cdx' => 'chemical/x-cdx',
134
+ 'cdxml' => 'application/vnd.chemdraw+xml',
135
+ 'cdy' => 'application/vnd.cinderella',
136
+ 'cer' => 'application/pkix-cert',
137
+ 'cfc' => 'application/x-coldfusion',
138
+ 'cfm' => 'application/x-coldfusion',
139
+ 'cgm' => 'image/cgm',
140
+ 'chat' => 'application/x-chat',
141
+ 'chm' => 'application/vnd.ms-htmlhelp',
142
+ 'chrt' => 'application/vnd.kde.kchart',
143
+ 'cif' => 'chemical/x-cif',
144
+ 'cii' => 'application/vnd.anser-web-certificate-issue-initiation',
145
+ 'cil' => 'application/vnd.ms-artgalry',
146
+ 'cla' => 'application/vnd.claymore',
147
+ 'class' => 'application/java-vm',
148
+ 'clkk' => 'application/vnd.crick.clicker.keyboard',
149
+ 'clkp' => 'application/vnd.crick.clicker.palette',
150
+ 'clkt' => 'application/vnd.crick.clicker.template',
151
+ 'clkw' => 'application/vnd.crick.clicker.wordbank',
152
+ 'clkx' => 'application/vnd.crick.clicker',
153
+ 'clp' => 'application/x-msclip',
154
+ 'cmc' => 'application/vnd.cosmocaller',
155
+ 'cmdf' => 'chemical/x-cmdf',
156
+ 'cml' => 'chemical/x-cml',
157
+ 'cmp' => 'application/vnd.yellowriver-custom-menu',
158
+ 'cmx' => 'image/x-cmx',
159
+ 'cod' => 'application/vnd.rim.cod',
160
+ 'com' => 'application/x-msdownload',
161
+ 'conf' => 'text/plain',
162
+ 'cpio' => 'application/x-cpio',
163
+ 'cpp' => 'text/x-c',
164
+ 'cpt' => 'application/mac-compactpro',
165
+ 'crd' => 'application/x-mscardfile',
166
+ 'crl' => 'application/pkix-crl',
167
+ 'crt' => 'application/x-x509-ca-cert',
168
+ 'cryptonote' => 'application/vnd.rig.cryptonote',
169
+ 'cs' => 'text/plain',
170
+ 'csh' => 'application/x-csh',
171
+ 'csml' => 'chemical/x-csml',
172
+ 'csp' => 'application/vnd.commonspace',
173
+ 'css' => 'text/css',
174
+ 'cst' => 'application/x-director',
175
+ 'csv' => 'text/csv',
176
+ 'cu' => 'application/cu-seeme',
177
+ 'curl' => 'text/vnd.curl',
178
+ 'cww' => 'application/prs.cww',
179
+ 'cxt' => 'application/x-director',
180
+ 'cxx' => 'text/x-c',
181
+ 'dae' => 'model/vnd.collada+xml',
182
+ 'daf' => 'application/vnd.mobius.daf',
183
+ 'dataless' => 'application/vnd.fdsn.seed',
184
+ 'davmount' => 'application/davmount+xml',
185
+ 'dcr' => 'application/x-director',
186
+ 'dcurl' => 'text/vnd.curl.dcurl',
187
+ 'dd2' => 'application/vnd.oma.dd2+xml',
188
+ 'ddd' => 'application/vnd.fujixerox.ddd',
189
+ 'deb' => 'application/x-debian-package',
190
+ 'def' => 'text/plain',
191
+ 'deploy' => 'application/octet-stream',
192
+ 'der' => 'application/x-x509-ca-cert',
193
+ 'dfac' => 'application/vnd.dreamfactory',
194
+ 'dic' => 'text/x-c',
195
+ 'dir' => 'application/x-director',
196
+ 'dis' => 'application/vnd.mobius.dis',
197
+ 'dist' => 'application/octet-stream',
198
+ 'distz' => 'application/octet-stream',
199
+ 'djv' => 'image/vnd.djvu',
200
+ 'djvu' => 'image/vnd.djvu',
201
+ 'dll' => 'application/x-msdownload',
202
+ 'dmg' => 'application/octet-stream',
203
+ 'dms' => 'application/octet-stream',
204
+ 'dna' => 'application/vnd.dna',
205
+ 'doc' => 'application/msword',
206
+ 'docm' => 'application/vnd.ms-word.document.macroenabled.12',
207
+ 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
208
+ 'dot' => 'application/msword',
209
+ 'dotm' => 'application/vnd.ms-word.template.macroenabled.12',
210
+ 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
211
+ 'dp' => 'application/vnd.osgi.dp',
212
+ 'dpg' => 'application/vnd.dpgraph',
213
+ 'dra' => 'audio/vnd.dra',
214
+ 'dsc' => 'text/prs.lines.tag',
215
+ 'dssc' => 'application/dssc+der',
216
+ 'dtb' => 'application/x-dtbook+xml',
217
+ 'dtd' => 'application/xml-dtd',
218
+ 'dts' => 'audio/vnd.dts',
219
+ 'dtshd' => 'audio/vnd.dts.hd',
220
+ 'dump' => 'application/octet-stream',
221
+ 'dvi' => 'application/x-dvi',
222
+ 'dwf' => 'model/vnd.dwf',
223
+ 'dwg' => 'image/vnd.dwg',
224
+ 'dxf' => 'image/vnd.dxf',
225
+ 'dxp' => 'application/vnd.spotfire.dxp',
226
+ 'dxr' => 'application/x-director',
227
+ 'ecelp4800' => 'audio/vnd.nuera.ecelp4800',
228
+ 'ecelp7470' => 'audio/vnd.nuera.ecelp7470',
229
+ 'ecelp9600' => 'audio/vnd.nuera.ecelp9600',
230
+ 'ecma' => 'application/ecmascript',
231
+ 'edm' => 'application/vnd.novadigm.edm',
232
+ 'edx' => 'application/vnd.novadigm.edx',
233
+ 'efif' => 'application/vnd.picsel',
234
+ 'ei6' => 'application/vnd.pg.osasli',
235
+ 'elc' => 'application/octet-stream',
236
+ 'eml' => 'message/rfc822',
237
+ 'emma' => 'application/emma+xml',
238
+ 'eol' => 'audio/vnd.digital-winds',
239
+ 'eot' => 'application/vnd.ms-fontobject',
240
+ 'eps' => 'application/postscript',
241
+ 'epub' => 'application/epub+zip',
242
+ 'es3' => 'application/vnd.eszigno3+xml',
243
+ 'esf' => 'application/vnd.epson.esf',
244
+ 'et3' => 'application/vnd.eszigno3+xml',
245
+ 'etx' => 'text/x-setext',
246
+ 'exe' => 'application/x-msdownload',
247
+ 'exi' => 'application/exi',
248
+ 'ext' => 'application/vnd.novadigm.ext',
249
+ 'ez' => 'application/andrew-inset',
250
+ 'ez2' => 'application/vnd.ezpix-album',
251
+ 'ez3' => 'application/vnd.ezpix-package',
252
+ 'f' => 'text/x-fortran',
253
+ 'f4v' => 'video/x-f4v',
254
+ 'f77' => 'text/x-fortran',
255
+ 'f90' => 'text/x-fortran',
256
+ 'fbs' => 'image/vnd.fastbidsheet',
257
+ 'fcs' => 'application/vnd.isac.fcs',
258
+ 'fdf' => 'application/vnd.fdf',
259
+ 'fe_launch' => 'application/vnd.denovo.fcselayout-link',
260
+ 'fg5' => 'application/vnd.fujitsu.oasysgp',
261
+ 'fgd' => 'application/x-director',
262
+ 'fh' => 'image/x-freehand',
263
+ 'fh4' => 'image/x-freehand',
264
+ 'fh5' => 'image/x-freehand',
265
+ 'fh7' => 'image/x-freehand',
266
+ 'fhc' => 'image/x-freehand',
267
+ 'fig' => 'application/x-xfig',
268
+ 'fli' => 'video/x-fli',
269
+ 'flo' => 'application/vnd.micrografx.flo',
270
+ 'flv' => 'video/x-flv',
271
+ 'flw' => 'application/vnd.kde.kivio',
272
+ 'flx' => 'text/vnd.fmi.flexstor',
273
+ 'fly' => 'text/vnd.fly',
274
+ 'fm' => 'application/vnd.framemaker',
275
+ 'fnc' => 'application/vnd.frogans.fnc',
276
+ 'for' => 'text/x-fortran',
277
+ 'fpx' => 'image/vnd.fpx',
278
+ 'frame' => 'application/vnd.framemaker',
279
+ 'fsc' => 'application/vnd.fsc.weblaunch',
280
+ 'fst' => 'image/vnd.fst',
281
+ 'ftc' => 'application/vnd.fluxtime.clip',
282
+ 'fti' => 'application/vnd.anser-web-funds-transfer-initiation',
283
+ 'fvt' => 'video/vnd.fvt',
284
+ 'fxp' => 'application/vnd.adobe.fxp',
285
+ 'fxpl' => 'application/vnd.adobe.fxp',
286
+ 'fzs' => 'application/vnd.fuzzysheet',
287
+ 'g2w' => 'application/vnd.geoplan',
288
+ 'g3' => 'image/g3fax',
289
+ 'g3w' => 'application/vnd.geospace',
290
+ 'gac' => 'application/vnd.groove-account',
291
+ 'gdl' => 'model/vnd.gdl',
292
+ 'geo' => 'application/vnd.dynageo',
293
+ 'gex' => 'application/vnd.geometry-explorer',
294
+ 'ggb' => 'application/vnd.geogebra.file',
295
+ 'ggt' => 'application/vnd.geogebra.tool',
296
+ 'ghf' => 'application/vnd.groove-help',
297
+ 'gif' => 'image/gif',
298
+ 'gim' => 'application/vnd.groove-identity-message',
299
+ 'gmx' => 'application/vnd.gmx',
300
+ 'gnumeric' => 'application/x-gnumeric',
301
+ 'gph' => 'application/vnd.flographit',
302
+ 'gqf' => 'application/vnd.grafeq',
303
+ 'gqs' => 'application/vnd.grafeq',
304
+ 'gram' => 'application/srgs',
305
+ 'gre' => 'application/vnd.geometry-explorer',
306
+ 'grv' => 'application/vnd.groove-injector',
307
+ 'grxml' => 'application/srgs+xml',
308
+ 'gsf' => 'application/x-font-ghostscript',
309
+ 'gtar' => 'application/x-gtar',
310
+ 'gtm' => 'application/vnd.groove-tool-message',
311
+ 'gtw' => 'model/vnd.gtw',
312
+ 'gv' => 'text/vnd.graphviz',
313
+ 'gxt' => 'application/vnd.geonext',
314
+ 'h' => 'text/x-c',
315
+ 'h261' => 'video/h261',
316
+ 'h263' => 'video/h263',
317
+ 'h264' => 'video/h264',
318
+ 'hal' => 'application/vnd.hal+xml',
319
+ 'hbci' => 'application/vnd.hbci',
320
+ 'hdf' => 'application/x-hdf',
321
+ 'hh' => 'text/x-c',
322
+ 'hlp' => 'application/winhlp',
323
+ 'hpgl' => 'application/vnd.hp-hpgl',
324
+ 'hpid' => 'application/vnd.hp-hpid',
325
+ 'hps' => 'application/vnd.hp-hps',
326
+ 'hqx' => 'application/mac-binhex40',
327
+ 'hta' => 'application/octet-stream',
328
+ 'htc' => 'text/html',
329
+ 'htke' => 'application/vnd.kenameaapp',
330
+ 'htm' => 'text/html',
331
+ 'html' => 'text/html',
332
+ 'hvd' => 'application/vnd.yamaha.hv-dic',
333
+ 'hvp' => 'application/vnd.yamaha.hv-voice',
334
+ 'hvs' => 'application/vnd.yamaha.hv-script',
335
+ 'i2g' => 'application/vnd.intergeo',
336
+ 'icc' => 'application/vnd.iccprofile',
337
+ 'ice' => 'x-conference/x-cooltalk',
338
+ 'icm' => 'application/vnd.iccprofile',
339
+ 'ico' => 'image/x-icon',
340
+ 'ics' => 'text/calendar',
341
+ 'ief' => 'image/ief',
342
+ 'ifb' => 'text/calendar',
343
+ 'ifm' => 'application/vnd.shana.informed.formdata',
344
+ 'iges' => 'model/iges',
345
+ 'igl' => 'application/vnd.igloader',
346
+ 'igm' => 'application/vnd.insors.igm',
347
+ 'igs' => 'model/iges',
348
+ 'igx' => 'application/vnd.micrografx.igx',
349
+ 'iif' => 'application/vnd.shana.informed.interchange',
350
+ 'imp' => 'application/vnd.accpac.simply.imp',
351
+ 'ims' => 'application/vnd.ms-ims',
352
+ 'in' => 'text/plain',
353
+ 'ini' => 'text/plain',
354
+ 'ipfix' => 'application/ipfix',
355
+ 'ipk' => 'application/vnd.shana.informed.package',
356
+ 'irm' => 'application/vnd.ibm.rights-management',
357
+ 'irp' => 'application/vnd.irepository.package+xml',
358
+ 'iso' => 'application/octet-stream',
359
+ 'itp' => 'application/vnd.shana.informed.formtemplate',
360
+ 'ivp' => 'application/vnd.immervision-ivp',
361
+ 'ivu' => 'application/vnd.immervision-ivu',
362
+ 'jad' => 'text/vnd.sun.j2me.app-descriptor',
363
+ 'jam' => 'application/vnd.jam',
364
+ 'jar' => 'application/java-archive',
365
+ 'java' => 'text/x-java-source',
366
+ 'jisp' => 'application/vnd.jisp',
367
+ 'jlt' => 'application/vnd.hp-jlyt',
368
+ 'jnlp' => 'application/x-java-jnlp-file',
369
+ 'joda' => 'application/vnd.joost.joda-archive',
370
+ 'jpe' => 'image/jpeg',
371
+ 'jpeg' => 'image/jpeg',
372
+ 'jpg' => 'image/jpeg',
373
+ 'jpgm' => 'video/jpm',
374
+ 'jpgv' => 'video/jpeg',
375
+ 'jpm' => 'video/jpm',
376
+ 'js' => 'text/javascript',
377
+ 'json' => 'application/json',
378
+ 'kar' => 'audio/midi',
379
+ 'karbon' => 'application/vnd.kde.karbon',
380
+ 'kfo' => 'application/vnd.kde.kformula',
381
+ 'kia' => 'application/vnd.kidspiration',
382
+ 'kml' => 'application/vnd.google-earth.kml+xml',
383
+ 'kmz' => 'application/vnd.google-earth.kmz',
384
+ 'kne' => 'application/vnd.kinar',
385
+ 'knp' => 'application/vnd.kinar',
386
+ 'kon' => 'application/vnd.kde.kontour',
387
+ 'kpr' => 'application/vnd.kde.kpresenter',
388
+ 'kpt' => 'application/vnd.kde.kpresenter',
389
+ 'ksp' => 'application/vnd.kde.kspread',
390
+ 'ktr' => 'application/vnd.kahootz',
391
+ 'ktx' => 'image/ktx',
392
+ 'ktz' => 'application/vnd.kahootz',
393
+ 'kwd' => 'application/vnd.kde.kword',
394
+ 'kwt' => 'application/vnd.kde.kword',
395
+ 'lasxml' => 'application/vnd.las.las+xml',
396
+ 'latex' => 'application/x-latex',
397
+ 'lbd' => 'application/vnd.llamagraphics.life-balance.desktop',
398
+ 'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml',
399
+ 'les' => 'application/vnd.hhe.lesson-player',
400
+ 'lha' => 'application/octet-stream',
401
+ 'link66' => 'application/vnd.route66.link66+xml',
402
+ 'list' => 'text/plain',
403
+ 'list3820' => 'application/vnd.ibm.modcap',
404
+ 'listafp' => 'application/vnd.ibm.modcap',
405
+ 'log' => 'text/plain',
406
+ 'lostxml' => 'application/lost+xml',
407
+ 'lrf' => 'application/octet-stream',
408
+ 'lrm' => 'application/vnd.ms-lrm',
409
+ 'ltf' => 'application/vnd.frogans.ltf',
410
+ 'lvp' => 'audio/vnd.lucent.voice',
411
+ 'lwp' => 'application/vnd.lotus-wordpro',
412
+ 'lzh' => 'application/octet-stream',
413
+ 'm13' => 'application/x-msmediaview',
414
+ 'm14' => 'application/x-msmediaview',
415
+ 'm1v' => 'video/mpeg',
416
+ 'm21' => 'application/mp21',
417
+ 'm2a' => 'audio/mpeg',
418
+ 'm2v' => 'video/mpeg',
419
+ 'm3a' => 'audio/mpeg',
420
+ 'm3u' => 'audio/x-mpegurl',
421
+ 'm3u8' => 'application/vnd.apple.mpegurl',
422
+ 'm4a' => 'audio/mp4',
423
+ 'm4u' => 'video/vnd.mpegurl',
424
+ 'm4v' => 'video/mp4',
425
+ 'ma' => 'application/mathematica',
426
+ 'mads' => 'application/mads+xml',
427
+ 'mag' => 'application/vnd.ecowin.chart',
428
+ 'maker' => 'application/vnd.framemaker',
429
+ 'man' => 'text/troff',
430
+ 'mathml' => 'application/mathml+xml',
431
+ 'mb' => 'application/mathematica',
432
+ 'mbk' => 'application/vnd.mobius.mbk',
433
+ 'mbox' => 'application/mbox',
434
+ 'mc1' => 'application/vnd.medcalcdata',
435
+ 'mcd' => 'application/vnd.mcd',
436
+ 'mcurl' => 'text/vnd.curl.mcurl',
437
+ 'mdb' => 'application/x-msaccess',
438
+ 'mdi' => 'image/vnd.ms-modi',
439
+ 'me' => 'text/troff',
440
+ 'mesh' => 'model/mesh',
441
+ 'meta4' => 'application/metalink4+xml',
442
+ 'mets' => 'application/mets+xml',
443
+ 'mfm' => 'application/vnd.mfmp',
444
+ 'mgp' => 'application/vnd.osgeo.mapguide.package',
445
+ 'mgz' => 'application/vnd.proteus.magazine',
446
+ 'mid' => 'audio/midi',
447
+ 'midi' => 'audio/midi',
448
+ 'mif' => 'application/vnd.mif',
449
+ 'mime' => 'message/rfc822',
450
+ 'mj2' => 'video/mj2',
451
+ 'mjp2' => 'video/mj2',
452
+ 'mlp' => 'application/vnd.dolby.mlp',
453
+ 'mmd' => 'application/vnd.chipnuts.karaoke-mmd',
454
+ 'mmf' => 'application/vnd.smaf',
455
+ 'mmr' => 'image/vnd.fujixerox.edmics-mmr',
456
+ 'mny' => 'application/x-msmoney',
457
+ 'mobi' => 'application/x-mobipocket-ebook',
458
+ 'mods' => 'application/mods+xml',
459
+ 'mov' => 'video/quicktime',
460
+ 'movie' => 'video/x-sgi-movie',
461
+ 'mp2' => 'audio/mpeg',
462
+ 'mp21' => 'application/mp21',
463
+ 'mp2a' => 'audio/mpeg',
464
+ 'mp3' => 'audio/mpeg',
465
+ 'mp4' => 'video/mp4',
466
+ 'mp4a' => 'audio/mp4',
467
+ 'mp4s' => 'application/mp4',
468
+ 'mp4v' => 'video/mp4',
469
+ 'mpc' => 'application/vnd.mophun.certificate',
470
+ 'mpe' => 'video/mpeg',
471
+ 'mpeg' => 'video/mpeg',
472
+ 'mpg' => 'video/mpeg',
473
+ 'mpg4' => 'video/mp4',
474
+ 'mpga' => 'audio/mpeg',
475
+ 'mpkg' => 'application/vnd.apple.installer+xml',
476
+ 'mpm' => 'application/vnd.blueice.multipass',
477
+ 'mpn' => 'application/vnd.mophun.application',
478
+ 'mpp' => 'application/vnd.ms-project',
479
+ 'mpt' => 'application/vnd.ms-project',
480
+ 'mpy' => 'application/vnd.ibm.minipay',
481
+ 'mqy' => 'application/vnd.mobius.mqy',
482
+ 'mrc' => 'application/marc',
483
+ 'mrcx' => 'application/marcxml+xml',
484
+ 'ms' => 'text/troff',
485
+ 'mscml' => 'application/mediaservercontrol+xml',
486
+ 'mseed' => 'application/vnd.fdsn.mseed',
487
+ 'mseq' => 'application/vnd.mseq',
488
+ 'msf' => 'application/vnd.epson.msf',
489
+ 'msh' => 'model/mesh',
490
+ 'msi' => 'application/x-msdownload',
491
+ 'msl' => 'application/vnd.mobius.msl',
492
+ 'msty' => 'application/vnd.muvee.style',
493
+ 'mts' => 'model/vnd.mts',
494
+ 'mus' => 'application/vnd.musician',
495
+ 'musicxml' => 'application/vnd.recordare.musicxml+xml',
496
+ 'mvb' => 'application/x-msmediaview',
497
+ 'mwf' => 'application/vnd.mfer',
498
+ 'mxf' => 'application/mxf',
499
+ 'mxl' => 'application/vnd.recordare.musicxml',
500
+ 'mxml' => 'application/xv+xml',
501
+ 'mxs' => 'application/vnd.triscape.mxs',
502
+ 'mxu' => 'video/vnd.mpegurl',
503
+ 'n-gage' => 'application/vnd.nokia.n-gage.symbian.install',
504
+ 'n3' => 'text/n3',
505
+ 'nb' => 'application/mathematica',
506
+ 'nbp' => 'application/vnd.wolfram.player',
507
+ 'nc' => 'application/x-netcdf',
508
+ 'ncx' => 'application/x-dtbncx+xml',
509
+ 'ngdat' => 'application/vnd.nokia.n-gage.data',
510
+ 'nlu' => 'application/vnd.neurolanguage.nlu',
511
+ 'nml' => 'application/vnd.enliven',
512
+ 'nnd' => 'application/vnd.noblenet-directory',
513
+ 'nns' => 'application/vnd.noblenet-sealer',
514
+ 'nnw' => 'application/vnd.noblenet-web',
515
+ 'npx' => 'image/vnd.net-fpx',
516
+ 'nsf' => 'application/vnd.lotus-notes',
517
+ 'oa2' => 'application/vnd.fujitsu.oasys2',
518
+ 'oa3' => 'application/vnd.fujitsu.oasys3',
519
+ 'oas' => 'application/vnd.fujitsu.oasys',
520
+ 'obd' => 'application/x-msbinder',
521
+ 'oda' => 'application/oda',
522
+ 'odb' => 'application/vnd.oasis.opendocument.database',
523
+ 'odc' => 'application/vnd.oasis.opendocument.chart',
524
+ 'odf' => 'application/vnd.oasis.opendocument.formula',
525
+ 'odft' => 'application/vnd.oasis.opendocument.formula-template',
526
+ 'odg' => 'application/vnd.oasis.opendocument.graphics',
527
+ 'odi' => 'application/vnd.oasis.opendocument.image',
528
+ 'odm' => 'application/vnd.oasis.opendocument.text-master',
529
+ 'odp' => 'application/vnd.oasis.opendocument.presentation',
530
+ 'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
531
+ 'odt' => 'application/vnd.oasis.opendocument.text',
532
+ 'oga' => 'audio/ogg',
533
+ 'ogg' => 'audio/ogg',
534
+ 'ogv' => 'video/ogg',
535
+ 'ogx' => 'application/ogg',
536
+ 'onepkg' => 'application/onenote',
537
+ 'onetmp' => 'application/onenote',
538
+ 'onetoc' => 'application/onenote',
539
+ 'onetoc2' => 'application/onenote',
540
+ 'opf' => 'application/oebps-package+xml',
541
+ 'oprc' => 'application/vnd.palm',
542
+ 'org' => 'application/vnd.lotus-organizer',
543
+ 'osf' => 'application/vnd.yamaha.openscoreformat',
544
+ 'osfpvg' => 'application/vnd.yamaha.openscoreformat.osfpvg+xml',
545
+ 'otc' => 'application/vnd.oasis.opendocument.chart-template',
546
+ 'otf' => 'application/x-font-otf',
547
+ 'otg' => 'application/vnd.oasis.opendocument.graphics-template',
548
+ 'oth' => 'application/vnd.oasis.opendocument.text-web',
549
+ 'oti' => 'application/vnd.oasis.opendocument.image-template',
550
+ 'otp' => 'application/vnd.oasis.opendocument.presentation-template',
551
+ 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template',
552
+ 'ott' => 'application/vnd.oasis.opendocument.text-template',
553
+ 'oxt' => 'application/vnd.openofficeorg.extension',
554
+ 'p' => 'text/x-pascal',
555
+ 'p10' => 'application/pkcs10',
556
+ 'p12' => 'application/x-pkcs12',
557
+ 'p7b' => 'application/x-pkcs7-certificates',
558
+ 'p7c' => 'application/pkcs7-mime',
559
+ 'p7m' => 'application/pkcs7-mime',
560
+ 'p7r' => 'application/x-pkcs7-certreqresp',
561
+ 'p7s' => 'application/pkcs7-signature',
562
+ 'p8' => 'application/pkcs8',
563
+ 'pas' => 'text/x-pascal',
564
+ 'paw' => 'application/vnd.pawaafile',
565
+ 'pbd' => 'application/vnd.powerbuilder6',
566
+ 'pbm' => 'image/x-portable-bitmap',
567
+ 'pcf' => 'application/x-font-pcf',
568
+ 'pcl' => 'application/vnd.hp-pcl',
569
+ 'pclxl' => 'application/vnd.hp-pclxl',
570
+ 'pct' => 'image/x-pict',
571
+ 'pcurl' => 'application/vnd.curl.pcurl',
572
+ 'pcx' => 'image/x-pcx',
573
+ 'pdb' => 'application/vnd.palm',
574
+ 'pdf' => 'application/pdf',
575
+ 'pfa' => 'application/x-font-type1',
576
+ 'pfb' => 'application/x-font-type1',
577
+ 'pfm' => 'application/x-font-type1',
578
+ 'pfr' => 'application/font-tdpfr',
579
+ 'pfx' => 'application/x-pkcs12',
580
+ 'pgm' => 'image/x-portable-graymap',
581
+ 'pgn' => 'application/x-chess-pgn',
582
+ 'pgp' => 'application/pgp-encrypted',
583
+ 'php' => 'text/x-php',
584
+ 'phps' => 'application/x-httpd-phps',
585
+ 'pic' => 'image/x-pict',
586
+ 'pkg' => 'application/octet-stream',
587
+ 'pki' => 'application/pkixcmp',
588
+ 'pkipath' => 'application/pkix-pkipath',
589
+ 'plb' => 'application/vnd.3gpp.pic-bw-large',
590
+ 'plc' => 'application/vnd.mobius.plc',
591
+ 'plf' => 'application/vnd.pocketlearn',
592
+ 'pls' => 'application/pls+xml',
593
+ 'pml' => 'application/vnd.ctc-posml',
594
+ 'png' => 'image/png',
595
+ 'pnm' => 'image/x-portable-anymap',
596
+ 'portpkg' => 'application/vnd.macports.portpkg',
597
+ 'pot' => 'application/vnd.ms-powerpoint',
598
+ 'potm' => 'application/vnd.ms-powerpoint.template.macroenabled.12',
599
+ 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
600
+ 'ppam' => 'application/vnd.ms-powerpoint.addin.macroenabled.12',
601
+ 'ppd' => 'application/vnd.cups-ppd',
602
+ 'ppm' => 'image/x-portable-pixmap',
603
+ 'pps' => 'application/vnd.ms-powerpoint',
604
+ 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroenabled.12',
605
+ 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
606
+ 'ppt' => 'application/vnd.ms-powerpoint',
607
+ 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroenabled.12',
608
+ 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
609
+ 'pqa' => 'application/vnd.palm',
610
+ 'prc' => 'application/x-mobipocket-ebook',
611
+ 'pre' => 'application/vnd.lotus-freelance',
612
+ 'prf' => 'application/pics-rules',
613
+ 'ps' => 'application/postscript',
614
+ 'psb' => 'application/vnd.3gpp.pic-bw-small',
615
+ 'psd' => 'image/vnd.adobe.photoshop',
616
+ 'psf' => 'application/x-font-linux-psf',
617
+ 'pskcxml' => 'application/pskc+xml',
618
+ 'ptid' => 'application/vnd.pvi.ptid1',
619
+ 'pub' => 'application/x-mspublisher',
620
+ 'pvb' => 'application/vnd.3gpp.pic-bw-var',
621
+ 'pwn' => 'application/vnd.3m.post-it-notes',
622
+ 'pya' => 'audio/vnd.ms-playready.media.pya',
623
+ 'pyv' => 'video/vnd.ms-playready.media.pyv',
624
+ 'qam' => 'application/vnd.epson.quickanime',
625
+ 'qbo' => 'application/vnd.intu.qbo',
626
+ 'qfx' => 'application/vnd.intu.qfx',
627
+ 'qps' => 'application/vnd.publishare-delta-tree',
628
+ 'qt' => 'video/quicktime',
629
+ 'qwd' => 'application/vnd.quark.quarkxpress',
630
+ 'qwt' => 'application/vnd.quark.quarkxpress',
631
+ 'qxb' => 'application/vnd.quark.quarkxpress',
632
+ 'qxd' => 'application/vnd.quark.quarkxpress',
633
+ 'qxl' => 'application/vnd.quark.quarkxpress',
634
+ 'qxt' => 'application/vnd.quark.quarkxpress',
635
+ 'ra' => 'audio/x-pn-realaudio',
636
+ 'ram' => 'audio/x-pn-realaudio',
637
+ 'rar' => 'application/x-rar-compressed',
638
+ 'ras' => 'image/x-cmu-raster',
639
+ 'rb' => 'text/plain',
640
+ 'rcprofile' => 'application/vnd.ipunplugged.rcprofile',
641
+ 'rdf' => 'application/rdf+xml',
642
+ 'rdz' => 'application/vnd.data-vision.rdz',
643
+ 'rep' => 'application/vnd.businessobjects',
644
+ 'res' => 'application/x-dtbresource+xml',
645
+ 'resx' => 'text/xml',
646
+ 'rgb' => 'image/x-rgb',
647
+ 'rif' => 'application/reginfo+xml',
648
+ 'rip' => 'audio/vnd.rip',
649
+ 'rl' => 'application/resource-lists+xml',
650
+ 'rlc' => 'image/vnd.fujixerox.edmics-rlc',
651
+ 'rld' => 'application/resource-lists-diff+xml',
652
+ 'rm' => 'application/vnd.rn-realmedia',
653
+ 'rmi' => 'audio/midi',
654
+ 'rmp' => 'audio/x-pn-realaudio-plugin',
655
+ 'rms' => 'application/vnd.jcp.javame.midlet-rms',
656
+ 'rnc' => 'application/relax-ng-compact-syntax',
657
+ 'roff' => 'text/troff',
658
+ 'rp9' => 'application/vnd.cloanto.rp9',
659
+ 'rpss' => 'application/vnd.nokia.radio-presets',
660
+ 'rpst' => 'application/vnd.nokia.radio-preset',
661
+ 'rq' => 'application/sparql-query',
662
+ 'rs' => 'application/rls-services+xml',
663
+ 'rsd' => 'application/rsd+xml',
664
+ 'rss' => 'application/rss+xml',
665
+ 'rtf' => 'application/rtf',
666
+ 'rtx' => 'text/richtext',
667
+ 's' => 'text/x-asm',
668
+ 'saf' => 'application/vnd.yamaha.smaf-audio',
669
+ 'sbml' => 'application/sbml+xml',
670
+ 'sc' => 'application/vnd.ibm.secure-container',
671
+ 'scd' => 'application/x-msschedule',
672
+ 'scm' => 'application/vnd.lotus-screencam',
673
+ 'scq' => 'application/scvp-cv-request',
674
+ 'scs' => 'application/scvp-cv-response',
675
+ 'scurl' => 'text/vnd.curl.scurl',
676
+ 'sda' => 'application/vnd.stardivision.draw',
677
+ 'sdc' => 'application/vnd.stardivision.calc',
678
+ 'sdd' => 'application/vnd.stardivision.impress',
679
+ 'sdkd' => 'application/vnd.solent.sdkm+xml',
680
+ 'sdkm' => 'application/vnd.solent.sdkm+xml',
681
+ 'sdp' => 'application/sdp',
682
+ 'sdw' => 'application/vnd.stardivision.writer',
683
+ 'see' => 'application/vnd.seemail',
684
+ 'seed' => 'application/vnd.fdsn.seed',
685
+ 'sema' => 'application/vnd.sema',
686
+ 'semd' => 'application/vnd.semd',
687
+ 'semf' => 'application/vnd.semf',
688
+ 'ser' => 'application/java-serialized-object',
689
+ 'setpay' => 'application/set-payment-initiation',
690
+ 'setreg' => 'application/set-registration-initiation',
691
+ 'sfd-hdstx' => 'application/vnd.hydrostatix.sof-data',
692
+ 'sfs' => 'application/vnd.spotfire.sfs',
693
+ 'sgl' => 'application/vnd.stardivision.writer-global',
694
+ 'sgm' => 'text/sgml',
695
+ 'sgml' => 'text/sgml',
696
+ 'sh' => 'application/x-sh',
697
+ 'shar' => 'application/x-shar',
698
+ 'shf' => 'application/shf+xml',
699
+ 'sig' => 'application/pgp-signature',
700
+ 'silo' => 'model/mesh',
701
+ 'sis' => 'application/vnd.symbian.install',
702
+ 'sisx' => 'application/vnd.symbian.install',
703
+ 'sit' => 'application/x-stuffit',
704
+ 'sitx' => 'application/x-stuffitx',
705
+ 'skd' => 'application/vnd.koan',
706
+ 'skm' => 'application/vnd.koan',
707
+ 'skp' => 'application/vnd.koan',
708
+ 'skt' => 'application/vnd.koan',
709
+ 'sldm' => 'application/vnd.ms-powerpoint.slide.macroenabled.12',
710
+ 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
711
+ 'slt' => 'application/vnd.epson.salt',
712
+ 'sm' => 'application/vnd.stepmania.stepchart',
713
+ 'smf' => 'application/vnd.stardivision.math',
714
+ 'smi' => 'application/smil+xml',
715
+ 'smil' => 'application/smil+xml',
716
+ 'snd' => 'audio/basic',
717
+ 'snf' => 'application/x-font-snf',
718
+ 'so' => 'application/octet-stream',
719
+ 'spc' => 'application/x-pkcs7-certificates',
720
+ 'spf' => 'application/vnd.yamaha.smaf-phrase',
721
+ 'spl' => 'application/x-futuresplash',
722
+ 'spot' => 'text/vnd.in3d.spot',
723
+ 'spp' => 'application/scvp-vp-response',
724
+ 'spq' => 'application/scvp-vp-request',
725
+ 'spx' => 'audio/ogg',
726
+ 'src' => 'application/x-wais-source',
727
+ 'sru' => 'application/sru+xml',
728
+ 'srx' => 'application/sparql-results+xml',
729
+ 'sse' => 'application/vnd.kodak-descriptor',
730
+ 'ssf' => 'application/vnd.epson.ssf',
731
+ 'ssml' => 'application/ssml+xml',
732
+ 'st' => 'application/vnd.sailingtracker.track',
733
+ 'stc' => 'application/vnd.sun.xml.calc.template',
734
+ 'std' => 'application/vnd.sun.xml.draw.template',
735
+ 'stf' => 'application/vnd.wt.stf',
736
+ 'sti' => 'application/vnd.sun.xml.impress.template',
737
+ 'stk' => 'application/hyperstudio',
738
+ 'stl' => 'application/vnd.ms-pki.stl',
739
+ 'str' => 'application/vnd.pg.format',
740
+ 'stw' => 'application/vnd.sun.xml.writer.template',
741
+ 'sub' => 'image/vnd.dvb.subtitle',
742
+ 'sus' => 'application/vnd.sus-calendar',
743
+ 'susp' => 'application/vnd.sus-calendar',
744
+ 'sv4cpio' => 'application/x-sv4cpio',
745
+ 'sv4crc' => 'application/x-sv4crc',
746
+ 'svc' => 'application/vnd.dvb.service',
747
+ 'svd' => 'application/vnd.svd',
748
+ 'svg' => 'image/svg+xml',
749
+ 'svgz' => 'image/svg+xml',
750
+ 'swa' => 'application/x-director',
751
+ 'swf' => 'application/x-shockwave-flash',
752
+ 'swi' => 'application/vnd.aristanetworks.swi',
753
+ 'sxc' => 'application/vnd.sun.xml.calc',
754
+ 'sxd' => 'application/vnd.sun.xml.draw',
755
+ 'sxg' => 'application/vnd.sun.xml.writer.global',
756
+ 'sxi' => 'application/vnd.sun.xml.impress',
757
+ 'sxm' => 'application/vnd.sun.xml.math',
758
+ 'sxw' => 'application/vnd.sun.xml.writer',
759
+ 't' => 'text/troff',
760
+ 'tao' => 'application/vnd.tao.intent-module-archive',
761
+ 'tar' => 'application/x-tar',
762
+ 'tcap' => 'application/vnd.3gpp2.tcap',
763
+ 'tcl' => 'application/x-tcl',
764
+ 'teacher' => 'application/vnd.smart.teacher',
765
+ 'tei' => 'application/tei+xml',
766
+ 'teicorpus' => 'application/tei+xml',
767
+ 'tex' => 'application/x-tex',
768
+ 'texi' => 'application/x-texinfo',
769
+ 'texinfo' => 'application/x-texinfo',
770
+ 'text' => 'text/plain',
771
+ 'tfi' => 'application/thraud+xml',
772
+ 'tfm' => 'application/x-tex-tfm',
773
+ 'thmx' => 'application/vnd.ms-officetheme',
774
+ 'tif' => 'image/tiff',
775
+ 'tiff' => 'image/tiff',
776
+ 'tmo' => 'application/vnd.tmobile-livetv',
777
+ 'torrent' => 'application/x-bittorrent',
778
+ 'tpl' => 'application/vnd.groove-tool-template',
779
+ 'tpt' => 'application/vnd.trid.tpt',
780
+ 'tr' => 'text/troff',
781
+ 'tra' => 'application/vnd.trueapp',
782
+ 'trm' => 'application/x-msterminal',
783
+ 'tsd' => 'application/timestamped-data',
784
+ 'tsv' => 'text/tab-separated-values',
785
+ 'ttc' => 'application/x-font-ttf',
786
+ 'ttf' => 'application/x-font-ttf',
787
+ 'ttl' => 'text/turtle',
788
+ 'twd' => 'application/vnd.simtech-mindmapper',
789
+ 'twds' => 'application/vnd.simtech-mindmapper',
790
+ 'txd' => 'application/vnd.genomatix.tuxedo',
791
+ 'txf' => 'application/vnd.mobius.txf',
792
+ 'txt' => 'text/plain',
793
+ 'u32' => 'application/x-authorware-bin',
794
+ 'udeb' => 'application/x-debian-package',
795
+ 'ufd' => 'application/vnd.ufdl',
796
+ 'ufdl' => 'application/vnd.ufdl',
797
+ 'umj' => 'application/vnd.umajin',
798
+ 'unityweb' => 'application/vnd.unity',
799
+ 'uoml' => 'application/vnd.uoml+xml',
800
+ 'uri' => 'text/uri-list',
801
+ 'uris' => 'text/uri-list',
802
+ 'urls' => 'text/uri-list',
803
+ 'ustar' => 'application/x-ustar',
804
+ 'utz' => 'application/vnd.uiq.theme',
805
+ 'uu' => 'text/x-uuencode',
806
+ 'uva' => 'audio/vnd.dece.audio',
807
+ 'uvd' => 'application/vnd.dece.data',
808
+ 'uvf' => 'application/vnd.dece.data',
809
+ 'uvg' => 'image/vnd.dece.graphic',
810
+ 'uvh' => 'video/vnd.dece.hd',
811
+ 'uvi' => 'image/vnd.dece.graphic',
812
+ 'uvm' => 'video/vnd.dece.mobile',
813
+ 'uvp' => 'video/vnd.dece.pd',
814
+ 'uvs' => 'video/vnd.dece.sd',
815
+ 'uvt' => 'application/vnd.dece.ttml+xml',
816
+ 'uvu' => 'video/vnd.uvvu.mp4',
817
+ 'uvv' => 'video/vnd.dece.video',
818
+ 'uvva' => 'audio/vnd.dece.audio',
819
+ 'uvvd' => 'application/vnd.dece.data',
820
+ 'uvvf' => 'application/vnd.dece.data',
821
+ 'uvvg' => 'image/vnd.dece.graphic',
822
+ 'uvvh' => 'video/vnd.dece.hd',
823
+ 'uvvi' => 'image/vnd.dece.graphic',
824
+ 'uvvm' => 'video/vnd.dece.mobile',
825
+ 'uvvp' => 'video/vnd.dece.pd',
826
+ 'uvvs' => 'video/vnd.dece.sd',
827
+ 'uvvt' => 'application/vnd.dece.ttml+xml',
828
+ 'uvvu' => 'video/vnd.uvvu.mp4',
829
+ 'uvvv' => 'video/vnd.dece.video',
830
+ 'uvvx' => 'application/vnd.dece.unspecified',
831
+ 'uvx' => 'application/vnd.dece.unspecified',
832
+ 'vcd' => 'application/x-cdlink',
833
+ 'vcf' => 'text/x-vcard',
834
+ 'vcg' => 'application/vnd.groove-vcard',
835
+ 'vcs' => 'text/x-vcalendar',
836
+ 'vcx' => 'application/vnd.vcx',
837
+ 'vis' => 'application/vnd.visionary',
838
+ 'viv' => 'video/vnd.vivo',
839
+ 'vor' => 'application/vnd.stardivision.writer',
840
+ 'vox' => 'application/x-authorware-bin',
841
+ 'vrml' => 'model/vrml',
842
+ 'vsd' => 'application/vnd.visio',
843
+ 'vsf' => 'application/vnd.vsf',
844
+ 'vss' => 'application/vnd.visio',
845
+ 'vst' => 'application/vnd.visio',
846
+ 'vsw' => 'application/vnd.visio',
847
+ 'vtu' => 'model/vnd.vtu',
848
+ 'vxml' => 'application/voicexml+xml',
849
+ 'w3d' => 'application/x-director',
850
+ 'wad' => 'application/x-doom',
851
+ 'wav' => 'audio/x-wav',
852
+ 'wax' => 'audio/x-ms-wax',
853
+ 'wbmp' => 'image/vnd.wap.wbmp',
854
+ 'wbs' => 'application/vnd.criticaltools.wbs+xml',
855
+ 'wbxml' => 'application/vnd.wap.wbxml',
856
+ 'wcm' => 'application/vnd.ms-works',
857
+ 'wdb' => 'application/vnd.ms-works',
858
+ 'weba' => 'audio/webm',
859
+ 'webm' => 'video/webm',
860
+ 'webp' => 'image/webp',
861
+ 'wg' => 'application/vnd.pmi.widget',
862
+ 'wgt' => 'application/widget',
863
+ 'wks' => 'application/vnd.ms-works',
864
+ 'wm' => 'video/x-ms-wm',
865
+ 'wma' => 'audio/x-ms-wma',
866
+ 'wmd' => 'application/x-ms-wmd',
867
+ 'wmf' => 'application/x-msmetafile',
868
+ 'wml' => 'text/vnd.wap.wml',
869
+ 'wmlc' => 'application/vnd.wap.wmlc',
870
+ 'wmls' => 'text/vnd.wap.wmlscript',
871
+ 'wmlsc' => 'application/vnd.wap.wmlscriptc',
872
+ 'wmv' => 'video/x-ms-wmv',
873
+ 'wmx' => 'video/x-ms-wmx',
874
+ 'wmz' => 'application/x-ms-wmz',
875
+ 'woff' => 'application/x-font-woff',
876
+ 'wpd' => 'application/vnd.wordperfect',
877
+ 'wpl' => 'application/vnd.ms-wpl',
878
+ 'wps' => 'application/vnd.ms-works',
879
+ 'wqd' => 'application/vnd.wqd',
880
+ 'wri' => 'application/x-mswrite',
881
+ 'wrl' => 'model/vrml',
882
+ 'wsdl' => 'application/wsdl+xml',
883
+ 'wspolicy' => 'application/wspolicy+xml',
884
+ 'wtb' => 'application/vnd.webturbo',
885
+ 'wvx' => 'video/x-ms-wvx',
886
+ 'x32' => 'application/x-authorware-bin',
887
+ 'x3d' => 'application/vnd.hzn-3d-crossword',
888
+ 'xap' => 'application/x-silverlight-app',
889
+ 'xar' => 'application/vnd.xara',
890
+ 'xbap' => 'application/x-ms-xbap',
891
+ 'xbd' => 'application/vnd.fujixerox.docuworks.binder',
892
+ 'xbm' => 'image/x-xbitmap',
893
+ 'xdf' => 'application/xcap-diff+xml',
894
+ 'xdm' => 'application/vnd.syncml.dm+xml',
895
+ 'xdp' => 'application/vnd.adobe.xdp+xml',
896
+ 'xdssc' => 'application/dssc+xml',
897
+ 'xdw' => 'application/vnd.fujixerox.docuworks',
898
+ 'xenc' => 'application/xenc+xml',
899
+ 'xer' => 'application/patch-ops-error+xml',
900
+ 'xfdf' => 'application/vnd.adobe.xfdf',
901
+ 'xfdl' => 'application/vnd.xfdl',
902
+ 'xht' => 'application/xhtml+xml',
903
+ 'xhtml' => 'application/xhtml+xml',
904
+ 'xhvml' => 'application/xv+xml',
905
+ 'xif' => 'image/vnd.xiff',
906
+ 'xla' => 'application/vnd.ms-excel',
907
+ 'xlam' => 'application/vnd.ms-excel.addin.macroenabled.12',
908
+ 'xlc' => 'application/vnd.ms-excel',
909
+ 'xlm' => 'application/vnd.ms-excel',
910
+ 'xls' => 'application/vnd.ms-excel',
911
+ 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroenabled.12',
912
+ 'xlsm' => 'application/vnd.ms-excel.sheet.macroenabled.12',
913
+ 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
914
+ 'xlt' => 'application/vnd.ms-excel',
915
+ 'xltm' => 'application/vnd.ms-excel.template.macroenabled.12',
916
+ 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
917
+ 'xlw' => 'application/vnd.ms-excel',
918
+ 'xml' => 'application/xml',
919
+ 'xo' => 'application/vnd.olpc-sugar',
920
+ 'xop' => 'application/xop+xml',
921
+ 'xpi' => 'application/x-xpinstall',
922
+ 'xpm' => 'image/x-xpixmap',
923
+ 'xpr' => 'application/vnd.is-xpr',
924
+ 'xps' => 'application/vnd.ms-xpsdocument',
925
+ 'xpw' => 'application/vnd.intercon.formnet',
926
+ 'xpx' => 'application/vnd.intercon.formnet',
927
+ 'xsl' => 'application/xml',
928
+ 'xslt' => 'application/xslt+xml',
929
+ 'xsm' => 'application/vnd.syncml+xml',
930
+ 'xspf' => 'application/xspf+xml',
931
+ 'xul' => 'application/vnd.mozilla.xul+xml',
932
+ 'xvm' => 'application/xv+xml',
933
+ 'xvml' => 'application/xv+xml',
934
+ 'xwd' => 'image/x-xwindowdump',
935
+ 'xyz' => 'chemical/x-xyz',
936
+ 'yaml' => 'text/yaml',
937
+ 'yang' => 'application/yang',
938
+ 'yin' => 'application/yin+xml',
939
+ 'yml' => 'text/yaml',
940
+ 'zaz' => 'application/vnd.zzazz.deck+xml',
941
+ 'zip' => 'application/zip',
942
+ 'zir' => 'application/vnd.zul',
943
+ 'zirz' => 'application/vnd.zul',
944
+ 'zmm' => 'application/vnd.handheld-entertainment+xml'
945
+ ];
946
+
947
+ /**
948
+ * Get a singleton instance of the class
949
+ *
950
+ * @return self
951
+ * @codeCoverageIgnore
952
+ */
953
+ public static function getInstance()
954
+ {
955
+ if (!self::$instance) {
956
+ self::$instance = new self();
957
+ }
958
+
959
+ return self::$instance;
960
+ }
961
+
962
+ /**
963
+ * Get a mimetype value from a file extension
964
+ *
965
+ * @param string $extension File extension
966
+ *
967
+ * @return string|null
968
+ */
969
+ public function fromExtension($extension)
970
+ {
971
+ $extension = strtolower($extension);
972
+
973
+ return isset($this->mimetypes[$extension]) ? $this->mimetypes[$extension] : null;
974
+ }
975
+
976
+ /**
977
+ * Get a mimetype from a filename
978
+ *
979
+ * @param string $filename Filename to generate a mimetype from
980
+ *
981
+ * @return string|null
982
+ */
983
+ public function fromFilename($filename)
984
+ {
985
+ return $this->fromExtension(pathinfo($filename, PATHINFO_EXTENSION));
986
+ }
987
+ }
vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/Collection.php ADDED
@@ -0,0 +1,242 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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
+ /**
27
+ * Class Collection
28
+ *
29
+ * Modified version of Collection in "illuminate/support" by Taylor Otwell
30
+ *
31
+ * @package Facebook
32
+ */
33
+
34
+ use ArrayAccess;
35
+ use ArrayIterator;
36
+ use Countable;
37
+ use IteratorAggregate;
38
+
39
+ class Collection implements ArrayAccess, Countable, IteratorAggregate
40
+ {
41
+ /**
42
+ * The items contained in the collection.
43
+ *
44
+ * @var array
45
+ */
46
+ protected $items = [];
47
+
48
+ /**
49
+ * Create a new collection.
50
+ *
51
+ * @param array $items
52
+ */
53
+ public function __construct(array $items = [])
54
+ {
55
+ $this->items = $items;
56
+ }
57
+
58
+ /**
59
+ * Gets the value of a field from the Graph node.
60
+ *
61
+ * @param string $name The field to retrieve.
62
+ * @param mixed $default The default to return if the field doesn't exist.
63
+ *
64
+ * @return mixed
65
+ */
66
+ public function getField($name, $default = null)
67
+ {
68
+ if (isset($this->items[$name])) {
69
+ return $this->items[$name];
70
+ }
71
+
72
+ return $default;
73
+ }
74
+
75
+ /**
76
+ * Gets the value of the named property for this graph object.
77
+ *
78
+ * @param string $name The property to retrieve.
79
+ * @param mixed $default The default to return if the property doesn't exist.
80
+ *
81
+ * @return mixed
82
+ *
83
+ * @deprecated 5.0.0 getProperty() has been renamed to getField()
84
+ * @todo v6: Remove this method
85
+ */
86
+ public function getProperty($name, $default = null)
87
+ {
88
+ return $this->getField($name, $default);
89
+ }
90
+
91
+ /**
92
+ * Returns a list of all fields set on the object.
93
+ *
94
+ * @return array
95
+ */
96
+ public function getFieldNames()
97
+ {
98
+ return array_keys($this->items);
99
+ }
100
+
101
+ /**
102
+ * Returns a list of all properties set on the object.
103
+ *
104
+ * @return array
105
+ *
106
+ * @deprecated 5.0.0 getPropertyNames() has been renamed to getFieldNames()
107
+ * @todo v6: Remove this method
108
+ */
109
+ public function getPropertyNames()
110
+ {
111
+ return $this->getFieldNames();
112
+ }
113
+
114
+ /**
115
+ * Get all of the items in the collection.
116
+ *
117
+ * @return array
118
+ */
119
+ public function all()
120
+ {
121
+ return $this->items;
122
+ }
123
+
124
+ /**
125
+ * Get the collection of items as a plain array.
126
+ *
127
+ * @return array
128
+ */
129
+ public function asArray()
130
+ {
131
+ return array_map(function ($value) {
132
+ return $value instanceof Collection ? $value->asArray() : $value;
133
+ }, $this->items);
134
+ }
135
+
136
+ /**
137
+ * Run a map over each of the items.
138
+ *
139
+ * @param \Closure $callback
140
+ *
141
+ * @return static
142
+ */
143
+ public function map(\Closure $callback)
144
+ {
145
+ return new static(array_map($callback, $this->items, array_keys($this->items)));
146
+ }
147
+
148
+ /**
149
+ * Get the collection of items as JSON.
150
+ *
151
+ * @param int $options
152
+ *
153
+ * @return string
154
+ */
155
+ public function asJson($options = 0)
156
+ {
157
+ return json_encode($this->asArray(), $options);
158
+ }
159
+
160
+ /**
161
+ * Count the number of items in the collection.
162
+ *
163
+ * @return int
164
+ */
165
+ public function count()
166
+ {
167
+ return count($this->items);
168
+ }
169
+
170
+ /**
171
+ * Get an iterator for the items.
172
+ *
173
+ * @return ArrayIterator
174
+ */
175
+ public function getIterator()
176
+ {
177
+ return new ArrayIterator($this->items);
178
+ }
179
+
180
+ /**
181
+ * Determine if an item exists at an offset.
182
+ *
183
+ * @param mixed $key
184
+ *
185
+ * @return bool
186
+ */
187
+ public function offsetExists($key)
188
+ {
189
+ return array_key_exists($key, $this->items);
190
+ }
191
+
192
+ /**
193
+ * Get an item at a given offset.
194
+ *
195
+ * @param mixed $key
196
+ *
197
+ * @return mixed
198
+ */
199
+ public function offsetGet($key)
200
+ {
201
+ return $this->items[$key];
202
+ }
203
+
204
+ /**
205
+ * Set the item at a given offset.
206
+ *
207
+ * @param mixed $key
208
+ * @param mixed $value
209
+ *
210
+ * @return void
211
+ */
212
+ public function offsetSet($key, $value)
213
+ {
214
+ if (is_null($key)) {
215
+ $this->items[] = $value;
216
+ } else {
217
+ $this->items[$key] = $value;
218
+ }
219
+ }
220
+
221
+ /**
222
+ * Unset the item at a given offset.
223
+ *
224
+ * @param string $key
225
+ *
226
+ * @return void
227
+ */
228
+ public function offsetUnset($key)
229
+ {
230
+ unset($this->items[$key]);
231
+ }
232
+
233
+ /**
234
+ * Convert the collection to its string representation.
235
+ *
236
+ * @return string
237
+ */
238
+ public function __toString()
239
+ {
240
+ return $this->asJson();
241
+ }
242
+ }
vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphAchievement.php ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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
+ /**
27
+ * Class GraphAchievement
28
+ *
29
+ * @package Facebook
30
+ */
31
+
32
+ class GraphAchievement extends GraphNode
33
+ {
34
+ /**
35
+ * @var array Maps object key names to Graph object types.
36
+ */
37
+ protected static $graphObjectMap = [
38
+ 'from' => '\Facebook\GraphNodes\GraphUser',
39
+ 'application' => '\Facebook\GraphNodes\GraphApplication',
40
+ ];
41
+
42
+ /**
43
+ * Returns the ID for the achievement.
44
+ *
45
+ * @return string|null
46
+ */
47
+ public function getId()
48
+ {
49
+ return $this->getField('id');
50
+ }
51
+
52
+ /**
53
+ * Returns the user who achieved this.
54
+ *
55
+ * @return GraphUser|null
56
+ */
57
+ public function getFrom()
58
+ {
59
+ return $this->getField('from');
60
+ }
61
+
62
+ /**
63
+ * Returns the time at which this was achieved.
64
+ *
65
+ * @return \DateTime|null
66
+ */
67
+ public function getPublishTime()
68
+ {
69
+ return $this->getField('publish_time');
70
+ }
71
+
72
+ /**
73
+ * Returns the app in which the user achieved this.
74
+ *
75
+ * @return GraphApplication|null
76
+ */
77
+ public function getApplication()
78
+ {
79
+ return $this->getField('application');
80
+ }
81
+
82
+ /**
83
+ * Returns information about the achievement type this instance is connected with.
84
+ *
85
+ * @return array|null
86
+ */
87
+ public function getData()
88
+ {
89
+ return $this->getField('data');
90
+ }
91
+
92
+ /**
93
+ * Returns the type of achievement.
94
+ *
95
+ * @see https://developers.facebook.com/docs/graph-api/reference/achievement
96
+ *
97
+ * @return string
98
+ */
99
+ public function getType()
100
+ {
101
+ return 'game.achievement';
102
+ }
103
+
104
+ /**
105
+ * Indicates whether gaining the achievement published a feed story for the user.
106
+ *
107
+ * @return boolean|null
108
+ */
109
+ public function isNoFeedStory()
110
+ {
111
+ return $this->getField('no_feed_story');
112
+ }
113
+ }
vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphAlbum.php ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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
+ /**
27
+ * Class GraphAlbum
28
+ *
29
+ * @package Facebook
30
+ */
31
+
32
+ class GraphAlbum extends GraphNode
33
+ {
34
+ /**
35
+ * @var array Maps object key names to Graph object types.
36
+ */
37
+ protected static $graphObjectMap = [
38
+ 'from' => '\Facebook\GraphNodes\GraphUser',
39
+ 'place' => '\Facebook\GraphNodes\GraphPage',
40
+ ];
41
+
42
+ /**
43
+ * Returns the ID for the album.
44
+ *
45
+ * @return string|null
46
+ */
47
+ public function getId()
48
+ {
49
+ return $this->getField('id');
50
+ }
51
+
52
+ /**
53
+ * Returns whether the viewer can upload photos to this album.
54
+ *
55
+ * @return boolean|null
56
+ */
57
+ public function getCanUpload()
58
+ {
59
+ return $this->getField('can_upload');
60
+ }
61
+
62
+ /**
63
+ * Returns the number of photos in this album.
64
+ *
65
+ * @return int|null
66
+ */
67
+ public function getCount()
68
+ {
69
+ return $this->getField('count');
70
+ }
71
+
72
+ /**
73
+ * Returns the ID of the album's cover photo.
74
+ *
75
+ * @return string|null
76
+ */
77
+ public function getCoverPhoto()
78
+ {
79
+ return $this->getField('cover_photo');
80
+ }
81
+
82
+ /**
83
+ * Returns the time the album was initially created.
84
+ *
85
+ * @return \DateTime|null
86
+ */
87
+ public function getCreatedTime()
88
+ {
89
+ return $this->getField('created_time');
90
+ }
91
+
92
+ /**
93
+ * Returns the time the album was updated.
94
+ *
95
+ * @return \DateTime|null
96
+ */
97
+ public function getUpdatedTime()
98
+ {
99
+ return $this->getField('updated_time');
100
+ }
101
+
102
+ /**
103
+ * Returns the description of the album.
104
+ *
105
+ * @return string|null
106
+ */
107
+ public function getDescription()
108
+ {
109
+ return $this->getField('description');
110
+ }
111
+
112
+ /**
113
+ * Returns profile that created the album.
114
+ *
115
+ * @return GraphUser|null
116
+ */
117
+ public function getFrom()
118
+ {
119
+ return $this->getField('from');
120
+ }
121
+
122
+ /**
123
+ * Returns profile that created the album.
124
+ *
125
+ * @return GraphPage|null
126
+ */
127
+ public function getPlace()
128
+ {
129
+ return $this->getField('place');
130
+ }
131
+
132
+ /**
133
+ * Returns a link to this album on Facebook.
134
+ *
135
+ * @return string|null
136
+ */
137
+ public function getLink()
138
+ {
139
+ return $this->getField('link');
140
+ }
141
+
142
+ /**
143
+ * Returns the textual location of the album.
144
+ *
145
+ * @return string|null
146
+ */
147
+ public function getLocation()
148
+ {
149
+ return $this->getField('location');
150
+ }
151
+
152
+ /**
153
+ * Returns the title of the album.
154
+ *
155
+ * @return string|null
156
+ */
157
+ public function getName()
158
+ {
159
+ return $this->getField('name');
160
+ }
161
+
162
+ /**
163
+ * Returns the privacy settings for the album.
164
+ *
165
+ * @return string|null
166
+ */
167
+ public function getPrivacy()
168
+ {
169
+ return $this->getField('privacy');
170
+ }
171
+
172
+ /**
173
+ * Returns the type of the album.
174
+ *
175
+ * enum{ profile, mobile, wall, normal, album }
176
+ *
177
+ * @return string|null
178
+ */
179
+ public function getType()
180
+ {
181
+ return $this->getField('type');
182
+ }
183
+ }
vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphApplication.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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
+ /**
27
+ * Class GraphApplication
28
+ *
29
+ * @package Facebook
30
+ */
31
+
32
+ class GraphApplication extends GraphNode
33
+ {
34
+ /**
35
+ * Returns the ID for the application.
36
+ *
37
+ * @return string|null
38
+ */
39
+ public function getId()
40
+ {
41
+ return $this->getField('id');
42
+ }
43
+ }
vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphCoverPhoto.php ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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
+ /**
27
+ * Class GraphCoverPhoto
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class GraphCoverPhoto extends GraphNode
32
+ {
33
+ /**
34
+ * Returns the id of cover if it exists
35
+ *
36
+ * @return int|null
37
+ */
38
+ public function getId()
39
+ {
40
+ return $this->getField('id');
41
+ }
42
+
43
+ /**
44
+ * Returns the source of cover if it exists
45
+ *
46
+ * @return string|null
47
+ */
48
+ public function getSource()
49
+ {
50
+ return $this->getField('source');
51
+ }
52
+
53
+ /**
54
+ * Returns the offset_x of cover if it exists
55
+ *
56
+ * @return int|null
57
+ */
58
+ public function getOffsetX()
59
+ {
60
+ return $this->getField('offset_x');
61
+ }
62
+
63
+ /**
64
+ * Returns the offset_y of cover if it exists
65
+ *
66
+ * @return int|null
67
+ */
68
+ public function getOffsetY()
69
+ {
70
+ return $this->getField('offset_y');
71
+ }
72
+ }
vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphEdge.php ADDED
@@ -0,0 +1,238 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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 Facebook\FacebookRequest;
27
+ use Facebook\Url\FacebookUrlManipulator;
28
+ use Facebook\Exceptions\FacebookSDKException;
29
+
30
+ /**
31
+ * Class GraphEdge
32
+ *
33
+ * @package Facebook
34
+ */
35
+ class GraphEdge extends Collection
36
+ {
37
+ /**
38
+ * @var FacebookRequest The original request that generated this data.
39
+ */
40
+ protected $request;
41
+
42
+ /**
43
+ * @var array An array of Graph meta data like pagination, etc.
44
+ */
45
+ protected $metaData = [];
46
+
47
+ /**
48
+ * @var string|null The parent Graph edge endpoint that generated the list.
49
+ */
50
+ protected $parentEdgeEndpoint;
51
+
52
+ /**
53
+ * @var string|null The subclass of the child GraphNode's.
54
+ */
55
+ protected $subclassName;
56
+
57
+ /**
58
+ * Init this collection of GraphNode's.
59
+ *
60
+ * @param FacebookRequest $request The original request that generated this data.
61
+ * @param array $data An array of GraphNode's.
62
+ * @param array $metaData An array of Graph meta data like pagination, etc.
63
+ * @param string|null $parentEdgeEndpoint The parent Graph edge endpoint that generated the list.
64
+ * @param string|null $subclassName The subclass of the child GraphNode's.
65
+ */
66
+ public function __construct(FacebookRequest $request, array $data = [], array $metaData = [], $parentEdgeEndpoint = null, $subclassName = null)
67
+ {
68
+ $this->request = $request;
69
+ $this->metaData = $metaData;
70
+ $this->parentEdgeEndpoint = $parentEdgeEndpoint;
71
+ $this->subclassName = $subclassName;
72
+
73
+ parent::__construct($data);
74
+ }
75
+
76
+ /**
77
+ * Gets the parent Graph edge endpoint that generated the list.
78
+ *
79
+ * @return string|null
80
+ */
81
+ public function getParentGraphEdge()
82
+ {
83
+ return $this->parentEdgeEndpoint;
84
+ }
85
+
86
+ /**
87
+ * Gets the subclass name that the child GraphNode's are cast as.
88
+ *
89
+ * @return string|null
90
+ */
91
+ public function getSubClassName()
92
+ {
93
+ return $this->subclassName;
94
+ }
95
+
96
+ /**
97
+ * Returns the raw meta data associated with this GraphEdge.
98
+ *
99
+ * @return array
100
+ */
101
+ public function getMetaData()
102
+ {
103
+ return $this->metaData;
104
+ }
105
+
106
+ /**
107
+ * Returns the next cursor if it exists.
108
+ *
109
+ * @return string|null
110
+ */
111
+ public function getNextCursor()
112
+ {
113
+ return $this->getCursor('after');
114
+ }
115
+
116
+ /**
117
+ * Returns the previous cursor if it exists.
118
+ *
119
+ * @return string|null
120
+ */
121
+ public function getPreviousCursor()
122
+ {
123
+ return $this->getCursor('before');
124
+ }
125
+
126
+ /**
127
+ * Returns the cursor for a specific direction if it exists.
128
+ *
129
+ * @param string $direction The direction of the page: after|before
130
+ *
131
+ * @return string|null
132
+ */
133
+ public function getCursor($direction)
134
+ {
135
+ if (isset($this->metaData['paging']['cursors'][$direction])) {
136
+ return $this->metaData['paging']['cursors'][$direction];
137
+ }
138
+
139
+ return null;
140
+ }
141
+
142
+ /**
143
+ * Generates a pagination URL based on a cursor.
144
+ *
145
+ * @param string $direction The direction of the page: next|previous
146
+ *
147
+ * @return string|null
148
+ *
149
+ * @throws FacebookSDKException
150
+ */
151
+ public function getPaginationUrl($direction)
152
+ {
153
+ $this->validateForPagination();
154
+
155
+ // Do we have a paging URL?
156
+ if (!isset($this->metaData['paging'][$direction])) {
157
+ return null;
158
+ }
159
+
160
+ $pageUrl = $this->metaData['paging'][$direction];
161
+
162
+ return FacebookUrlManipulator::baseGraphUrlEndpoint($pageUrl);
163
+ }
164
+
165
+ /**
166
+ * Validates whether or not we can paginate on this request.
167
+ *
168
+ * @throws FacebookSDKException
169
+ */
170
+ public function validateForPagination()
171
+ {
172
+ if ($this->request->getMethod() !== 'GET') {
173
+ throw new FacebookSDKException('You can only paginate on a GET request.', 720);
174
+ }
175
+ }
176
+
177
+ /**
178
+ * Gets the request object needed to make a next|previous page request.
179
+ *
180
+ * @param string $direction The direction of the page: next|previous
181
+ *
182
+ * @return FacebookRequest|null
183
+ *
184
+ * @throws FacebookSDKException
185
+ */
186
+ public function getPaginationRequest($direction)
187
+ {
188
+ $pageUrl = $this->getPaginationUrl($direction);
189
+ if (!$pageUrl) {
190
+ return null;
191
+ }
192
+
193
+ $newRequest = clone $this->request;
194
+ $newRequest->setEndpoint($pageUrl);
195
+
196
+ return $newRequest;
197
+ }
198
+
199
+ /**
200
+ * Gets the request object needed to make a "next" page request.
201
+ *
202
+ * @return FacebookRequest|null
203
+ *
204
+ * @throws FacebookSDKException
205
+ */
206
+ public function getNextPageRequest()
207
+ {
208
+ return $this->getPaginationRequest('next');
209
+ }
210
+
211
+ /**
212
+ * Gets the request object needed to make a "previous" page request.
213
+ *
214
+ * @return FacebookRequest|null
215
+ *
216
+ * @throws FacebookSDKException
217
+ */
218
+ public function getPreviousPageRequest()
219
+ {
220
+ return $this->getPaginationRequest('previous');
221
+ }
222
+
223
+ /**
224
+ * The total number of results according to Graph if it exists.
225
+ *
226
+ * This will be returned if the summary=true modifier is present in the request.
227
+ *
228
+ * @return int|null
229
+ */
230
+ public function getTotalCount()
231
+ {
232
+ if (isset($this->metaData['summary']['total_count'])) {
233
+ return $this->metaData['summary']['total_count'];
234
+ }
235
+
236
+ return null;
237
+ }
238
+ }
vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphEvent.php ADDED
@@ -0,0 +1,242 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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
+ /**
27
+ * Class GraphEvent
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class GraphEvent extends GraphNode
32
+ {
33
+ /**
34
+ * @var array Maps object key names to GraphNode types.
35
+ */
36
+ protected static $graphObjectMap = [
37
+ 'cover' => '\Facebook\GraphNodes\GraphCoverPhoto',
38
+ 'place' => '\Facebook\GraphNodes\GraphPage',
39
+ 'picture' => '\Facebook\GraphNodes\GraphPicture',
40
+ 'parent_group' => '\Facebook\GraphNodes\GraphGroup',
41
+ ];
42
+
43
+ /**
44
+ * Returns the `id` (The event ID) as string if present.
45
+ *
46
+ * @return string|null
47
+ */
48
+ public function getId()
49
+ {
50
+ return $this->getField('id');
51
+ }
52
+
53
+ /**
54
+ * Returns the `cover` (Cover picture) as GraphCoverPhoto if present.
55
+ *
56
+ * @return GraphCoverPhoto|null
57
+ */
58
+ public function getCover()
59
+ {
60
+ return $this->getField('cover');
61
+ }
62
+
63
+ /**
64
+ * Returns the `description` (Long-form description) as string if present.
65
+ *
66
+ * @return string|null
67
+ */
68
+ public function getDescription()
69
+ {
70
+ return $this->getField('description');
71
+ }
72
+
73
+ /**
74
+ * Returns the `end_time` (End time, if one has been set) as DateTime if present.
75
+ *
76
+ * @return \DateTime|null
77
+ */
78
+ public function getEndTime()
79
+ {
80
+ return $this->getField('end_time');
81
+ }
82
+
83
+ /**
84
+ * Returns the `is_date_only` (Whether the event only has a date specified, but no time) as bool if present.
85
+ *
86
+ * @return bool|null
87
+ */
88
+ public function getIsDateOnly()
89
+ {
90
+ return $this->getField('is_date_only');
91
+ }
92
+
93
+ /**
94
+ * Returns the `name` (Event name) as string if present.
95
+ *
96
+ * @return string|null
97
+ */
98
+ public function getName()
99
+ {
100
+ return $this->getField('name');
101
+ }
102
+
103
+ /**
104
+ * Returns the `owner` (The profile that created the event) as GraphNode if present.
105
+ *
106
+ * @return GraphNode|null
107
+ */
108
+ public function getOwner()
109
+ {
110
+ return $this->getField('owner');
111
+ }
112
+
113
+ /**
114
+ * Returns the `parent_group` (The group the event belongs to) as GraphGroup if present.
115
+ *
116
+ * @return GraphGroup|null
117
+ */
118
+ public function getParentGroup()
119
+ {
120
+ return $this->getField('parent_group');
121
+ }
122
+
123
+ /**
124
+ * Returns the `place` (Event Place information) as GraphPage if present.
125
+ *
126
+ * @return GraphPage|null
127
+ */
128
+ public function getPlace()
129
+ {
130
+ return $this->getField('place');
131
+ }
132
+
133
+ /**
134
+ * Returns the `privacy` (Who can see the event) as string if present.
135
+ *
136
+ * @return string|null
137
+ */
138
+ public function getPrivacy()
139
+ {
140
+ return $this->getField('privacy');
141
+ }
142
+
143
+ /**
144
+ * Returns the `start_time` (Start time) as DateTime if present.
145
+ *
146
+ * @return \DateTime|null
147
+ */
148
+ public function getStartTime()
149
+ {
150
+ return $this->getField('start_time');
151
+ }
152
+
153
+ /**
154
+ * Returns the `ticket_uri` (The link users can visit to buy a ticket to this event) as string if present.
155
+ *
156
+ * @return string|null
157
+ */
158
+ public function getTicketUri()
159
+ {
160
+ return $this->getField('ticket_uri');
161
+ }
162
+
163
+ /**
164
+ * Returns the `timezone` (Timezone) as string if present.
165
+ *
166
+ * @return string|null
167
+ */
168
+ public function getTimezone()
169
+ {
170
+ return $this->getField('timezone');
171
+ }
172
+
173
+ /**
174
+ * Returns the `updated_time` (Last update time) as DateTime if present.
175
+ *
176
+ * @return \DateTime|null
177
+ */
178
+ public function getUpdatedTime()
179
+ {
180
+ return $this->getField('updated_time');
181
+ }
182
+
183
+ /**
184
+ * Returns the `picture` (Event picture) as GraphPicture if present.
185
+ *
186
+ * @return GraphPicture|null
187
+ */
188
+ public function getPicture()
189
+ {
190
+ return $this->getField('picture');
191
+ }
192
+
193
+ /**
194
+ * Returns the `attending_count` (Number of people attending the event) as int if present.
195
+ *
196
+ * @return int|null
197
+ */
198
+ public function getAttendingCount()
199
+ {
200
+ return $this->getField('attending_count');
201
+ }
202
+
203
+ /**
204
+ * Returns the `declined_count` (Number of people who declined the event) as int if present.
205
+ *
206
+ * @return int|null
207
+ */
208
+ public function getDeclinedCount()
209
+ {
210
+ return $this->getField('declined_count');
211
+ }
212
+
213
+ /**
214
+ * Returns the `maybe_count` (Number of people who maybe going to the event) as int if present.
215
+ *
216
+ * @return int|null
217
+ */
218
+ public function getMaybeCount()
219
+ {
220
+ return $this->getField('maybe_count');
221
+ }
222
+
223
+ /**
224
+ * Returns the `noreply_count` (Number of people who did not reply to the event) as int if present.
225
+ *
226
+ * @return int|null
227
+ */
228
+ public function getNoreplyCount()
229
+ {
230
+ return $this->getField('noreply_count');
231
+ }
232
+
233
+ /**
234
+ * Returns the `invited_count` (Number of people invited to the event) as int if present.
235
+ *
236
+ * @return int|null
237
+ */
238
+ public function getInvitedCount()
239
+ {
240
+ return $this->getField('invited_count');
241
+ }
242
+ }
vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphGroup.php ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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
+ /**
27
+ * Class GraphGroup
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class GraphGroup extends GraphNode
32
+ {
33
+ /**
34
+ * @var array Maps object key names to GraphNode types.
35
+ */
36
+ protected static $graphObjectMap = [
37
+ 'cover' => '\Facebook\GraphNodes\GraphCoverPhoto',
38
+ 'venue' => '\Facebook\GraphNodes\GraphLocation',
39
+ ];
40
+
41
+ /**
42
+ * Returns the `id` (The Group ID) as string if present.
43
+ *
44
+ * @return string|null
45
+ */
46
+ public function getId()
47
+ {
48
+ return $this->getField('id');
49
+ }
50
+
51
+ /**
52
+ * Returns the `cover` (The cover photo of the Group) as GraphCoverPhoto if present.
53
+ *
54
+ * @return GraphCoverPhoto|null
55
+ */
56
+ public function getCover()
57
+ {
58
+ return $this->getField('cover');
59
+ }
60
+
61
+ /**
62
+ * Returns the `description` (A brief description of the Group) as string if present.
63
+ *
64
+ * @return string|null
65
+ */
66
+ public function getDescription()
67
+ {
68
+ return $this->getField('description');
69
+ }
70
+
71
+ /**
72
+ * Returns the `email` (The email address to upload content to the Group. Only current members of the Group can use this) as string if present.
73
+ *
74
+ * @return string|null
75
+ */
76
+ public function getEmail()
77
+ {
78
+ return $this->getField('email');
79
+ }
80
+
81
+ /**
82
+ * Returns the `icon` (The URL for the Group's icon) as string if present.
83
+ *
84
+ * @return string|null
85
+ */
86
+ public function getIcon()
87
+ {
88
+ return $this->getField('icon');
89
+ }
90
+
91
+ /**
92
+ * Returns the `link` (The Group's website) as string if present.
93
+ *
94
+ * @return string|null
95
+ */
96
+ public function getLink()
97
+ {
98
+ return $this->getField('link');
99
+ }
100
+
101
+ /**
102
+ * Returns the `name` (The name of the Group) as string if present.
103
+ *
104
+ * @return string|null
105
+ */
106
+ public function getName()
107
+ {
108
+ return $this->getField('name');
109
+ }
110
+
111
+ /**
112
+ * Returns the `member_request_count` (Number of people asking to join the group.) as int if present.
113
+ *
114
+ * @return int|null
115
+ */
116
+ public function getMemberRequestCount()
117
+ {
118
+ return $this->getField('member_request_count');
119
+ }
120
+
121
+ /**
122
+ * Returns the `owner` (The profile that created this Group) as GraphNode if present.
123
+ *
124
+ * @return GraphNode|null
125
+ */
126
+ public function getOwner()
127
+ {
128
+ return $this->getField('owner');
129
+ }
130
+
131
+ /**
132
+ * Returns the `parent` (The parent Group of this Group, if it exists) as GraphNode if present.
133
+ *
134
+ * @return GraphNode|null
135
+ */
136
+ public function getParent()
137
+ {
138
+ return $this->getField('parent');
139
+ }
140
+
141
+ /**
142
+ * Returns the `privacy` (The privacy setting of the Group) as string if present.
143
+ *
144
+ * @return string|null
145
+ */
146
+ public function getPrivacy()
147
+ {
148
+ return $this->getField('privacy');
149
+ }
150
+
151
+ /**
152
+ * Returns the `updated_time` (The last time the Group was updated (this includes changes in the Group's properties and changes in posts and comments if user can see them)) as \DateTime if present.
153
+ *
154
+ * @return \DateTime|null
155
+ */
156
+ public function getUpdatedTime()
157
+ {
158
+ return $this->getField('updated_time');
159
+ }
160
+
161
+ /**
162
+ * Returns the `venue` (The location for the Group) as GraphLocation if present.
163
+ *
164
+ * @return GraphLocation|null
165
+ */
166
+ public function getVenue()
167
+ {
168
+ return $this->getField('venue');
169
+ }
170
+ }
vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphList.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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
+ /**
27
+ * Class GraphList
28
+ *
29
+ * @package Facebook
30
+ *
31
+ * @deprecated 5.0.0 GraphList has been renamed to GraphEdge
32
+ * @todo v6: Remove this class
33
+ */
34
+ class GraphList extends GraphEdge
35
+ {
36
+ }
vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphLocation.php ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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
+ /**
27
+ * Class GraphLocation
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class GraphLocation extends GraphNode
32
+ {
33
+ /**
34
+ * Returns the street component of the location
35
+ *
36
+ * @return string|null
37
+ */
38
+ public function getStreet()
39
+ {
40
+ return $this->getField('street');
41
+ }
42
+
43
+ /**
44
+ * Returns the city component of the location
45
+ *
46
+ * @return string|null
47
+ */
48
+ public function getCity()
49
+ {
50
+ return $this->getField('city');
51
+ }
52
+
53
+ /**
54
+ * Returns the state component of the location
55
+ *
56
+ * @return string|null
57
+ */
58
+ public function getState()
59
+ {
60
+ return $this->getField('state');
61
+ }
62
+
63
+ /**
64
+ * Returns the country component of the location
65
+ *
66
+ * @return string|null
67
+ */
68
+ public function getCountry()
69
+ {
70
+ return $this->getField('country');
71
+ }
72
+
73
+ /**
74
+ * Returns the zipcode component of the location
75
+ *
76
+ * @return string|null
77
+ */
78
+ public function getZip()
79
+ {
80
+ return $this->getField('zip');
81
+ }
82
+
83
+ /**
84
+ * Returns the latitude component of the location
85
+ *
86
+ * @return float|null
87
+ */
88
+ public function getLatitude()
89
+ {
90
+ return $this->getField('latitude');
91
+ }
92
+
93
+ /**
94
+ * Returns the street component of the location
95
+ *
96
+ * @return float|null
97
+ */
98
+ public function getLongitude()
99
+ {
100
+ return $this->getField('longitude');
101
+ }
102
+ }
vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphNode.php ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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
+ /**
27
+ * Class GraphNode
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class GraphNode extends Collection
32
+ {
33
+ /**
34
+ * @var array Maps object key names to Graph object types.
35
+ */
36
+ protected static $graphObjectMap = [];
37
+
38
+ /**
39
+ * Init this Graph object.
40
+ *
41
+ * @param array $data
42
+ */
43
+ public function __construct(array $data = [])
44
+ {
45
+ parent::__construct($this->castItems($data));
46
+ }
47
+
48
+ /**
49
+ * Iterates over an array and detects the types each node
50
+ * should be cast to and returns all the items as an array.
51
+ *
52
+ * @TODO Add auto-casting to AccessToken entities.
53
+ *
54
+ * @param array $data The array to iterate over.
55
+ *
56
+ * @return array
57
+ */
58
+ public function castItems(array $data)
59
+ {
60
+ $items = [];
61
+
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
+ }
72
+ }
73
+
74
+ return $items;
75
+ }
76
+
77
+ /**
78
+ * Uncasts any auto-casted datatypes.
79
+ * Basically the reverse of castItems().
80
+ *
81
+ * @return array
82
+ */
83
+ public function uncastItems()
84
+ {
85
+ $items = $this->asArray();
86
+
87
+ return array_map(function ($v) {
88
+ if ($v instanceof \DateTime) {
89
+ return $v->format(\DateTime::ISO8601);
90
+ }
91
+
92
+ return $v;
93
+ }, $items);
94
+ }
95
+
96
+ /**
97
+ * Get the collection of items as JSON.
98
+ *
99
+ * @param int $options
100
+ *
101
+ * @return string
102
+ */
103
+ public function asJson($options = 0)
104
+ {
105
+ return json_encode($this->uncastItems(), $options);
106
+ }
107
+
108
+ /**
109
+ * Detects an ISO 8601 formatted string.
110
+ *
111
+ * @param string $string
112
+ *
113
+ * @return boolean
114
+ *
115
+ * @see https://developers.facebook.com/docs/graph-api/using-graph-api/#readmodifiers
116
+ * @see http://www.cl.cam.ac.uk/~mgk25/iso-time.html
117
+ * @see http://en.wikipedia.org/wiki/ISO_8601
118
+ */
119
+ public function isIso8601DateString($string)
120
+ {
121
+ // This insane regex was yoinked from here:
122
+ // http://www.pelagodesign.com/blog/2009/05/20/iso-8601-date-validation-that-doesnt-suck/
123
+ // ...and I'm all like:
124
+ // http://thecodinglove.com/post/95378251969/when-code-works-and-i-dont-know-why
125
+ $crazyInsaneRegexThatSomehowDetectsIso8601 = '/^([\+-]?\d{4}(?!\d{2}\b))'
126
+ . '((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?'
127
+ . '|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d'
128
+ . '|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])'
129
+ . '((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d'
130
+ . '([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/';
131
+
132
+ return preg_match($crazyInsaneRegexThatSomehowDetectsIso8601, $string) === 1;
133
+ }
134
+
135
+ /**
136
+ * Determines if a value from Graph should be cast to DateTime.
137
+ *
138
+ * @param string $key
139
+ *
140
+ * @return boolean
141
+ */
142
+ public function shouldCastAsDateTime($key)
143
+ {
144
+ return in_array($key, [
145
+ 'created_time',
146
+ 'updated_time',
147
+ 'start_time',
148
+ 'end_time',
149
+ 'backdated_time',
150
+ 'issued_at',
151
+ 'expires_at',
152
+ 'birthday',
153
+ 'publish_time'
154
+ ], true);
155
+ }
156
+
157
+ /**
158
+ * Casts a date value from Graph to DateTime.
159
+ *
160
+ * @param int|string $value
161
+ *
162
+ * @return \DateTime
163
+ */
164
+ public function castToDateTime($value)
165
+ {
166
+ if (is_int($value)) {
167
+ $dt = new \DateTime();
168
+ $dt->setTimestamp($value);
169
+ } else {
170
+ $dt = new \DateTime($value);
171
+ }
172
+
173
+ return $dt;
174
+ }
175
+
176
+ /**
177
+ * Getter for $graphObjectMap.
178
+ *
179
+ * @return array
180
+ */
181
+ public static function getObjectMap()
182
+ {
183
+ return static::$graphObjectMap;
184
+ }
185
+ }
vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphNodeFactory.php ADDED
@@ -0,0 +1,392 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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 Facebook\FacebookResponse;
27
+ use Facebook\Exceptions\FacebookSDKException;
28
+
29
+ /**
30
+ * Class GraphNodeFactory
31
+ *
32
+ * @package Facebook
33
+ *
34
+ * ## Assumptions ##
35
+ * GraphEdge - is ALWAYS a numeric array
36
+ * GraphEdge - is ALWAYS an array of GraphNode types
37
+ * GraphNode - is ALWAYS an associative array
38
+ * GraphNode - MAY contain GraphNode's "recurrable"
39
+ * GraphNode - MAY contain GraphEdge's "recurrable"
40
+ * GraphNode - MAY contain DateTime's "primitives"
41
+ * GraphNode - MAY contain string's "primitives"
42
+ */
43
+ class GraphNodeFactory
44
+ {
45
+ /**
46
+ * @const string The base graph object class.
47
+ */
48
+ const BASE_GRAPH_NODE_CLASS = '\Facebook\GraphNodes\GraphNode';
49
+
50
+ /**
51
+ * @const string The base graph edge class.
52
+ */
53
+ const BASE_GRAPH_EDGE_CLASS = '\Facebook\GraphNodes\GraphEdge';
54
+
55
+ /**
56
+ * @const string The graph object prefix.
57
+ */
58
+ const BASE_GRAPH_OBJECT_PREFIX = '\Facebook\GraphNodes\\';
59
+
60
+ /**
61
+ * @var FacebookResponse The response entity from Graph.
62
+ */
63
+ protected $response;
64
+
65
+ /**
66
+ * @var array The decoded body of the FacebookResponse entity from Graph.
67
+ */
68
+ protected $decodedBody;
69
+
70
+ /**
71
+ * Init this Graph object.
72
+ *
73
+ * @param FacebookResponse $response The response entity from Graph.
74
+ */
75
+ public function __construct(FacebookResponse $response)
76
+ {
77
+ $this->response = $response;
78
+ $this->decodedBody = $response->getDecodedBody();
79
+ }
80
+
81
+ /**
82
+ * Tries to convert a FacebookResponse entity into a GraphNode.
83
+ *
84
+ * @param string|null $subclassName The GraphNode sub class to cast to.
85
+ *
86
+ * @return GraphNode
87
+ *
88
+ * @throws FacebookSDKException
89
+ */
90
+ public function makeGraphNode($subclassName = null)
91
+ {
92
+ $this->validateResponseAsArray();
93
+ $this->validateResponseCastableAsGraphNode();
94
+
95
+ return $this->castAsGraphNodeOrGraphEdge($this->decodedBody, $subclassName);
96
+ }
97
+
98
+ /**
99
+ * Convenience method for creating a GraphAchievement collection.
100
+ *
101
+ * @return GraphAchievement
102
+ *
103
+ * @throws FacebookSDKException
104
+ */
105
+ public function makeGraphAchievement()
106
+ {
107
+ return $this->makeGraphNode(static::BASE_GRAPH_OBJECT_PREFIX . 'GraphAchievement');
108
+ }
109
+
110
+ /**
111
+ * Convenience method for creating a GraphAlbum collection.
112
+ *
113
+ * @return GraphAlbum
114
+ *
115
+ * @throws FacebookSDKException
116
+ */
117
+ public function makeGraphAlbum()
118
+ {
119
+ return $this->makeGraphNode(static::BASE_GRAPH_OBJECT_PREFIX . 'GraphAlbum');
120
+ }
121
+
122
+ /**
123
+ * Convenience method for creating a GraphPage collection.
124
+ *
125
+ * @return GraphPage
126
+ *
127
+ * @throws FacebookSDKException
128
+ */
129
+ public function makeGraphPage()
130
+ {
131
+ return $this->makeGraphNode(static::BASE_GRAPH_OBJECT_PREFIX . 'GraphPage');
132
+ }
133
+
134
+ /**
135
+ * Convenience method for creating a GraphSessionInfo collection.
136
+ *
137
+ * @return GraphSessionInfo
138
+ *
139
+ * @throws FacebookSDKException
140
+ */
141
+ public function makeGraphSessionInfo()
142
+ {
143
+ return $this->makeGraphNode(static::BASE_GRAPH_OBJECT_PREFIX . 'GraphSessionInfo');
144
+ }
145
+
146
+ /**
147
+ * Convenience method for creating a GraphUser collection.
148
+ *
149
+ * @return GraphUser
150
+ *
151
+ * @throws FacebookSDKException
152
+ */
153
+ public function makeGraphUser()
154
+ {
155
+ return $this->makeGraphNode(static::BASE_GRAPH_OBJECT_PREFIX . 'GraphUser');
156
+ }
157
+
158
+ /**
159
+ * Convenience method for creating a GraphEvent collection.
160
+ *
161
+ * @return GraphEvent
162
+ *
163
+ * @throws FacebookSDKException
164
+ */
165
+ public function makeGraphEvent()
166
+ {
167
+ return $this->makeGraphNode(static::BASE_GRAPH_OBJECT_PREFIX . 'GraphEvent');
168
+ }
169
+
170
+ /**
171
+ * Convenience method for creating a GraphGroup collection.
172
+ *
173
+ * @return GraphGroup
174
+ *
175
+ * @throws FacebookSDKException
176
+ */
177
+ public function makeGraphGroup()
178
+ {
179
+ return $this->makeGraphNode(static::BASE_GRAPH_OBJECT_PREFIX . 'GraphGroup');
180
+ }
181
+
182
+ /**
183
+ * Tries to convert a FacebookResponse entity into a GraphEdge.
184
+ *
185
+ * @param string|null $subclassName The GraphNode sub class to cast the list items to.
186
+ * @param boolean $auto_prefix Toggle to auto-prefix the subclass name.
187
+ *
188
+ * @return GraphEdge
189
+ *
190
+ * @throws FacebookSDKException
191
+ */
192
+ public function makeGraphEdge($subclassName = null, $auto_prefix = true)
193
+ {
194
+ $this->validateResponseAsArray();
195
+ $this->validateResponseCastableAsGraphEdge();
196
+
197
+ if ($subclassName && $auto_prefix) {
198
+ $subclassName = static::BASE_GRAPH_OBJECT_PREFIX . $subclassName;
199
+ }
200
+
201
+ return $this->castAsGraphNodeOrGraphEdge($this->decodedBody, $subclassName);
202
+ }
203
+
204
+ /**
205
+ * Validates the decoded body.
206
+ *
207
+ * @throws FacebookSDKException
208
+ */
209
+ public function validateResponseAsArray()
210
+ {
211
+ if (!is_array($this->decodedBody)) {
212
+ throw new FacebookSDKException('Unable to get response from Graph as array.', 620);
213
+ }
214
+ }
215
+
216
+ /**
217
+ * Validates that the return data can be cast as a GraphNode.
218
+ *
219
+ * @throws FacebookSDKException
220
+ */
221
+ public function validateResponseCastableAsGraphNode()
222
+ {
223
+ if (isset($this->decodedBody['data']) && static::isCastableAsGraphEdge($this->decodedBody['data'])) {
224
+ throw new FacebookSDKException(
225
+ 'Unable to convert response from Graph to a GraphNode because the response looks like a GraphEdge. Try using GraphNodeFactory::makeGraphEdge() instead.',
226
+ 620
227
+ );
228
+ }
229
+ }
230
+
231
+ /**
232
+ * Validates that the return data can be cast as a GraphEdge.
233
+ *
234
+ * @throws FacebookSDKException
235
+ */
236
+ public function validateResponseCastableAsGraphEdge()
237
+ {
238
+ if (!(isset($this->decodedBody['data']) && static::isCastableAsGraphEdge($this->decodedBody['data']))) {
239
+ throw new FacebookSDKException(
240
+ 'Unable to convert response from Graph to a GraphEdge because the response does not look like a GraphEdge. Try using GraphNodeFactory::makeGraphNode() instead.',
241
+ 620
242
+ );
243
+ }
244
+ }
245
+
246
+ /**
247
+ * Safely instantiates a GraphNode of $subclassName.
248
+ *
249
+ * @param array $data The array of data to iterate over.
250
+ * @param string|null $subclassName The subclass to cast this collection to.
251
+ *
252
+ * @return GraphNode
253
+ *
254
+ * @throws FacebookSDKException
255
+ */
256
+ public function safelyMakeGraphNode(array $data, $subclassName = null)
257
+ {
258
+ $subclassName = $subclassName ?: static::BASE_GRAPH_NODE_CLASS;
259
+ static::validateSubclass($subclassName);
260
+
261
+ // Remember the parent node ID
262
+ $parentNodeId = isset($data['id']) ? $data['id'] : null;
263
+
264
+ $items = [];
265
+
266
+ foreach ($data as $k => $v) {
267
+ // Array means could be recurable
268
+ if (is_array($v)) {
269
+ // Detect any smart-casting from the $graphObjectMap array.
270
+ // This is always empty on the GraphNode collection, but subclasses can define
271
+ // their own array of smart-casting types.
272
+ $graphObjectMap = $subclassName::getObjectMap();
273
+ $objectSubClass = isset($graphObjectMap[$k])
274
+ ? $graphObjectMap[$k]
275
+ : null;
276
+
277
+ // Could be a GraphEdge or GraphNode
278
+ $items[$k] = $this->castAsGraphNodeOrGraphEdge($v, $objectSubClass, $k, $parentNodeId);
279
+ } else {
280
+ $items[$k] = $v;
281
+ }
282
+ }
283
+
284
+ return new $subclassName($items);
285
+ }
286
+
287
+ /**
288
+ * Takes an array of values and determines how to cast each node.
289
+ *
290
+ * @param array $data The array of data to iterate over.
291
+ * @param string|null $subclassName The subclass to cast this collection to.
292
+ * @param string|null $parentKey The key of this data (Graph edge).
293
+ * @param string|null $parentNodeId The parent Graph node ID.
294
+ *
295
+ * @return GraphNode|GraphEdge
296
+ *
297
+ * @throws FacebookSDKException
298
+ */
299
+ public function castAsGraphNodeOrGraphEdge(array $data, $subclassName = null, $parentKey = null, $parentNodeId = null)
300
+ {
301
+ if (isset($data['data'])) {
302
+ // Create GraphEdge
303
+ if (static::isCastableAsGraphEdge($data['data'])) {
304
+ return $this->safelyMakeGraphEdge($data, $subclassName, $parentKey, $parentNodeId);
305
+ }
306
+ // Sometimes Graph is a weirdo and returns a GraphNode under the "data" key
307
+ $data = $data['data'];
308
+ }
309
+
310
+ // Create GraphNode
311
+ return $this->safelyMakeGraphNode($data, $subclassName);
312
+ }
313
+
314
+ /**
315
+ * Return an array of GraphNode's.
316
+ *
317
+ * @param array $data The array of data to iterate over.
318
+ * @param string|null $subclassName The GraphNode subclass to cast each item in the list to.
319
+ * @param string|null $parentKey The key of this data (Graph edge).
320
+ * @param string|null $parentNodeId The parent Graph node ID.
321
+ *
322
+ * @return GraphEdge
323
+ *
324
+ * @throws FacebookSDKException
325
+ */
326
+ public function safelyMakeGraphEdge(array $data, $subclassName = null, $parentKey = null, $parentNodeId = null)
327
+ {
328
+ if (!isset($data['data'])) {
329
+ throw new FacebookSDKException('Cannot cast data to GraphEdge. Expected a "data" key.', 620);
330
+ }
331
+
332
+ $dataList = [];
333
+ foreach ($data['data'] as $graphNode) {
334
+ $dataList[] = $this->safelyMakeGraphNode($graphNode, $subclassName);
335
+ }
336
+
337
+ $metaData = $this->getMetaData($data);
338
+
339
+ // We'll need to make an edge endpoint for this in case it's a GraphEdge (for cursor pagination)
340
+ $parentGraphEdgeEndpoint = $parentNodeId && $parentKey ? '/' . $parentNodeId . '/' . $parentKey : null;
341
+ $className = static::BASE_GRAPH_EDGE_CLASS;
342
+
343
+ return new $className($this->response->getRequest(), $dataList, $metaData, $parentGraphEdgeEndpoint, $subclassName);
344
+ }
345
+
346
+ /**
347
+ * Get the meta data from a list in a Graph response.
348
+ *
349
+ * @param array $data The Graph response.
350
+ *
351
+ * @return array
352
+ */
353
+ public function getMetaData(array $data)
354
+ {
355
+ unset($data['data']);
356
+
357
+ return $data;
358
+ }
359
+
360
+ /**
361
+ * Determines whether or not the data should be cast as a GraphEdge.
362
+ *
363
+ * @param array $data
364
+ *
365
+ * @return boolean
366
+ */
367
+ public static function isCastableAsGraphEdge(array $data)
368
+ {
369
+ if ($data === []) {
370
+ return true;
371
+ }
372
+
373
+ // Checks for a sequential numeric array which would be a GraphEdge
374
+ return array_keys($data) === range(0, count($data) - 1);
375
+ }
376
+
377
+ /**
378
+ * Ensures that the subclass in question is valid.
379
+ *
380
+ * @param string $subclassName The GraphNode subclass to validate.
381
+ *
382
+ * @throws FacebookSDKException
383
+ */
384
+ public static function validateSubclass($subclassName)
385
+ {
386
+ if ($subclassName == static::BASE_GRAPH_NODE_CLASS || is_subclass_of($subclassName, static::BASE_GRAPH_NODE_CLASS)) {
387
+ return;
388
+ }
389
+
390
+ throw new FacebookSDKException('The given subclass "' . $subclassName . '" is not valid. Cannot cast to an object that is not a GraphNode subclass.', 620);
391
+ }
392
+ }
vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphObject.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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
+ /**
27
+ * Class GraphObject
28
+ *
29
+ * @package Facebook
30
+ *
31
+ * @deprecated 5.0.0 GraphObject has been renamed to GraphNode
32
+ * @todo v6: Remove this class
33
+ */
34
+ class GraphObject extends GraphNode
35
+ {
36
+ }
vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphObjectFactory.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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 Facebook\Exceptions\FacebookSDKException;
27
+
28
+ /**
29
+ * Class GraphObjectFactory
30
+ *
31
+ * @package Facebook
32
+ *
33
+ * @deprecated 5.0.0 GraphObjectFactory has been renamed to GraphNodeFactory
34
+ * @todo v6: Remove this class
35
+ */
36
+ class GraphObjectFactory extends GraphNodeFactory
37
+ {
38
+ /**
39
+ * @const string The base graph object class.
40
+ */
41
+ const BASE_GRAPH_NODE_CLASS = '\Facebook\GraphNodes\GraphObject';
42
+
43
+ /**
44
+ * @const string The base graph edge class.
45
+ */
46
+ const BASE_GRAPH_EDGE_CLASS = '\Facebook\GraphNodes\GraphList';
47
+
48
+ /**
49
+ * Tries to convert a FacebookResponse entity into a GraphNode.
50
+ *
51
+ * @param string|null $subclassName The GraphNode sub class to cast to.
52
+ *
53
+ * @return GraphNode
54
+ *
55
+ * @deprecated 5.0.0 GraphObjectFactory has been renamed to GraphNodeFactory
56
+ */
57
+ public function makeGraphObject($subclassName = null)
58
+ {
59
+ return $this->makeGraphNode($subclassName);
60
+ }
61
+
62
+ /**
63
+ * Convenience method for creating a GraphEvent collection.
64
+ *
65
+ * @return GraphEvent
66
+ *
67
+ * @throws FacebookSDKException
68
+ */
69
+ public function makeGraphEvent()
70
+ {
71
+ return $this->makeGraphNode(static::BASE_GRAPH_OBJECT_PREFIX . 'GraphEvent');
72
+ }
73
+
74
+ /**
75
+ * Tries to convert a FacebookResponse entity into a GraphEdge.
76
+ *
77
+ * @param string|null $subclassName The GraphNode sub class to cast the list items to.
78
+ * @param boolean $auto_prefix Toggle to auto-prefix the subclass name.
79
+ *
80
+ * @return GraphEdge
81
+ *
82
+ * @deprecated 5.0.0 GraphObjectFactory has been renamed to GraphNodeFactory
83
+ */
84
+ public function makeGraphList($subclassName = null, $auto_prefix = true)
85
+ {
86
+ return $this->makeGraphEdge($subclassName, $auto_prefix);
87
+ }
88
+ }
vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphPage.php ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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
+ /**
27
+ * Class GraphPage
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class GraphPage extends GraphNode
32
+ {
33
+ /**
34
+ * @var array Maps object key names to Graph object types.
35
+ */
36
+ protected static $graphObjectMap = [
37
+ 'best_page' => '\Facebook\GraphNodes\GraphPage',
38
+ 'global_brand_parent_page' => '\Facebook\GraphNodes\GraphPage',
39
+ 'location' => '\Facebook\GraphNodes\GraphLocation',
40
+ ];
41
+
42
+ /**
43
+ * Returns the ID for the user's page as a string if present.
44
+ *
45
+ * @return string|null
46
+ */
47
+ public function getId()
48
+ {
49
+ return $this->getField('id');
50
+ }
51
+
52
+ /**
53
+ * Returns the Category for the user's page as a string if present.
54
+ *
55
+ * @return string|null
56
+ */
57
+ public function getCategory()
58
+ {
59
+ return $this->getField('category');
60
+ }
61
+
62
+ /**
63
+ * Returns the Name of the user's page as a string if present.
64
+ *
65
+ * @return string|null
66
+ */
67
+ public function getName()
68
+ {
69
+ return $this->getField('name');
70
+ }
71
+
72
+ /**
73
+ * Returns the best available Page on Facebook.
74
+ *
75
+ * @return GraphPage|null
76
+ */
77
+ public function getBestPage()
78
+ {
79
+ return $this->getField('best_page');
80
+ }
81
+
82
+ /**
83
+ * Returns the brand's global (parent) Page.
84
+ *
85
+ * @return GraphPage|null
86
+ */
87
+ public function getGlobalBrandParentPage()
88
+ {
89
+ return $this->getField('global_brand_parent_page');
90
+ }
91
+
92
+ /**
93
+ * Returns the location of this place.
94
+ *
95
+ * @return GraphLocation|null
96
+ */
97
+ public function getLocation()
98
+ {
99
+ return $this->getField('location');
100
+ }
101
+
102
+ /**
103
+ * Returns the page access token for the admin user.
104
+ *
105
+ * Only available in the `/me/accounts` context.
106
+ *
107
+ * @return string|null
108
+ */
109
+ public function getAccessToken()
110
+ {
111
+ return $this->getField('access_token');
112
+ }
113
+
114
+ /**
115
+ * Returns the roles of the page admin user.
116
+ *
117
+ * Only available in the `/me/accounts` context.
118
+ *
119
+ * @return array|null
120
+ */
121
+ public function getPerms()
122
+ {
123
+ return $this->getField('perms');
124
+ }
125
+ }
vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphPicture.php ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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
+ /**
27
+ * Class GraphPicture
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class GraphPicture extends GraphNode
32
+ {
33
+ /**
34
+ * Returns true if user picture is silhouette.
35
+ *
36
+ * @return bool|null
37
+ */
38
+ public function isSilhouette()
39
+ {
40
+ return $this->getField('is_silhouette');
41
+ }
42
+
43
+ /**
44
+ * Returns the url of user picture if it exists
45
+ *
46
+ * @return string|null
47
+ */
48
+ public function getUrl()
49
+ {
50
+ return $this->getField('url');
51
+ }
52
+
53
+ /**
54
+ * Returns the width of user picture if it exists
55
+ *
56
+ * @return int|null
57
+ */
58
+ public function getWidth()
59
+ {
60
+ return $this->getField('width');
61
+ }
62
+
63
+ /**
64
+ * Returns the height of user picture if it exists
65
+ *
66
+ * @return int|null
67
+ */
68
+ public function getHeight()
69
+ {
70
+ return $this->getField('height');
71
+ }
72
+ }
vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphSessionInfo.php ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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
+ /**
27
+ * Class GraphSessionInfo
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class GraphSessionInfo extends GraphNode
32
+ {
33
+ /**
34
+ * Returns the application id the token was issued for.
35
+ *
36
+ * @return string|null
37
+ */
38
+ public function getAppId()
39
+ {
40
+ return $this->getField('app_id');
41
+ }
42
+
43
+ /**
44
+ * Returns the application name the token was issued for.
45
+ *
46
+ * @return string|null
47
+ */
48
+ public function getApplication()
49
+ {
50
+ return $this->getField('application');
51
+ }
52
+
53
+ /**
54
+ * Returns the date & time that the token expires.
55
+ *
56
+ * @return \DateTime|null
57
+ */
58
+ public function getExpiresAt()
59
+ {
60
+ return $this->getField('expires_at');
61
+ }
62
+
63
+ /**
64
+ * Returns whether the token is valid.
65
+ *
66
+ * @return boolean
67
+ */
68
+ public function getIsValid()
69
+ {
70
+ return $this->getField('is_valid');
71
+ }
72
+
73
+ /**
74
+ * Returns the date & time the token was issued at.
75
+ *
76
+ * @return \DateTime|null
77
+ */
78
+ public function getIssuedAt()
79
+ {
80
+ return $this->getField('issued_at');
81
+ }
82
+
83
+ /**
84
+ * Returns the scope permissions associated with the token.
85
+ *
86
+ * @return array
87
+ */
88
+ public function getScopes()
89
+ {
90
+ return $this->getField('scopes');
91
+ }
92
+
93
+ /**
94
+ * Returns the login id of the user associated with the token.
95
+ *
96
+ * @return string|null
97
+ */
98
+ public function getUserId()
99
+ {
100
+ return $this->getField('user_id');
101
+ }
102
+ }
vendor/facebook/php-sdk-v4/src/Facebook/GraphNodes/GraphUser.php ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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
+ /**
27
+ * Class GraphUser
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class GraphUser extends GraphNode
32
+ {
33
+ /**
34
+ * @var array Maps object key names to Graph object types.
35
+ */
36
+ protected static $graphObjectMap = [
37
+ 'hometown' => '\Facebook\GraphNodes\GraphPage',
38
+ 'location' => '\Facebook\GraphNodes\GraphPage',
39
+ 'significant_other' => '\Facebook\GraphNodes\GraphUser',
40
+ 'picture' => '\Facebook\GraphNodes\GraphPicture',
41
+ ];
42
+
43
+ /**
44
+ * Returns the ID for the user as a string if present.
45
+ *
46
+ * @return string|null
47
+ */
48
+ public function getId()
49
+ {
50
+ return $this->getField('id');
51
+ }
52
+
53
+ /**
54
+ * Returns the name for the user as a string if present.
55
+ *
56
+ * @return string|null
57
+ */
58
+ public function getName()
59
+ {
60
+ return $this->getField('name');
61
+ }
62
+
63
+ /**
64
+ * Returns the first name for the user as a string if present.
65
+ *
66
+ * @return string|null
67
+ */
68
+ public function getFirstName()
69
+ {
70
+ return $this->getField('first_name');
71
+ }
72
+
73
+ /**
74
+ * Returns the middle name for the user as a string if present.
75
+ *
76
+ * @return string|null
77
+ */
78
+ public function getMiddleName()
79
+ {
80
+ return $this->getField('middle_name');
81
+ }
82
+
83
+ /**
84
+ * Returns the last name for the user as a string if present.
85
+ *
86
+ * @return string|null
87
+ */
88
+ public function getLastName()
89
+ {
90
+ return $this->getField('last_name');
91
+ }
92
+
93
+ /**
94
+ * Returns the email for the user as a string if present.
95
+ *
96
+ * @return string|null
97
+ */
98
+ public function getEmail()
99
+ {
100
+ return $this->getField('email');
101
+ }
102
+
103
+ /**
104
+ * Returns the gender for the user as a string if present.
105
+ *
106
+ * @return string|null
107
+ */
108
+ public function getGender()
109
+ {
110
+ return $this->getField('gender');
111
+ }
112
+
113
+ /**
114
+ * Returns the Facebook URL for the user as a string if available.
115
+ *
116
+ * @return string|null
117
+ */
118
+ public function getLink()
119
+ {
120
+ return $this->getField('link');
121
+ }
122
+
123
+ /**
124
+ * Returns the users birthday, if available.
125
+ *
126
+ * @return \DateTime|null
127
+ */
128
+ public function getBirthday()
129
+ {
130
+ return $this->getField('birthday');
131
+ }
132
+
133
+ /**
134
+ * Returns the current location of the user as a GraphPage.
135
+ *
136
+ * @return GraphPage|null
137
+ */
138
+ public function getLocation()
139
+ {
140
+ return $this->getField('location');
141
+ }
142
+
143
+ /**
144
+ * Returns the current location of the user as a GraphPage.
145
+ *
146
+ * @return GraphPage|null
147
+ */
148
+ public function getHometown()
149
+ {
150
+ return $this->getField('hometown');
151
+ }
152
+
153
+ /**
154
+ * Returns the current location of the user as a GraphUser.
155
+ *
156
+ * @return GraphUser|null
157
+ */
158
+ public function getSignificantOther()
159
+ {
160
+ return $this->getField('significant_other');
161
+ }
162
+
163
+ /**
164
+ * Returns the picture of the user as a GraphPicture
165
+ *
166
+ * @return GraphPicture|null
167
+ */
168
+ public function getPicture()
169
+ {
170
+ return $this->getField('picture');
171
+ }
172
+ }
vendor/facebook/php-sdk-v4/src/Facebook/Helpers/FacebookCanvasHelper.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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\Helpers;
25
+
26
+ /**
27
+ * Class FacebookCanvasLoginHelper
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class FacebookCanvasHelper extends FacebookSignedRequestFromInputHelper
32
+ {
33
+ /**
34
+ * Returns the app data value.
35
+ *
36
+ * @return mixed|null
37
+ */
38
+ public function getAppData()
39
+ {
40
+ return $this->signedRequest ? $this->signedRequest->get('app_data') : null;
41
+ }
42
+
43
+ /**
44
+ * Get raw signed request from POST.
45
+ *
46
+ * @return string|null
47
+ */
48
+ public function getRawSignedRequest()
49
+ {
50
+ return $this->getRawSignedRequestFromPost() ?: null;
51
+ }
52
+ }
vendor/facebook/php-sdk-v4/src/Facebook/Helpers/FacebookJavaScriptHelper.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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\Helpers;
25
+
26
+ /**
27
+ * Class FacebookJavaScriptLoginHelper
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class FacebookJavaScriptHelper extends FacebookSignedRequestFromInputHelper
32
+ {
33
+ /**
34
+ * Get raw signed request from the cookie.
35
+ *
36
+ * @return string|null
37
+ */
38
+ public function getRawSignedRequest()
39
+ {
40
+ return $this->getRawSignedRequestFromCookie();
41
+ }
42
+ }
vendor/facebook/php-sdk-v4/src/Facebook/Helpers/FacebookPageTabHelper.php ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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\Helpers;
25
+
26
+ use Facebook\FacebookApp;
27
+ use Facebook\FacebookClient;
28
+
29
+ /**
30
+ * Class FacebookPageTabHelper
31
+ *
32
+ * @package Facebook
33
+ */
34
+ class FacebookPageTabHelper extends FacebookCanvasHelper
35
+ {
36
+ /**
37
+ * @var array|null
38
+ */
39
+ protected $pageData;
40
+
41
+ /**
42
+ * Initialize the helper and process available signed request data.
43
+ *
44
+ * @param FacebookApp $app The FacebookApp entity.
45
+ * @param FacebookClient $client The client to make HTTP requests.
46
+ * @param string|null $graphVersion The version of Graph to use.
47
+ */
48
+ public function __construct(FacebookApp $app, FacebookClient $client, $graphVersion = null)
49
+ {
50
+ parent::__construct($app, $client, $graphVersion);
51
+
52
+ if (!$this->signedRequest) {
53
+ return;
54
+ }
55
+
56
+ $this->pageData = $this->signedRequest->get('page');
57
+ }
58
+
59
+ /**
60
+ * Returns a value from the page data.
61
+ *
62
+ * @param string $key
63
+ * @param mixed|null $default
64
+ *
65
+ * @return mixed|null
66
+ */
67
+ public function getPageData($key, $default = null)
68
+ {
69
+ if (isset($this->pageData[$key])) {
70
+ return $this->pageData[$key];
71
+ }
72
+
73
+ return $default;
74
+ }
75
+
76
+ /**
77
+ * Returns true if the user is an admin.
78
+ *
79
+ * @return boolean
80
+ */
81
+ public function isAdmin()
82
+ {
83
+ return $this->getPageData('admin') === true;
84
+ }
85
+
86
+ /**
87
+ * Returns the page id if available.
88
+ *
89
+ * @return string|null
90
+ */
91
+ public function getPageId()
92
+ {
93
+ return $this->getPageData('id');
94
+ }
95
+ }
vendor/facebook/php-sdk-v4/src/Facebook/Helpers/FacebookRedirectLoginHelper.php ADDED
@@ -0,0 +1,332 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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\Helpers;
25
+
26
+ use Facebook\Authentication\AccessToken;
27
+ use Facebook\Authentication\OAuth2Client;
28
+ use Facebook\Exceptions\FacebookSDKException;
29
+ use Facebook\PersistentData\FacebookSessionPersistentDataHandler;
30
+ use Facebook\PersistentData\PersistentDataInterface;
31
+ use Facebook\PseudoRandomString\PseudoRandomStringGeneratorFactory;
32
+ use Facebook\PseudoRandomString\PseudoRandomStringGeneratorInterface;
33
+ use Facebook\Url\FacebookUrlDetectionHandler;
34
+ use Facebook\Url\FacebookUrlManipulator;
35
+ use Facebook\Url\UrlDetectionInterface;
36
+
37
+ /**
38
+ * Class FacebookRedirectLoginHelper
39
+ *
40
+ * @package Facebook
41
+ */
42
+ class FacebookRedirectLoginHelper
43
+ {
44
+ /**
45
+ * @const int The length of CSRF string to validate the login link.
46
+ */
47
+ const CSRF_LENGTH = 32;
48
+
49
+ /**
50
+ * @var OAuth2Client The OAuth 2.0 client service.
51
+ */
52
+ protected $oAuth2Client;
53
+
54
+ /**
55
+ * @var UrlDetectionInterface The URL detection handler.
56
+ */
57
+ protected $urlDetectionHandler;
58
+
59
+ /**
60
+ * @var PersistentDataInterface The persistent data handler.
61
+ */
62
+ protected $persistentDataHandler;
63
+
64
+ /**
65
+ * @var PseudoRandomStringGeneratorInterface The cryptographically secure pseudo-random string generator.
66
+ */
67
+ protected $pseudoRandomStringGenerator;
68
+
69
+ /**
70
+ * @param OAuth2Client $oAuth2Client The OAuth 2.0 client service.
71
+ * @param PersistentDataInterface|null $persistentDataHandler The persistent data handler.
72
+ * @param UrlDetectionInterface|null $urlHandler The URL detection handler.
73
+ * @param PseudoRandomStringGeneratorInterface|null $prsg The cryptographically secure pseudo-random string generator.
74
+ */
75
+ public function __construct(OAuth2Client $oAuth2Client, PersistentDataInterface $persistentDataHandler = null, UrlDetectionInterface $urlHandler = null, PseudoRandomStringGeneratorInterface $prsg = null)
76
+ {
77
+ $this->oAuth2Client = $oAuth2Client;
78
+ $this->persistentDataHandler = $persistentDataHandler ?: new FacebookSessionPersistentDataHandler();
79
+ $this->urlDetectionHandler = $urlHandler ?: new FacebookUrlDetectionHandler();
80
+ $this->pseudoRandomStringGenerator = PseudoRandomStringGeneratorFactory::createPseudoRandomStringGenerator($prsg);
81
+ }
82
+
83
+ /**
84
+ * Returns the persistent data handler.
85
+ *
86
+ * @return PersistentDataInterface
87
+ */
88
+ public function getPersistentDataHandler()
89
+ {
90
+ return $this->persistentDataHandler;
91
+ }
92
+
93
+ /**
94
+ * Returns the URL detection handler.
95
+ *
96
+ * @return UrlDetectionInterface
97
+ */
98
+ public function getUrlDetectionHandler()
99
+ {
100
+ return $this->urlDetectionHandler;
101
+ }
102
+
103
+ /**
104
+ * Returns the cryptographically secure pseudo-random string generator.
105
+ *
106
+ * @return PseudoRandomStringGeneratorInterface
107
+ */
108
+ public function getPseudoRandomStringGenerator()
109
+ {
110
+ return $this->pseudoRandomStringGenerator;
111
+ }
112
+
113
+ /**
114
+ * Stores CSRF state and returns a URL to which the user should be sent to in order to continue the login process with Facebook.
115
+ *
116
+ * @param string $redirectUrl The URL Facebook should redirect users to after login.
117
+ * @param array $scope List of permissions to request during login.
118
+ * @param array $params An array of parameters to generate URL.
119
+ * @param string $separator The separator to use in http_build_query().
120
+ *
121
+ * @return string
122
+ */
123
+ private function makeUrl($redirectUrl, array $scope, array $params = [], $separator = '&')
124
+ {
125
+ $state = $this->pseudoRandomStringGenerator->getPseudoRandomString(static::CSRF_LENGTH);
126
+ $this->persistentDataHandler->set('state', $state);
127
+
128
+ return $this->oAuth2Client->getAuthorizationUrl($redirectUrl, $state, $scope, $params, $separator);
129
+ }
130
+
131
+ /**
132
+ * Returns the URL to send the user in order to login to Facebook.
133
+ *
134
+ * @param string $redirectUrl The URL Facebook should redirect users to after login.
135
+ * @param array $scope List of permissions to request during login.
136
+ * @param string $separator The separator to use in http_build_query().
137
+ *
138
+ * @return string
139
+ */
140
+ public function getLoginUrl($redirectUrl, array $scope = [], $separator = '&')
141
+ {
142
+ return $this->makeUrl($redirectUrl, $scope, [], $separator);
143
+ }
144
+
145
+ /**
146
+ * Returns the URL to send the user in order to log out of Facebook.
147
+ *
148
+ * @param AccessToken|string $accessToken The access token that will be logged out.
149
+ * @param string $next The url Facebook should redirect the user to after a successful logout.
150
+ * @param string $separator The separator to use in http_build_query().
151
+ *
152
+ * @return string
153
+ *
154
+ * @throws FacebookSDKException
155
+ */
156
+ public function getLogoutUrl($accessToken, $next, $separator = '&')
157
+ {
158
+ if (!$accessToken instanceof AccessToken) {
159
+ $accessToken = new AccessToken($accessToken);
160
+ }
161
+
162
+ if ($accessToken->isAppAccessToken()) {
163
+ throw new FacebookSDKException('Cannot generate a logout URL with an app access token.', 722);
164
+ }
165
+
166
+ $params = [
167
+ 'next' => $next,
168
+ 'access_token' => $accessToken->getValue(),
169
+ ];
170
+
171
+ return 'https://www.facebook.com/logout.php?' . http_build_query($params, null, $separator);
172
+ }
173
+
174
+ /**
175
+ * Returns the URL to send the user in order to login to Facebook with permission(s) to be re-asked.
176
+ *
177
+ * @param string $redirectUrl The URL Facebook should redirect users to after login.
178
+ * @param array $scope List of permissions to request during login.
179
+ * @param string $separator The separator to use in http_build_query().
180
+ *
181
+ * @return string
182
+ */
183
+ public function getReRequestUrl($redirectUrl, array $scope = [], $separator = '&')
184
+ {
185
+ $params = ['auth_type' => 'rerequest'];
186
+
187
+ return $this->makeUrl($redirectUrl, $scope, $params, $separator);
188
+ }
189
+
190
+ /**
191
+ * Returns the URL to send the user in order to login to Facebook with user to be re-authenticated.
192
+ *
193
+ * @param string $redirectUrl The URL Facebook should redirect users to after login.
194
+ * @param array $scope List of permissions to request during login.
195
+ * @param string $separator The separator to use in http_build_query().
196
+ *
197
+ * @return string
198
+ */
199
+ public function getReAuthenticationUrl($redirectUrl, array $scope = [], $separator = '&')
200
+ {
201
+ $params = ['auth_type' => 'reauthenticate'];
202
+
203
+ return $this->makeUrl($redirectUrl, $scope, $params, $separator);
204
+ }
205
+
206
+ /**
207
+ * Takes a valid code from a login redirect, and returns an AccessToken entity.
208
+ *
209
+ * @param string|null $redirectUrl The redirect URL.
210
+ *
211
+ * @return AccessToken|null
212
+ *
213
+ * @throws FacebookSDKException
214
+ */
215
+ public function getAccessToken($redirectUrl = null)
216
+ {
217
+ if (!$code = $this->getCode()) {
218
+ return null;
219
+ }
220
+
221
+ $this->validateCsrf();
222
+
223
+ $redirectUrl = $redirectUrl ?: $this->urlDetectionHandler->getCurrentUrl();
224
+ // At minimum we need to remove the state param
225
+ $redirectUrl = FacebookUrlManipulator::removeParamsFromUrl($redirectUrl, ['state']);
226
+
227
+ return $this->oAuth2Client->getAccessTokenFromCode($code, $redirectUrl);
228
+ }
229
+
230
+ /**
231
+ * Validate the request against a cross-site request forgery.
232
+ *
233
+ * @throws FacebookSDKException
234
+ */
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
+ /**
262
+ * Return the code.
263
+ *
264
+ * @return string|null
265
+ */
266
+ protected function getCode()
267
+ {
268
+ return $this->getInput('code');
269
+ }
270
+
271
+ /**
272
+ * Return the state.
273
+ *
274
+ * @return string|null
275
+ */
276
+ protected function getState()
277
+ {
278
+ return $this->getInput('state');
279
+ }
280
+
281
+ /**
282
+ * Return the error code.
283
+ *
284
+ * @return string|null
285
+ */
286
+ public function getErrorCode()
287
+ {
288
+ return $this->getInput('error_code');
289
+ }
290
+
291
+ /**
292
+ * Returns the error.
293
+ *
294
+ * @return string|null
295
+ */
296
+ public function getError()
297
+ {
298
+ return $this->getInput('error');
299
+ }
300
+
301
+ /**
302
+ * Returns the error reason.
303
+ *
304
+ * @return string|null
305
+ */
306
+ public function getErrorReason()
307
+ {
308
+ return $this->getInput('error_reason');
309
+ }
310
+
311
+ /**
312
+ * Returns the error description.
313
+ *
314
+ * @return string|null
315
+ */
316
+ public function getErrorDescription()
317
+ {
318
+ return $this->getInput('error_description');
319
+ }
320
+
321
+ /**
322
+ * Returns a value from a GET param.
323
+ *
324
+ * @param string $key
325
+ *
326
+ * @return string|null
327
+ */
328
+ private function getInput($key)
329
+ {
330
+ return isset($_GET[$key]) ? $_GET[$key] : null;
331
+ }
332
+ }
vendor/facebook/php-sdk-v4/src/Facebook/Helpers/FacebookSignedRequestFromInputHelper.php ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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\Helpers;
25
+
26
+ use Facebook\Facebook;
27
+ use Facebook\FacebookApp;
28
+ use Facebook\FacebookClient;
29
+ use Facebook\SignedRequest;
30
+ use Facebook\Authentication\AccessToken;
31
+ use Facebook\Authentication\OAuth2Client;
32
+
33
+ /**
34
+ * Class FacebookSignedRequestFromInputHelper
35
+ *
36
+ * @package Facebook
37
+ */
38
+ abstract class FacebookSignedRequestFromInputHelper
39
+ {
40
+ /**
41
+ * @var SignedRequest|null The SignedRequest entity.
42
+ */
43
+ protected $signedRequest;
44
+
45
+ /**
46
+ * @var FacebookApp The FacebookApp entity.
47
+ */
48
+ protected $app;
49
+
50
+ /**
51
+ * @var OAuth2Client The OAuth 2.0 client service.
52
+ */
53
+ protected $oAuth2Client;
54
+
55
+ /**
56
+ * Initialize the helper and process available signed request data.
57
+ *
58
+ * @param FacebookApp $app The FacebookApp entity.
59
+ * @param FacebookClient $client The client to make HTTP requests.
60
+ * @param string|null $graphVersion The version of Graph to use.
61
+ */
62
+ public function __construct(FacebookApp $app, FacebookClient $client, $graphVersion = null)
63
+ {
64
+ $this->app = $app;
65
+ $graphVersion = $graphVersion ?: Facebook::DEFAULT_GRAPH_VERSION;
66
+ $this->oAuth2Client = new OAuth2Client($this->app, $client, $graphVersion);
67
+
68
+ $this->instantiateSignedRequest();
69
+ }
70
+
71
+ /**
72
+ * Instantiates a new SignedRequest entity.
73
+ *
74
+ * @param string|null
75
+ */
76
+ public function instantiateSignedRequest($rawSignedRequest = null)
77
+ {
78
+ $rawSignedRequest = $rawSignedRequest ?: $this->getRawSignedRequest();
79
+
80
+ if (!$rawSignedRequest) {
81
+ return;
82
+ }
83
+
84
+ $this->signedRequest = new SignedRequest($this->app, $rawSignedRequest);
85
+ }
86
+
87
+ /**
88
+ * Returns an AccessToken entity from the signed request.
89
+ *
90
+ * @return AccessToken|null
91
+ *
92
+ * @throws \Facebook\Exceptions\FacebookSDKException
93
+ */
94
+ public function getAccessToken()
95
+ {
96
+ if ($this->signedRequest && $this->signedRequest->hasOAuthData()) {
97
+ $code = $this->signedRequest->get('code');
98
+ $accessToken = $this->signedRequest->get('oauth_token');
99
+
100
+ if ($code && !$accessToken) {
101
+ return $this->oAuth2Client->getAccessTokenFromCode($code);
102
+ }
103
+
104
+ $expiresAt = $this->signedRequest->get('expires', 0);
105
+
106
+ return new AccessToken($accessToken, $expiresAt);
107
+ }
108
+
109
+ return null;
110
+ }
111
+
112
+ /**
113
+ * Returns the SignedRequest entity.
114
+ *
115
+ * @return SignedRequest|null
116
+ */
117
+ public function getSignedRequest()
118
+ {
119
+ return $this->signedRequest;
120
+ }
121
+
122
+ /**
123
+ * Returns the user_id if available.
124
+ *
125
+ * @return string|null
126
+ */
127
+ public function getUserId()
128
+ {
129
+ return $this->signedRequest ? $this->signedRequest->getUserId() : null;
130
+ }
131
+
132
+ /**
133
+ * Get raw signed request from input.
134
+ *
135
+ * @return string|null
136
+ */
137
+ abstract public function getRawSignedRequest();
138
+
139
+ /**
140
+ * Get raw signed request from POST input.
141
+ *
142
+ * @return string|null
143
+ */
144
+ public function getRawSignedRequestFromPost()
145
+ {
146
+ if (isset($_POST['signed_request'])) {
147
+ return $_POST['signed_request'];
148
+ }
149
+
150
+ return null;
151
+ }
152
+
153
+ /**
154
+ * Get raw signed request from cookie set from the Javascript SDK.
155
+ *
156
+ * @return string|null
157
+ */
158
+ public function getRawSignedRequestFromCookie()
159
+ {
160
+ if (isset($_COOKIE['fbsr_' . $this->app->getId()])) {
161
+ return $_COOKIE['fbsr_' . $this->app->getId()];
162
+ }
163
+
164
+ return null;
165
+ }
166
+ }
vendor/facebook/php-sdk-v4/src/Facebook/Http/GraphRawResponse.php ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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\Http;
25
+
26
+ /**
27
+ * Class GraphRawResponse
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class GraphRawResponse
32
+ {
33
+ /**
34
+ * @var array The response headers in the form of an associative array.
35
+ */
36
+ protected $headers;
37
+
38
+ /**
39
+ * @var string The raw response body.
40
+ */
41
+ protected $body;
42
+
43
+ /**
44
+ * @var int The HTTP status response code.
45
+ */
46
+ protected $httpResponseCode;
47
+
48
+ /**
49
+ * Creates a new GraphRawResponse entity.
50
+ *
51
+ * @param string|array $headers The headers as a raw string or array.
52
+ * @param string $body The raw response body.
53
+ * @param int $httpStatusCode The HTTP response code (if sending headers as parsed array).
54
+ */
55
+ public function __construct($headers, $body, $httpStatusCode = null)
56
+ {
57
+ if (is_numeric($httpStatusCode)) {
58
+ $this->httpResponseCode = (int)$httpStatusCode;
59
+ }
60
+
61
+ if (is_array($headers)) {
62
+ $this->headers = $headers;
63
+ } else {
64
+ $this->setHeadersFromString($headers);
65
+ }
66
+
67
+ $this->body = $body;
68
+ }
69
+
70
+ /**
71
+ * Return the response headers.
72
+ *
73
+ * @return array
74
+ */
75
+ public function getHeaders()
76
+ {
77
+ return $this->headers;
78
+ }
79
+
80
+ /**
81
+ * Return the body of the response.
82
+ *
83
+ * @return string
84
+ */
85
+ public function getBody()
86
+ {
87
+ return $this->body;
88
+ }
89
+
90
+ /**
91
+ * Return the HTTP response code.
92
+ *
93
+ * @return int
94
+ */
95
+ public function getHttpResponseCode()
96
+ {
97
+ return $this->httpResponseCode;
98
+ }
99
+
100
+ /**
101
+ * Sets the HTTP response code from a raw header.
102
+ *
103
+ * @param string $rawResponseHeader
104
+ */
105
+ public function setHttpResponseCodeFromHeader($rawResponseHeader)
106
+ {
107
+ preg_match('|HTTP/\d\.\d\s+(\d+)\s+.*|', $rawResponseHeader, $match);
108
+ $this->httpResponseCode = (int)$match[1];
109
+ }
110
+
111
+ /**
112
+ * Parse the raw headers and set as an array.
113
+ *
114
+ * @param string $rawHeaders The raw headers from the response.
115
+ */
116
+ protected function setHeadersFromString($rawHeaders)
117
+ {
118
+ // Normalize line breaks
119
+ $rawHeaders = str_replace("\r\n", "\n", $rawHeaders);
120
+
121
+ // There will be multiple headers if a 301 was followed
122
+ // or a proxy was followed, etc
123
+ $headerCollection = explode("\n\n", trim($rawHeaders));
124
+ // We just want the last response (at the end)
125
+ $rawHeader = array_pop($headerCollection);
126
+
127
+ $headerComponents = explode("\n", $rawHeader);
128
+ foreach ($headerComponents as $line) {
129
+ if (strpos($line, ': ') === false) {
130
+ $this->setHttpResponseCodeFromHeader($line);
131
+ } else {
132
+ list($key, $value) = explode(': ', $line);
133
+ $this->headers[$key] = $value;
134
+ }
135
+ }
136
+ }
137
+ }
vendor/facebook/php-sdk-v4/src/Facebook/Http/RequestBodyInterface.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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\Http;
25
+
26
+ /**
27
+ * Interface
28
+ *
29
+ * @package Facebook
30
+ */
31
+ interface RequestBodyInterface
32
+ {
33
+ /**
34
+ * Get the body of the request to send to Graph.
35
+ *
36
+ * @return string
37
+ */
38
+ public function getBody();
39
+ }
vendor/facebook/php-sdk-v4/src/Facebook/Http/RequestBodyMultipart.php ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 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\Http;
25
+
26
+ use Facebook\FileUpload\FacebookFile;
27
+
28
+ /**
29
+ * Class RequestBodyMultipartt
30
+ *
31
+ * Some things copied from Guzzle
32
+ *
33
+ * @package Facebook
34
+ *
35
+ * @see https://github.com/guzzle/guzzle/blob/master/src/Post/MultipartBody.php
36
+ */
37
+ class RequestBodyMultipart implements RequestBodyInterface
38
+ {
39
+ /**
40
+ * @var string The boundary.
41
+ */
42
+ private $boundary;
43
+
44
+ /**
45
+ * @var array The parameters to send with this request.
46
+ */
47
+ private $params;
48
+
49
+ /**
50
+ * @var array The files to send with this request.
51
+ */
52
+ private $files = [];
53
+
54
+ /**
55
+ * @param array $params The parameters to send with this request.
56
+ * @param array $files The files to send with this request.
57
+ * @param string $boundary Provide a specific boundary.
58
+ */
59
+ public function __construct(array $params = [], array $files = [], $boundary = null)
60
+ {
61
+ $this->params = $params;
62
+ $this->files = $files;
63
+ $this->boundary = $boundary ?: uniqid();
64
+ }
65
+
66
+ /**
67
+ * @inheritdoc
68
+ */
69
+ public function getBody()
70
+ {
71
+ $body = '';
72
+
73
+ // Compile normal params
74
+ $params = $this->getNestedParams($this->params);
75
+ foreach ($params as $k => $v) {
76
+ $body .= $this->getParamString($k, $v);
77
+ }
78
+
79
+ // Compile files
80
+ foreach ($this->files as $k => $v) {
81
+ $body .= $this->getFileString($k, $v);
82
+ }
83
+
84
+ // Peace out
85
+ $body .= "--{$this->boundary}--\r\n";
86
+
87
+ return $body;
88
+ }
89
+
90
+ /**
91
+ * Get the boundary
92
+ *
93
+ * @return string
94
+