Version Description
- New on-boarding flow wizard
- Automattic URL claiming
- Submit for review from wizard
- Improved transformation rules
- Option to submit only articles without warnings
- Jetpack compatibility
- Added Jetpack carousel rules
- Compatibility layer for Get The Image plugin
- Fix for relative URL checking
- Fix for missing subtitles
- Fix for double call of wpautop
- Fix for loadHTML warnings
- Fix for get_cover_media function
- Fix to prevent publishing of password protected posts
props diegoquinteiro everton-rosario gemedet jacobarriola menzow rinatkhaziev srtfisher
Download this release
Release Info
Developer | philipjohn |
Plugin | Instant Articles for WP |
Version | 3.1 |
Comparing to | |
See all releases |
Code changes from version 3.0.1 to 3.1
- README.md +46 -0
- assets/banner-1544x500.jpg +0 -0
- assets/banner-772x250.jpg +0 -0
- assets/check@2x.png +0 -0
- assets/connect@2x.png +0 -0
- assets/customize@2x.png +0 -0
- assets/icon-128x128.jpg +0 -0
- assets/icon-256x256.jpg +0 -0
- assets/icon-fb-login.png +0 -0
- assets/key@2x.png +0 -0
- assets/pencil.png +0 -0
- assets/screenshot-1.png +0 -0
- class-instant-articles-post.php +49 -35
- class-instant-articles-publisher.php +22 -3
- compat.php +12 -0
- compat/class-instant-articles-get-the-image.php +27 -0
- compat/class-instant-articles-jetpack.php +10 -0
- compat/get-the-image-rules-configuration.json +13 -0
- compat/jetpack-rules-configuration.json +91 -0
- css/instant-articles-wizard.css +417 -0
- facebook-instant-articles.php +34 -11
- js/instant-articles-settings.js +1 -18
- js/instant-articles-wizard.js +136 -0
- meta-box/class-instant-articles-meta-box.php +2 -2
- readme.txt +19 -1
- rules-configuration.json +157 -32
- vendor/autoload.php +1 -1
- vendor/composer/autoload_real.php +7 -7
- vendor/composer/autoload_static.php +4 -4
- vendor/composer/installed.json +17 -16
- vendor/facebook/facebook-instant-articles-sdk-php/.gitignore +0 -4
- vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Client/Client.php +38 -0
- vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Client/Helper.php +1 -1
- vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/InstantArticle.php +45 -1
- vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Interactive.php +1 -1
- vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Parser/instant-articles-rules.json +16 -0
- vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Getters/GetterFactory.php +3 -0
- vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Getters/JSONGetter.php +63 -0
- vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/Compat/JetpackSlideshowRule.php +77 -0
- vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/ConfigurationSelectorRule.php +1 -1
- vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/H1Rule.php +1 -1
- vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/H2Rule.php +1 -1
- vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/ImageRule.php +20 -1
- vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/InteractiveInsideParagraphRule.php +119 -0
- vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/InteractiveRule.php +1 -1
- vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/Rule.php +2 -3
- vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Warnings/validator_warning_messages.ini +1 -1
- vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Client/ClientTest.php +193 -0
- vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Client/HelperTest.php +1 -1
- vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/InteractiveTest.php +49 -27
- vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/CMS/WPTransformerTest.php +3 -2
- vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/CMS/wp-ia.xml +116 -1
- vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/CMS/wp-rules.json +325 -12
- vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/CMS/wp.html +132 -11
- vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/Example/simple-ia.html +5 -0
- vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/Example/simple.html +3 -0
- vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/TransformerTest.php +1 -1
- vendor/facebook/php-sdk-v4/src/Facebook/Facebook.php +2 -2
- vendor/facebook/php-sdk-v4/src/Facebook/FacebookResponse.php +1 -1
- vendor/facebook/php-sdk-v4/src/Facebook/Helpers/FacebookRedirectLoginHelper.php +10 -1
- vendor/facebook/php-sdk-v4/src/Facebook/PseudoRandomString/PseudoRandomStringGeneratorTrait.php +0 -1
- vendor/facebook/php-sdk-v4/src/Facebook/Url/FacebookUrlDetectionHandler.php +2 -1
- vendor/facebook/php-sdk-v4/src/Facebook/autoload.php +2 -0
- wizard/class-instant-articles-invalid-wizard-transition-exception.php +19 -0
- wizard/class-instant-articles-option-ads.php +245 -0
- wizard/class-instant-articles-option-analytics.php +144 -0
- wizard/class-instant-articles-option-fb-app.php +65 -0
- wizard/class-instant-articles-option-fb-page.php +77 -0
- wizard/class-instant-articles-option-publishing.php +121 -0
- wizard/class-instant-articles-option-styles.php +45 -0
- wizard/class-instant-articles-option.php +490 -0
- wizard/class-instant-articles-wizard-fb-helper.php +212 -0
- wizard/class-instant-articles-wizard-review-submission.php +96 -0
- wizard/class-instant-articles-wizard-state.php +352 -0
- wizard/class-instant-articles-wizard.php +295 -0
- wizard/state_machine.txt +26 -0
- wizard/templates/advanced-template.php +31 -0
- wizard/templates/all-steps-wizard.php +288 -0
- wizard/templates/app-setup-template.php +115 -0
- wizard/templates/overview-template.php +43 -0
- wizard/templates/page-selection-template.php +63 -0
- wizard/templates/review-submission-template.php +156 -0
- wizard/templates/style-selection-template.php +66 -0
- wizard/templates/wizard-template.php +112 -0
README.md
CHANGED
@@ -1,7 +1,12 @@
|
|
|
|
|
|
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.
|
@@ -62,3 +67,44 @@ By default it is set to `instant-articles` which usually will give you a feed UR
|
|
62 |
**How do I flush the rewrite rules after changing the feed slug?**
|
63 |
|
64 |
Usually simply visiting the permalinks settings page in the WordPress dashboard will do the trick (/wp-admin/options-permalink.php)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
[![Build Status](https://travis-ci.org/Automattic/facebook-instant-articles-wp.svg?branch=master)](https://travis-ci.org/Automattic/facebook-instant-articles-wp)
|
2 |
+
|
3 |
# Instant Articles for WP
|
4 |
|
5 |
Enable [Instant Articles for Facebook](https://developers.facebook.com/docs/instant-articles) on your WordPress site.
|
6 |
|
7 |
+
## Plugin activity
|
8 |
+
[![Throughput Graph](https://graphs.waffle.io/Automattic/facebook-instant-articles-wp/throughput.svg)](https://waffle.io/Automattic/facebook-instant-articles-wp/metrics/throughput)
|
9 |
+
|
10 |
## Description
|
11 |
|
12 |
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.
|
67 |
**How do I flush the rewrite rules after changing the feed slug?**
|
68 |
|
69 |
Usually simply visiting the permalinks settings page in the WordPress dashboard will do the trick (/wp-admin/options-permalink.php)
|
70 |
+
|
71 |
+
## Development Environment
|
72 |
+
You are more than welcome to help us to make this plugin even better!
|
73 |
+
|
74 |
+
### Setup SDK and WP to use the Github code
|
75 |
+
Most of development and debugging we use the master or any feature branch for the development of WP plugin.
|
76 |
+
Sometimes it needs specific or newest version of the SDK to match all the new features that are release candidates to every new release of SDK and WP plugin.
|
77 |
+
|
78 |
+
The SDK is also under development @ GitHub: <https://github.com/facebook/facebook-instant-articles-sdk-php>
|
79 |
+
|
80 |
+
#### Pre-requisites
|
81 |
+
- Have PHP installed (you can install with homebrew)
|
82 |
+
- Have WebServer installed (you can use MAMP)
|
83 |
+
- Have WP installed (downloading from wordpress.org)
|
84 |
+
|
85 |
+
#### Setup
|
86 |
+
Clone both repositories into your developer folder (ex: ~/instant-articles).
|
87 |
+
```
|
88 |
+
git clone git@github.com:Automattic/facebook-instant-articles-wp.git
|
89 |
+
git clone git@github.com:facebook/facebook-instant-articles-sdk-php.git
|
90 |
+
```
|
91 |
+
|
92 |
+
Build both source folders:
|
93 |
+
```
|
94 |
+
cd facebook-instant-articles-sdk-php
|
95 |
+
composer install
|
96 |
+
|
97 |
+
cd ../facebook-instant-articles-wp
|
98 |
+
composer install
|
99 |
+
```
|
100 |
+
|
101 |
+
Now remove the build from your WordPress, so it will include the code you've just built.
|
102 |
+
```
|
103 |
+
rm -rf vendor/facebook/facebook-instant-articles-sdk-php
|
104 |
+
ln -s ~/facebook-instant-articles-sdk-php vendor/facebook/facebook-instant-articles-sdk-php
|
105 |
+
```
|
106 |
+
|
107 |
+
and now you can create a link inside your /wp-content/plugins to your folder
|
108 |
+
```
|
109 |
+
ln -s ~/facebook-instant-articles-wp wp-content/plugins/facebook-instant-articles-wp
|
110 |
+
```
|
assets/banner-1544x500.jpg
ADDED
Binary file
|
assets/banner-772x250.jpg
ADDED
Binary file
|
assets/check@2x.png
ADDED
Binary file
|
assets/connect@2x.png
ADDED
Binary file
|
assets/customize@2x.png
ADDED
Binary file
|
assets/icon-128x128.jpg
ADDED
Binary file
|
assets/icon-256x256.jpg
ADDED
Binary file
|
assets/icon-fb-login.png
ADDED
Binary file
|
assets/key@2x.png
ADDED
Binary file
|
assets/pencil.png
ADDED
Binary file
|
assets/screenshot-1.png
ADDED
Binary file
|
class-instant-articles-post.php
CHANGED
@@ -14,6 +14,7 @@ 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;
|
@@ -84,6 +85,14 @@ class Instant_Articles_Post {
|
|
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 |
*
|
@@ -244,12 +253,12 @@ class Instant_Articles_Post {
|
|
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 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
} else {
|
252 |
-
|
253 |
}
|
254 |
|
255 |
return $url;
|
@@ -311,6 +320,11 @@ class Instant_Articles_Post {
|
|
311 |
* @since 0.1
|
312 |
* @param string $content The current post content.
|
313 |
*/
|
|
|
|
|
|
|
|
|
|
|
314 |
$content = apply_filters( 'the_content', $content );
|
315 |
|
316 |
// Maybe cleanup some globals after us?
|
@@ -319,15 +333,12 @@ class Instant_Articles_Post {
|
|
319 |
wp_reset_postdata();
|
320 |
}
|
321 |
|
322 |
-
// Some people choose to disable wpautop. Due to the Instant Articles spec, we really want it in!
|
323 |
-
$content = wpautop( $content );
|
324 |
-
|
325 |
// Remove hyperlinks beginning with a # as they cause errors on Facebook (from http://wordpress.stackexchange.com/a/227332/19528)
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
/**
|
332 |
* Filter the post content for Instant Articles.
|
333 |
*
|
@@ -481,12 +492,12 @@ class Instant_Articles_Post {
|
|
481 |
* Get the cover media.
|
482 |
*
|
483 |
* @since 0.1
|
484 |
-
* @return
|
485 |
*/
|
486 |
public function get_cover_media() {
|
487 |
|
488 |
-
$cover_media =
|
489 |
-
|
490 |
|
491 |
// If someone else is handling this, let them. Otherwise fall back to us trying to use the featured image.
|
492 |
if ( has_filter( 'instant_articles_cover_media' ) ) {
|
@@ -494,16 +505,18 @@ class Instant_Articles_Post {
|
|
494 |
* Filter the cover media.
|
495 |
*
|
496 |
* @since 0.1
|
497 |
-
* @param
|
498 |
* @param int $post_id The current post ID.
|
499 |
*/
|
500 |
$cover_media = apply_filters( 'instant_articles_cover_media', $cover_media, $this->_post->ID );
|
501 |
} else {
|
|
|
502 |
$featured_image_data = $this->get_the_featured_image();
|
503 |
if ( isset( $featured_image_data['src'] ) && strlen( $featured_image_data['src'] ) ) {
|
504 |
-
$cover_media
|
505 |
-
$
|
506 |
-
|
|
|
507 |
}
|
508 |
}
|
509 |
|
@@ -574,11 +587,11 @@ class Instant_Articles_Post {
|
|
574 |
public function to_instant_article() {
|
575 |
|
576 |
/**
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
do_action( 'instant_articles_before_transform_post', $this );
|
583 |
|
584 |
// Get time zone configured in WordPress. Default to UTC if no time zone configured.
|
@@ -621,10 +634,16 @@ class Instant_Articles_Post {
|
|
621 |
$title = $this->get_the_title();
|
622 |
if ( $title ) {
|
623 |
$document = new DOMDocument();
|
|
|
624 |
$document->loadHTML( '<?xml encoding="' . $blog_charset . '" ?><h1>' . $title . '</h1>' );
|
|
|
625 |
$transformer->transform( $header, $document );
|
626 |
}
|
627 |
|
|
|
|
|
|
|
|
|
628 |
$authors = $this->get_the_authors();
|
629 |
foreach ( $authors as $author ) {
|
630 |
$author_obj = Author::create();
|
@@ -643,17 +662,12 @@ class Instant_Articles_Post {
|
|
643 |
if ( $kicker ) {
|
644 |
$header->withKicker( $kicker );
|
645 |
}
|
646 |
-
$cover = $this->get_the_featured_image();
|
647 |
-
if ( $cover['src'] ) {
|
648 |
-
$image = Image::create()->withURL( $cover['src'] );
|
649 |
-
if ( isset( $cover['caption'] ) && strlen( $cover['caption'] ) > 0 ) {
|
650 |
-
$document = new DOMDocument();
|
651 |
-
$document->loadHTML( '<?xml encoding="' . $blog_charset . '" ?><h1>' . $cover['caption'] . '</h1>' );
|
652 |
-
$image->withCaption( $transformer->transform( Caption::create(), $document ) );
|
653 |
-
}
|
654 |
|
655 |
-
|
|
|
|
|
656 |
}
|
|
|
657 |
$this->instant_article =
|
658 |
InstantArticle::create()
|
659 |
->withCanonicalUrl( $this->get_canonical_url() )
|
@@ -687,7 +701,7 @@ class Instant_Articles_Post {
|
|
687 |
foreach ( $scripts as $script ){
|
688 |
$src = $script->getAttribute( 'src' );
|
689 |
$explode_src = parse_url( $src );
|
690 |
-
if ( is_array( $explode_src ) && empty( $explode_src['scheme'] ) ) {
|
691 |
$src = 'https://' . $explode_src['host'] . $explode_src['path'];
|
692 |
}
|
693 |
$script->setAttribute( 'src' , $src );
|
14 |
use Facebook\InstantArticles\Elements\Analytics;
|
15 |
use Facebook\InstantArticles\Elements\Author;
|
16 |
use Facebook\InstantArticles\Elements\Image;
|
17 |
+
use Facebook\InstantArticles\Elements\Video;
|
18 |
use Facebook\InstantArticles\Elements\Caption;
|
19 |
use Facebook\InstantArticles\Elements\Footer;
|
20 |
use Facebook\InstantArticles\Transformer\Transformer;
|
85 |
public function get_the_title() {
|
86 |
$title = $this->_post->post_title;
|
87 |
|
88 |
+
/**
|
89 |
+
* Apply the default filter 'the_title' for the post tite.
|
90 |
+
*
|
91 |
+
* @since 3.1
|
92 |
+
* @param string $title The current post title.
|
93 |
+
*/
|
94 |
+
$title = apply_filters( 'the_title', $title);
|
95 |
+
|
96 |
/**
|
97 |
* Filter the post title for use in instant articles.
|
98 |
*
|
253 |
// If post is draft, clone it to get the eventual permalink,
|
254 |
// see http://wordpress.stackexchange.com/a/42988.
|
255 |
if ( in_array( $this->_post->post_status, array( 'draft', 'pending', 'auto-draft' ), true ) ) {
|
256 |
+
$post_clone = clone $this->_post;
|
257 |
+
$post_clone->post_status = 'published';
|
258 |
+
$post_clone->post_name = sanitize_title( $post_clone->post_name ? $post_clone->post_name : $post_clone->post_title, $post_clone->ID );
|
259 |
+
$url = get_permalink( $post_clone );
|
260 |
} else {
|
261 |
+
$url = get_permalink( $this->_post );
|
262 |
}
|
263 |
|
264 |
return $url;
|
320 |
* @since 0.1
|
321 |
* @param string $content The current post content.
|
322 |
*/
|
323 |
+
|
324 |
+
// Some people choose to disable wpautop. Due to the Instant Articles spec, we really want it in!
|
325 |
+
if ( ! has_filter( 'the_content', 'wpautop' ) )
|
326 |
+
add_filter( 'the_content', 'wpautop' );
|
327 |
+
|
328 |
$content = apply_filters( 'the_content', $content );
|
329 |
|
330 |
// Maybe cleanup some globals after us?
|
333 |
wp_reset_postdata();
|
334 |
}
|
335 |
|
|
|
|
|
|
|
336 |
// Remove hyperlinks beginning with a # as they cause errors on Facebook (from http://wordpress.stackexchange.com/a/227332/19528)
|
337 |
+
preg_match_all( '!<a[^>]*? href=[\'"]#[^<]+</a>!i', $content, $matches );
|
338 |
+
foreach ( $matches[0] as $link ) {
|
339 |
+
$content = str_replace( $link, strip_tags($link), $content );
|
340 |
+
}
|
341 |
+
|
342 |
/**
|
343 |
* Filter the post content for Instant Articles.
|
344 |
*
|
492 |
* Get the cover media.
|
493 |
*
|
494 |
* @since 0.1
|
495 |
+
* @return Image|Video
|
496 |
*/
|
497 |
public function get_cover_media() {
|
498 |
|
499 |
+
$cover_media = Image::create();
|
500 |
+
|
501 |
|
502 |
// If someone else is handling this, let them. Otherwise fall back to us trying to use the featured image.
|
503 |
if ( has_filter( 'instant_articles_cover_media' ) ) {
|
505 |
* Filter the cover media.
|
506 |
*
|
507 |
* @since 0.1
|
508 |
+
* @param Image $cover_media The cover media object.
|
509 |
* @param int $post_id The current post ID.
|
510 |
*/
|
511 |
$cover_media = apply_filters( 'instant_articles_cover_media', $cover_media, $this->_post->ID );
|
512 |
} else {
|
513 |
+
|
514 |
$featured_image_data = $this->get_the_featured_image();
|
515 |
if ( isset( $featured_image_data['src'] ) && strlen( $featured_image_data['src'] ) ) {
|
516 |
+
$cover_media = Image::create()->withURL($featured_image_data['src']);
|
517 |
+
if( isset( $featured_image_data['caption'] ) && strlen( $featured_image_data['caption'] )) {
|
518 |
+
$cover_media->withCaption(Caption::create()->withTitle($featured_image_data['caption']));
|
519 |
+
}
|
520 |
}
|
521 |
}
|
522 |
|
587 |
public function to_instant_article() {
|
588 |
|
589 |
/**
|
590 |
+
* Fires before the instant article is rendered.
|
591 |
+
*
|
592 |
+
* @since 0.1
|
593 |
+
* @param Instant_Article_Post $instant_article_post The instant article post.
|
594 |
+
*/
|
595 |
do_action( 'instant_articles_before_transform_post', $this );
|
596 |
|
597 |
// Get time zone configured in WordPress. Default to UTC if no time zone configured.
|
634 |
$title = $this->get_the_title();
|
635 |
if ( $title ) {
|
636 |
$document = new DOMDocument();
|
637 |
+
libxml_use_internal_errors(true);
|
638 |
$document->loadHTML( '<?xml encoding="' . $blog_charset . '" ?><h1>' . $title . '</h1>' );
|
639 |
+
libxml_use_internal_errors(false);
|
640 |
$transformer->transform( $header, $document );
|
641 |
}
|
642 |
|
643 |
+
if ( $this->has_subtitle() ) {
|
644 |
+
$header->withSubTitle ( $this->get_the_subtitle() ) ;
|
645 |
+
}
|
646 |
+
|
647 |
$authors = $this->get_the_authors();
|
648 |
foreach ( $authors as $author ) {
|
649 |
$author_obj = Author::create();
|
662 |
if ( $kicker ) {
|
663 |
$header->withKicker( $kicker );
|
664 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
665 |
|
666 |
+
$cover = $this->get_cover_media();
|
667 |
+
if ( $cover->getUrl() ) {
|
668 |
+
$header->withCover( $cover );
|
669 |
}
|
670 |
+
|
671 |
$this->instant_article =
|
672 |
InstantArticle::create()
|
673 |
->withCanonicalUrl( $this->get_canonical_url() )
|
701 |
foreach ( $scripts as $script ){
|
702 |
$src = $script->getAttribute( 'src' );
|
703 |
$explode_src = parse_url( $src );
|
704 |
+
if ( is_array( $explode_src ) && empty( $explode_src['scheme'] ) && ! empty( $explode_src['host'] ) && ! empty( $explode_src['path'] ) ) {
|
705 |
$src = 'https://' . $explode_src['host'] . $explode_src['path'];
|
706 |
}
|
707 |
$script->setAttribute( 'src' , $src );
|
class-instant-articles-publisher.php
CHANGED
@@ -89,16 +89,35 @@ class Instant_Articles_Publisher {
|
|
89 |
$dev_mode
|
90 |
);
|
91 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
92 |
if ( $dev_mode ) {
|
93 |
-
$
|
94 |
} else {
|
95 |
// Any publish status other than 'publish' means draft for the Instant Article.
|
96 |
-
$
|
97 |
}
|
98 |
|
99 |
try {
|
100 |
// Import the article.
|
101 |
-
$submission_id = $client->importArticle( $article, $
|
102 |
update_post_meta( $post_id, self::SUBMISSION_ID_KEY, $submission_id );
|
103 |
} catch ( Exception $e ) {
|
104 |
// Try without taking live for pages not yet reviewed.
|
89 |
$dev_mode
|
90 |
);
|
91 |
|
92 |
+
// Don't publish posts with password protection
|
93 |
+
if ( post_password_required( $post ) ) {
|
94 |
+
// Unpublishes if already published and from now on it started to have password protection
|
95 |
+
$client->removeArticle( $article->getCanonicalURL() );
|
96 |
+
delete_post_meta( $post_id, self::SUBMISSION_ID_KEY );
|
97 |
+
return;
|
98 |
+
}
|
99 |
+
|
100 |
+
// Don't process if contains warnings and blocker flag for transformation warnings is turned on.
|
101 |
+
if ( count( $adapter->transformer->getWarnings() ) > 0
|
102 |
+
&& isset( $publishing_settings['block_publish_with_warnings'] )
|
103 |
+
&& $publishing_settings['block_publish_with_warnings'] ) {
|
104 |
+
|
105 |
+
// Unpublishes if already published
|
106 |
+
$client->removeArticle( $article->getCanonicalURL() );
|
107 |
+
delete_post_meta( $post_id, self::SUBMISSION_ID_KEY );
|
108 |
+
return;
|
109 |
+
}
|
110 |
+
|
111 |
if ( $dev_mode ) {
|
112 |
+
$published = false;
|
113 |
} else {
|
114 |
// Any publish status other than 'publish' means draft for the Instant Article.
|
115 |
+
$published = true;
|
116 |
}
|
117 |
|
118 |
try {
|
119 |
// Import the article.
|
120 |
+
$submission_id = $client->importArticle( $article, $published );
|
121 |
update_post_meta( $post_id, self::SUBMISSION_ID_KEY, $submission_id );
|
122 |
} catch ( Exception $e ) {
|
123 |
// Try without taking live for pages not yet reviewed.
|
compat.php
CHANGED
@@ -7,6 +7,11 @@
|
|
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' );
|
@@ -34,3 +39,10 @@ if ( defined( 'JETPACK__VERSION' ) ) {
|
|
34 |
$jp = new Instant_Articles_Jetpack;
|
35 |
$jp->init();
|
36 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
* @package default
|
8 |
*/
|
9 |
|
10 |
+
if ( !function_exists( 'is_plugin_active' ) ) {
|
11 |
+
require_once ( ABSPATH . '/wp-admin/includes/plugin.php' );
|
12 |
+
}
|
13 |
+
|
14 |
+
|
15 |
// Load compat layer for Co-Authors Plus.
|
16 |
if ( function_exists( 'get_coauthors' ) && ! defined( 'CAP_IA_COMPAT' ) ) {
|
17 |
include( dirname( __FILE__ ) . '/compat/class-instant-articles-co-authors-plus.php' );
|
39 |
$jp = new Instant_Articles_Jetpack;
|
40 |
$jp->init();
|
41 |
}
|
42 |
+
|
43 |
+
// Load support for Get The Image plugin
|
44 |
+
if ( is_plugin_active( 'get-the-image/get-the-image.php' ) ) {
|
45 |
+
include( dirname( __FILE__ ) . '/compat/class-instant-articles-get-the-image.php' );
|
46 |
+
$gti = new Instant_Articles_Get_The_Image;
|
47 |
+
$gti->init();
|
48 |
+
}
|
compat/class-instant-articles-get-the-image.php
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Support class for Get The Image plugin
|
5 |
+
*
|
6 |
+
* @since 3.0.2+
|
7 |
+
*
|
8 |
+
*/
|
9 |
+
class Instant_Articles_Get_The_Image {
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Init the compat layer
|
13 |
+
*
|
14 |
+
*/
|
15 |
+
function init() {
|
16 |
+
add_filter( 'instant_articles_transformer_rules_loaded', array( 'Instant_Articles_Get_The_Image', 'transformer_loaded' ) );
|
17 |
+
}
|
18 |
+
|
19 |
+
public static function transformer_loaded( $transformer ) {
|
20 |
+
// Appends more rules to transformer
|
21 |
+
$file_path = plugin_dir_path( __FILE__ ) . 'get-the-image-rules-configuration.json';
|
22 |
+
$configuration = file_get_contents( $file_path );
|
23 |
+
$transformer->loadRules( $configuration );
|
24 |
+
|
25 |
+
return $transformer;
|
26 |
+
}
|
27 |
+
}
|
compat/class-instant-articles-jetpack.php
CHANGED
@@ -15,6 +15,7 @@ class Instant_Articles_Jetpack {
|
|
15 |
function init() {
|
16 |
$this->_fix_youtube_embed();
|
17 |
$this->_fix_facebook_embed();
|
|
|
18 |
}
|
19 |
|
20 |
/**
|
@@ -80,4 +81,13 @@ class Instant_Articles_Jetpack {
|
|
80 |
|
81 |
return '<figure class="op-social"><iframe><script src="https://connect.facebook.net/' . $locale . '/sdk.js#xfbml=1&version=v2.6" async></script><div class="fb-post" data-href="' . esc_url( $url ) . '"></div></iframe></figure>';
|
82 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
83 |
}
|
15 |
function init() {
|
16 |
$this->_fix_youtube_embed();
|
17 |
$this->_fix_facebook_embed();
|
18 |
+
add_filter( 'instant_articles_transformer_rules_loaded', array( 'Instant_Articles_Jetpack', 'transformer_loaded' ) );
|
19 |
}
|
20 |
|
21 |
/**
|
81 |
|
82 |
return '<figure class="op-social"><iframe><script src="https://connect.facebook.net/' . $locale . '/sdk.js#xfbml=1&version=v2.6" async></script><div class="fb-post" data-href="' . esc_url( $url ) . '"></div></iframe></figure>';
|
83 |
}
|
84 |
+
|
85 |
+
public static function transformer_loaded( $transformer ) {
|
86 |
+
// Appends more rules to transformer
|
87 |
+
$file_path = plugin_dir_path( __FILE__ ) . 'jetpack-rules-configuration.json';
|
88 |
+
$configuration = file_get_contents( $file_path );
|
89 |
+
$transformer->loadRules( $configuration );
|
90 |
+
|
91 |
+
return $transformer;
|
92 |
+
}
|
93 |
}
|
compat/get-the-image-rules-configuration.json
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"rules": [{
|
3 |
+
"class": "ImageInsideParagraphRule",
|
4 |
+
"selector": "figure.wp-caption",
|
5 |
+
"properties": {
|
6 |
+
"image.url": {
|
7 |
+
"type": "string",
|
8 |
+
"selector": "img",
|
9 |
+
"attribute": "src"
|
10 |
+
}
|
11 |
+
}
|
12 |
+
}]
|
13 |
+
}
|
compat/jetpack-rules-configuration.json
ADDED
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"rules": [{
|
3 |
+
"class" : "IgnoreRule",
|
4 |
+
"selector" : "p.jetpack-slideshow-noscript"
|
5 |
+
},
|
6 |
+
{
|
7 |
+
"class": "CaptionRule",
|
8 |
+
"selector" : "div.wp-caption-text"
|
9 |
+
},
|
10 |
+
{
|
11 |
+
"class" : "PassThroughRule",
|
12 |
+
"selector" : "div.gallery-row"
|
13 |
+
},
|
14 |
+
{
|
15 |
+
"class" : "PassThroughRule",
|
16 |
+
"selector" : "div.tiled-gallery p"
|
17 |
+
},
|
18 |
+
{
|
19 |
+
"class" : "PassThroughRule",
|
20 |
+
"selector" : "div.gallery-row p"
|
21 |
+
},
|
22 |
+
{
|
23 |
+
"class" : "PassThroughRule",
|
24 |
+
"selector" : "div.gallery-group p"
|
25 |
+
},
|
26 |
+
{
|
27 |
+
"class" : "PassThroughRule",
|
28 |
+
"selector" : "div.gallery-group"
|
29 |
+
},
|
30 |
+
{
|
31 |
+
"class": "ImageRule",
|
32 |
+
"selector" : "div.wp-caption",
|
33 |
+
"properties" : {
|
34 |
+
"image.url" : {
|
35 |
+
"type" : "string",
|
36 |
+
"selector" : "img",
|
37 |
+
"attribute": "src"
|
38 |
+
}
|
39 |
+
}
|
40 |
+
},
|
41 |
+
{
|
42 |
+
"class": "SlideshowImageRule",
|
43 |
+
"selector" : "div.tiled-gallery-item",
|
44 |
+
"properties" : {
|
45 |
+
"image.url" : {
|
46 |
+
"type" : "string",
|
47 |
+
"selector" : "img",
|
48 |
+
"attribute": "data-orig-file"
|
49 |
+
},
|
50 |
+
"caption.title" : {
|
51 |
+
"type" : "string",
|
52 |
+
"selector" : "div.tiled-gallery-caption"
|
53 |
+
}
|
54 |
+
}
|
55 |
+
},
|
56 |
+
{
|
57 |
+
"class": "SlideshowRule",
|
58 |
+
"selector" : "div.tiled-gallery"
|
59 |
+
},
|
60 |
+
{
|
61 |
+
"class": "SlideshowImageRule",
|
62 |
+
"selector" : "dl.gallery-item",
|
63 |
+
"properties" : {
|
64 |
+
"image.url" : {
|
65 |
+
"type" : "string",
|
66 |
+
"selector" : "a",
|
67 |
+
"attribute": "href"
|
68 |
+
},
|
69 |
+
"caption.title" : {
|
70 |
+
"type" : "string",
|
71 |
+
"selector" : "dd.wp-caption-text"
|
72 |
+
}
|
73 |
+
}
|
74 |
+
},
|
75 |
+
{
|
76 |
+
"class": "Compat\\JetpackSlideshowRule",
|
77 |
+
"selector" : "div.jetpack-slideshow",
|
78 |
+
"properties": {
|
79 |
+
"jetpack.data-gallery": {
|
80 |
+
"type": "json",
|
81 |
+
"selector": "div.jetpack-slideshow",
|
82 |
+
"attribute": "data-gallery"
|
83 |
+
}
|
84 |
+
}
|
85 |
+
},
|
86 |
+
{
|
87 |
+
"class": "CaptionRule",
|
88 |
+
"selector" : "div.tiled-gallery-caption"
|
89 |
+
}
|
90 |
+
]
|
91 |
+
}
|
css/instant-articles-wizard.css
ADDED
@@ -0,0 +1,417 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#instant_articles_wizard a {
|
2 |
+
color: #4080ff;
|
3 |
+
text-decoration: none;
|
4 |
+
font-weight: bold;
|
5 |
+
}
|
6 |
+
#instant_articles_wizard a:hover {
|
7 |
+
text-decoration: underline;
|
8 |
+
}
|
9 |
+
|
10 |
+
.instant-articles-card {
|
11 |
+
background: white;
|
12 |
+
border: solid 1px #dddfe2;
|
13 |
+
border-radius: 5px;
|
14 |
+
margin: 20px 20px 0 0;
|
15 |
+
overflow: hidden;
|
16 |
+
}
|
17 |
+
.instant-articles-card-success {
|
18 |
+
border: solid 1px #42b72a;
|
19 |
+
}
|
20 |
+
.instant-articles-card-fail {
|
21 |
+
border: solid 1px #eb4145;
|
22 |
+
}
|
23 |
+
.instant-articles-card-collapsed {
|
24 |
+
border: solid 1px #42b72a;
|
25 |
+
padding-bottom: 0;
|
26 |
+
}
|
27 |
+
.instant-articles-card-collapsed .instant-articles-card-content {
|
28 |
+
display: none;
|
29 |
+
}
|
30 |
+
.instant-articles-card-content-box h3 {
|
31 |
+
text-align: center;
|
32 |
+
margin-top: 40px;
|
33 |
+
margin-bottom: 40px;
|
34 |
+
}
|
35 |
+
.instant-articles-card-content-box h4 {
|
36 |
+
text-align: center;
|
37 |
+
margin-top: 15px;
|
38 |
+
margin-bottom: -5px;
|
39 |
+
color: #9ca0a7;
|
40 |
+
}
|
41 |
+
.instant-articles-card-steps {
|
42 |
+
margin: 20px auto;
|
43 |
+
overflow: hidden;
|
44 |
+
width: 660px;
|
45 |
+
}
|
46 |
+
.instant-articles-card-step {
|
47 |
+
position: relative;
|
48 |
+
float: left;
|
49 |
+
display: inline-block;
|
50 |
+
width: 140px;
|
51 |
+
margin: 0px 10px;
|
52 |
+
}
|
53 |
+
.instant-articles-card-step img {
|
54 |
+
display: block;
|
55 |
+
width: 60px;
|
56 |
+
margin: 0 auto;
|
57 |
+
}
|
58 |
+
.instant-articles-card-step p {
|
59 |
+
text-align: center;
|
60 |
+
}
|
61 |
+
.instant-articles-card-bullet-bar {
|
62 |
+
margin: 80px auto 20px auto;
|
63 |
+
min-height: 50px;
|
64 |
+
overflow: hidden;
|
65 |
+
width: 660px;
|
66 |
+
}
|
67 |
+
.instant-articles-card-bullet-step {
|
68 |
+
position: relative;
|
69 |
+
float: left;
|
70 |
+
display: inline-block;
|
71 |
+
width: 140px;
|
72 |
+
margin: 0 10px;
|
73 |
+
}
|
74 |
+
.instant-articles-card-bullet-step p {
|
75 |
+
text-align: center;
|
76 |
+
color: #9ca0a7;
|
77 |
+
font-size: 0.95em;
|
78 |
+
margin: 0.7em 0;
|
79 |
+
display: none;
|
80 |
+
}
|
81 |
+
.instant-articles-card-bullet-step h4 {
|
82 |
+
text-align: center;
|
83 |
+
color: #9ca0a7;
|
84 |
+
font-size: 0.95em;
|
85 |
+
margin-top: 0.7em;
|
86 |
+
margin-bottom: -0.5em;
|
87 |
+
}
|
88 |
+
.instant-articles-card-bullet {
|
89 |
+
display: block;
|
90 |
+
width: 15px;
|
91 |
+
height: 15px;
|
92 |
+
background-color: #d8d8d8;
|
93 |
+
border-radius: 10px;
|
94 |
+
margin: 0 auto;
|
95 |
+
color: white;
|
96 |
+
font-size: 0.55em;
|
97 |
+
font-weight: lighter;
|
98 |
+
text-align: center;
|
99 |
+
line-height: 15px;
|
100 |
+
}
|
101 |
+
.instant-articles-card-bullet-path {
|
102 |
+
position: absolute;
|
103 |
+
top: 0;
|
104 |
+
margin-top: 7px;
|
105 |
+
right: -84px;
|
106 |
+
width: 146px;
|
107 |
+
height: 2px;
|
108 |
+
background-color: #d8d8d8;
|
109 |
+
}
|
110 |
+
.instant-articles-card-bullet-step-completed p,
|
111 |
+
.instant-articles-card-bullet-step-completed h4 {
|
112 |
+
color: #69c456;
|
113 |
+
}
|
114 |
+
.instant-articles-card-bullet-step-completed .instant-articles-card-bullet {
|
115 |
+
background-color: #69c456;
|
116 |
+
}
|
117 |
+
.instant-articles-card-bullet-step-completed .instant-articles-card-bullet::before {
|
118 |
+
content: '✔';
|
119 |
+
}
|
120 |
+
.instant-articles-card-bullet-step-current p,
|
121 |
+
.instant-articles-card-bullet-step-current h4 {
|
122 |
+
display: block;
|
123 |
+
color: #4080ff;
|
124 |
+
}
|
125 |
+
.instant-articles-card-bullet-step-current .instant-articles-card-bullet {
|
126 |
+
background-color: #4080ff;
|
127 |
+
}
|
128 |
+
.instant-articles-card-title {
|
129 |
+
background: #f6f7f9;
|
130 |
+
border-radius: 5px 5px 0 0;
|
131 |
+
border-bottom: solid 1px #dddfe2;
|
132 |
+
height: 55px;
|
133 |
+
line-height: 55px;
|
134 |
+
position: relative;
|
135 |
+
}
|
136 |
+
.instant-articles-card-collapsed .instant-articles-card-title {
|
137 |
+
border-bottom: none;
|
138 |
+
background: #f6faf1;
|
139 |
+
}
|
140 |
+
.instant-articles-card-success .instant-articles-card-title {
|
141 |
+
border-bottom: solid 1px #42b72a;
|
142 |
+
background: #f6faf1;
|
143 |
+
}
|
144 |
+
.instant-articles-card-fail .instant-articles-card-title {
|
145 |
+
border-bottom: solid 1px #eb4145;
|
146 |
+
background: #fcebe8;
|
147 |
+
}
|
148 |
+
.instant-articles-card-title h3 {
|
149 |
+
margin: 0 20px 0 20px;
|
150 |
+
display: inline-block;
|
151 |
+
vertical-align: middle;
|
152 |
+
}
|
153 |
+
.instant-articles-card-title-right {
|
154 |
+
margin: 0 20px 0 20px;
|
155 |
+
display: inline-block;
|
156 |
+
vertical-align: middle;
|
157 |
+
position: absolute;
|
158 |
+
right: 0px;
|
159 |
+
font-size: 1.3em;
|
160 |
+
color: #acafb6;
|
161 |
+
}
|
162 |
+
.instant-articles-card-collapsed .instant-articles-card-title-right > * {
|
163 |
+
display: inline-block;
|
164 |
+
vertical-align: middle;
|
165 |
+
}
|
166 |
+
.instant-articles-card-title-right > * {
|
167 |
+
display: none;
|
168 |
+
}
|
169 |
+
.instant-articles-card-title-right img {
|
170 |
+
width: 40px;
|
171 |
+
height: 40px;
|
172 |
+
}
|
173 |
+
.instant-articles-card-title-step {
|
174 |
+
display: inline-block;
|
175 |
+
}
|
176 |
+
.instant-articles-card-title-checkmark {
|
177 |
+
color: #42b72a;
|
178 |
+
font-size: 0.9em;
|
179 |
+
}
|
180 |
+
.instant-articles-card-collapsed .instant-articles-card-title-step {
|
181 |
+
display: none;
|
182 |
+
}
|
183 |
+
.instant-articles-card-title-label {
|
184 |
+
font-weight: bold;
|
185 |
+
font-size: .8em;
|
186 |
+
color: #4b4f56;
|
187 |
+
}
|
188 |
+
.instant-articles-card-title-value {
|
189 |
+
font-size: .8em;
|
190 |
+
color: #373b42;
|
191 |
+
}
|
192 |
+
.instant-articles-card-title-edit {
|
193 |
+
background: url('/wp-content/plugins/facebook-instant-articles-wp/assets/pencil.png');
|
194 |
+
background-size: 13px 13px;
|
195 |
+
background-repeat: no-repeat;
|
196 |
+
width: 15px;
|
197 |
+
height: 14px;
|
198 |
+
}
|
199 |
+
.instant-articles-card-content {
|
200 |
+
margin: 20px;
|
201 |
+
}
|
202 |
+
.instant-articles-card-content-box {
|
203 |
+
width: 50%;
|
204 |
+
float: left;
|
205 |
+
box-sizing: border-box;
|
206 |
+
}
|
207 |
+
.instant-articles-card-content-box label {
|
208 |
+
font-weight: bold;
|
209 |
+
color: #4b4f56;
|
210 |
+
font-size: 1em;
|
211 |
+
}
|
212 |
+
.instant-articles-card-content-box p {
|
213 |
+
color: #9ca0a7;
|
214 |
+
font-size: 1em;
|
215 |
+
margin: 0.7em 0;
|
216 |
+
}
|
217 |
+
.instant-articles-card-content-box ol {
|
218 |
+
margin-left: 0px;
|
219 |
+
padding-left: 0px;
|
220 |
+
list-style: decimal inside none;
|
221 |
+
}
|
222 |
+
.instant-articles-card-content-box li {
|
223 |
+
color: #9ca0a7;
|
224 |
+
font-size: 1em;
|
225 |
+
margin: 0.7em 0;
|
226 |
+
}
|
227 |
+
.instant-articles-page-img {
|
228 |
+
width: 40px;
|
229 |
+
height: 40px;
|
230 |
+
background-color: black;
|
231 |
+
border: 1px solid #dddfe2;
|
232 |
+
margin-left: 5px;
|
233 |
+
}
|
234 |
+
.instant-articles-wizard-page-selection li {
|
235 |
+
margin: 0px -20px;
|
236 |
+
padding: 10px 20px;
|
237 |
+
cursor: pointer;
|
238 |
+
}
|
239 |
+
.instant-articles-radio-selected {
|
240 |
+
background-color: #f6f7f9;
|
241 |
+
}
|
242 |
+
.instant-articles-wizard-page-selection li > label {
|
243 |
+
font-weight: normal;
|
244 |
+
color: #9ca0a7;
|
245 |
+
margin-left: 10px;
|
246 |
+
}
|
247 |
+
.instant-articles-wizard-page-selection li > label span {
|
248 |
+
display: none;
|
249 |
+
}
|
250 |
+
.instant-articles-wizard-page-selection li.instant-articles-radio-selected > label > span {
|
251 |
+
display: inline-block;
|
252 |
+
margin-left: 30px;
|
253 |
+
}
|
254 |
+
.instant-articles-wizard-page-selection li.instant-articles-radio-selected > label > span.page-enabled {
|
255 |
+
font-weight: bold;
|
256 |
+
color: #69c456;
|
257 |
+
}
|
258 |
+
.instant-articles-wizard-page-selection li > * {
|
259 |
+
display:inline-block;
|
260 |
+
vertical-align:middle;
|
261 |
+
cursor: pointer;
|
262 |
+
}
|
263 |
+
.instant-articles-card-content-right {
|
264 |
+
padding-left: 10px;
|
265 |
+
}
|
266 |
+
.instant-articles-card-content-left {
|
267 |
+
padding-right: 10px;
|
268 |
+
}
|
269 |
+
.instant-articles-card-content-full {
|
270 |
+
float: none;
|
271 |
+
width: 100%;
|
272 |
+
}
|
273 |
+
.instant-articles-card-content-full .instant-articles-card-title-edit {
|
274 |
+
display: inline-block;
|
275 |
+
}
|
276 |
+
.instant-articles-card-content-full hr {
|
277 |
+
margin: 20px -20px 20px -20px;
|
278 |
+
}
|
279 |
+
.instant-articles-label {
|
280 |
+
display: block;
|
281 |
+
}
|
282 |
+
.instant-articles-input-text {
|
283 |
+
display: block;
|
284 |
+
border-radius: 4px;
|
285 |
+
margin-top: 5px;
|
286 |
+
margin-bottom: 10px;
|
287 |
+
}
|
288 |
+
.instant-articles-button {
|
289 |
+
display: inline-block;
|
290 |
+
border-radius: 4px;
|
291 |
+
background-color: #4267b2;
|
292 |
+
color: #fff !important;
|
293 |
+
text-decoration: none !important;
|
294 |
+
padding: 8px 20px;
|
295 |
+
margin-top: 10px;
|
296 |
+
border: none;
|
297 |
+
line-height: 25px;
|
298 |
+
vertical-align: middle;
|
299 |
+
cursor: pointer;
|
300 |
+
}
|
301 |
+
a.instant-articles-button {
|
302 |
+
padding: 5px 20px;
|
303 |
+
}
|
304 |
+
.instant-articles-button:hover,
|
305 |
+
.instant-articles-button:active,
|
306 |
+
.instant-articles-button:focus {
|
307 |
+
color: #fff;
|
308 |
+
}
|
309 |
+
.instant-articles-button label {
|
310 |
+
color: white;
|
311 |
+
font-weight: normal;
|
312 |
+
font-size: 1em;
|
313 |
+
margin-top: -2px;
|
314 |
+
display: inline-block;
|
315 |
+
height: 20px;
|
316 |
+
float: left;
|
317 |
+
}
|
318 |
+
.instant-articles-button-highlight {
|
319 |
+
background-color: #42b72a;
|
320 |
+
}
|
321 |
+
.instant-articles-button-disabled {
|
322 |
+
opacity: 0.4;
|
323 |
+
cursor: default !important;
|
324 |
+
}
|
325 |
+
.instant-articles-button-disabled * {
|
326 |
+
cursor: default !important;
|
327 |
+
}
|
328 |
+
.instant-articles-button-centered {
|
329 |
+
margin: 0 auto;
|
330 |
+
display: block;
|
331 |
+
}
|
332 |
+
.instant-articles-button-disabled:focus,
|
333 |
+
.instant-articles-button-disabled:active {
|
334 |
+
box-shadow: none;
|
335 |
+
outline: none;
|
336 |
+
}
|
337 |
+
.instant-articles-button-icon-facebook {
|
338 |
+
background: url('/wp-content/plugins/facebook-instant-articles-wp/assets/icon-fb-login.png');
|
339 |
+
background-size: 18px 18px;
|
340 |
+
background-repeat: no-repeat;
|
341 |
+
display: inline-block;
|
342 |
+
width: 18px;
|
343 |
+
height: 18px;
|
344 |
+
margin: 0 10px 0 -12px;
|
345 |
+
float: left;
|
346 |
+
}
|
347 |
+
.instant-articles-card-title-link {
|
348 |
+
text-decoration: none;
|
349 |
+
font-size: .7em;
|
350 |
+
font-weight: bold;
|
351 |
+
}
|
352 |
+
.instant-articles-advanced-settings {
|
353 |
+
text-decoration: none;
|
354 |
+
font-weight: bold;
|
355 |
+
margin-top: 20px;
|
356 |
+
display: block;
|
357 |
+
}
|
358 |
+
.instant-articles-advanced-settings:active,
|
359 |
+
.instant-articles-advanced-settings:focus {
|
360 |
+
outline: none;
|
361 |
+
box-shadow: none;
|
362 |
+
}
|
363 |
+
|
364 |
+
.instant-articles-wizard-advanced-settings-box {
|
365 |
+
display: none;
|
366 |
+
}
|
367 |
+
|
368 |
+
#instant_articles_wizard_messages div.error,
|
369 |
+
#instant_articles_wizard_messages div.update,
|
370 |
+
#instant_articles_wizard_messages .notice,
|
371 |
+
#instant_articles_wizard div.error,
|
372 |
+
#instant_articles_wizard div.update,
|
373 |
+
#instant_articles_wizard .notice {
|
374 |
+
margin-left: 0;
|
375 |
+
}
|
376 |
+
|
377 |
+
#instant_articles_wizard.loading {
|
378 |
+
opacity: 0.5;
|
379 |
+
position: relative;
|
380 |
+
}
|
381 |
+
|
382 |
+
#instant_articles_wizard.loading::after {
|
383 |
+
content: '';
|
384 |
+
border: 16px solid rgba(255,255,255,0); /* Light grey */
|
385 |
+
border-top: 16px solid #3498db; /* Blue */
|
386 |
+
border-radius: 50%;
|
387 |
+
width: 120px;
|
388 |
+
height: 120px;
|
389 |
+
animation: spin 1s linear infinite;
|
390 |
+
display: block;
|
391 |
+
position: absolute;
|
392 |
+
margin-top: -120px;
|
393 |
+
margin-left: -120px;
|
394 |
+
left: 50%;
|
395 |
+
top: 50%;
|
396 |
+
}
|
397 |
+
#instant-articles-wizard-signup {
|
398 |
+
display: none;
|
399 |
+
}
|
400 |
+
#instant-articles-wizard-customize-style-next {
|
401 |
+
display: none;
|
402 |
+
}
|
403 |
+
@keyframes spin {
|
404 |
+
0% { transform: rotate(0deg); }
|
405 |
+
100% { transform: rotate(360deg); }
|
406 |
+
}
|
407 |
+
|
408 |
+
@media screen and (max-width: 782px) {
|
409 |
+
.instant-articles-card-content-box {
|
410 |
+
clear: both;
|
411 |
+
width: 100%;
|
412 |
+
padding: 0;
|
413 |
+
}
|
414 |
+
.instant-articles-card-content-right {
|
415 |
+
margin-top: 40px;
|
416 |
+
}
|
417 |
+
}
|
facebook-instant-articles.php
CHANGED
@@ -4,7 +4,7 @@
|
|
4 |
* Description: Add support for Instant Articles for Facebook to your WordPress site.
|
5 |
* Author: Automattic, Dekode, Facebook
|
6 |
* Author URI: https://vip.wordpress.com/plugins/instant-articles/
|
7 |
-
* Version: 3.
|
8 |
* Text Domain: instant-articles
|
9 |
* License: GPLv2
|
10 |
* License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
@@ -61,7 +61,7 @@ if ( version_compare( PHP_VERSION, '5.4', '<' ) ) {
|
|
61 |
|
62 |
defined( 'ABSPATH' ) || die( 'Shame on you' );
|
63 |
|
64 |
-
define( 'IA_PLUGIN_VERSION', '
|
65 |
define( 'IA_PLUGIN_PATH_FULL', __FILE__ );
|
66 |
define( 'IA_PLUGIN_PATH', plugin_basename( __FILE__ ) );
|
67 |
define( 'IA_PLUGIN_FILE_BASENAME', pathinfo( __FILE__, PATHINFO_FILENAME ) );
|
@@ -74,7 +74,7 @@ if ( version_compare( PHP_VERSION, '5.4', '<' ) ) {
|
|
74 |
|
75 |
require_once( dirname( __FILE__ ) . '/embeds.php' );
|
76 |
require_once( dirname( __FILE__ ) . '/class-instant-articles-post.php' );
|
77 |
-
require_once( dirname( __FILE__ ) . '/
|
78 |
require_once( dirname( __FILE__ ) . '/meta-box/class-instant-articles-meta-box.php' );
|
79 |
require_once( dirname( __FILE__ ) . '/class-instant-articles-publisher.php' );
|
80 |
|
@@ -89,6 +89,21 @@ if ( version_compare( PHP_VERSION, '5.4', '<' ) ) {
|
|
89 |
}
|
90 |
register_activation_hook( __FILE__, 'instant_articles_activate' );
|
91 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
92 |
/**
|
93 |
* Plugin activation hook to remove our rewrite rules.
|
94 |
*
|
@@ -187,7 +202,6 @@ if ( version_compare( PHP_VERSION, '5.4', '<' ) ) {
|
|
187 |
) );
|
188 |
}
|
189 |
}
|
190 |
-
|
191 |
}
|
192 |
add_action( 'pre_get_posts', 'instant_articles_query', 10, 1 );
|
193 |
|
@@ -226,14 +240,14 @@ if ( version_compare( PHP_VERSION, '5.4', '<' ) ) {
|
|
226 |
'instant-articles-meta-box',
|
227 |
plugins_url( '/css/instant-articles-meta-box.css', __FILE__ )
|
228 |
);
|
229 |
-
wp_register_style(
|
230 |
-
'instant-articles-settings-wizard',
|
231 |
-
plugins_url( '/css/instant-articles-settings-wizard.css', __FILE__ )
|
232 |
-
);
|
233 |
wp_register_style(
|
234 |
'instant-articles-settings',
|
235 |
plugins_url( '/css/instant-articles-settings.css', __FILE__ )
|
236 |
);
|
|
|
|
|
|
|
|
|
237 |
|
238 |
wp_register_script(
|
239 |
'instant-articles-meta-box',
|
@@ -267,6 +281,13 @@ if ( version_compare( PHP_VERSION, '5.4', '<' ) ) {
|
|
267 |
null,
|
268 |
true
|
269 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
270 |
}
|
271 |
add_action( 'init', 'instant_articles_register_scripts' );
|
272 |
|
@@ -279,12 +300,14 @@ if ( version_compare( PHP_VERSION, '5.4', '<' ) ) {
|
|
279 |
wp_enqueue_style( 'instant-articles-meta-box' );
|
280 |
wp_enqueue_style( 'instant-articles-settings-wizard' );
|
281 |
wp_enqueue_style( 'instant-articles-settings' );
|
|
|
282 |
|
283 |
wp_enqueue_script( 'instant-articles-meta-box' );
|
284 |
wp_enqueue_script( 'instant-articles-option-ads' );
|
285 |
wp_enqueue_script( 'instant-articles-option-analytics' );
|
286 |
wp_enqueue_script( 'instant-articles-option-publishing' );
|
287 |
wp_enqueue_script( 'instant-articles-settings' );
|
|
|
288 |
}
|
289 |
add_action( 'admin_enqueue_scripts', 'instant_articles_enqueue_scripts' );
|
290 |
|
@@ -306,12 +329,12 @@ if ( version_compare( PHP_VERSION, '5.4', '<' ) ) {
|
|
306 |
}
|
307 |
add_action( 'wp_head', 'inject_url_claiming_meta_tag' );
|
308 |
|
309 |
-
// Initialize the Instant Articles settings page.
|
310 |
-
Instant_Articles_Settings::init();
|
311 |
-
|
312 |
// Initialize the Instant Articles meta box.
|
313 |
Instant_Articles_Meta_Box::init();
|
314 |
|
315 |
// Initialize the Instant Articles publisher.
|
316 |
Instant_Articles_Publisher::init();
|
|
|
|
|
|
|
317 |
}
|
4 |
* Description: Add support for Instant Articles for Facebook to your WordPress site.
|
5 |
* Author: Automattic, Dekode, Facebook
|
6 |
* Author URI: https://vip.wordpress.com/plugins/instant-articles/
|
7 |
+
* Version: 3.1
|
8 |
* Text Domain: instant-articles
|
9 |
* License: GPLv2
|
10 |
* License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
61 |
|
62 |
defined( 'ABSPATH' ) || die( 'Shame on you' );
|
63 |
|
64 |
+
define( 'IA_PLUGIN_VERSION', '3.1' );
|
65 |
define( 'IA_PLUGIN_PATH_FULL', __FILE__ );
|
66 |
define( 'IA_PLUGIN_PATH', plugin_basename( __FILE__ ) );
|
67 |
define( 'IA_PLUGIN_FILE_BASENAME', pathinfo( __FILE__, PATHINFO_FILENAME ) );
|
74 |
|
75 |
require_once( dirname( __FILE__ ) . '/embeds.php' );
|
76 |
require_once( dirname( __FILE__ ) . '/class-instant-articles-post.php' );
|
77 |
+
require_once( dirname( __FILE__ ) . '/wizard/class-instant-articles-wizard.php' );
|
78 |
require_once( dirname( __FILE__ ) . '/meta-box/class-instant-articles-meta-box.php' );
|
79 |
require_once( dirname( __FILE__ ) . '/class-instant-articles-publisher.php' );
|
80 |
|
89 |
}
|
90 |
register_activation_hook( __FILE__, 'instant_articles_activate' );
|
91 |
|
92 |
+
/**
|
93 |
+
* Show a message to set up the plugin when it is activated
|
94 |
+
*/
|
95 |
+
add_action( 'admin_notices', 'instant_articles_setup_admin_notice' );
|
96 |
+
add_action( 'network_admin_notices', 'instant_articles_setup_admin_notice' ); // also show message on multisite
|
97 |
+
function instant_articles_setup_admin_notice() {
|
98 |
+
global $pagenow;
|
99 |
+
if ( $pagenow === 'plugins.php' && Instant_Articles_Wizard_State::get_current_state() !== Instant_Articles_Wizard_State::STATE_REVIEW_SUBMISSION ) {
|
100 |
+
$settings_url = Instant_Articles_Wizard::get_url();
|
101 |
+
echo '<div class="updated settings-error notice is-dismissible">';
|
102 |
+
echo '<p>Congrats, you\'ve installed the Instant Articles for WP plugin. Now <a href="' . esc_url_raw($settings_url) . '">set it up</a> to start publishing Instant Articles.';
|
103 |
+
echo '</div>';
|
104 |
+
}
|
105 |
+
}
|
106 |
+
|
107 |
/**
|
108 |
* Plugin activation hook to remove our rewrite rules.
|
109 |
*
|
202 |
) );
|
203 |
}
|
204 |
}
|
|
|
205 |
}
|
206 |
add_action( 'pre_get_posts', 'instant_articles_query', 10, 1 );
|
207 |
|
240 |
'instant-articles-meta-box',
|
241 |
plugins_url( '/css/instant-articles-meta-box.css', __FILE__ )
|
242 |
);
|
|
|
|
|
|
|
|
|
243 |
wp_register_style(
|
244 |
'instant-articles-settings',
|
245 |
plugins_url( '/css/instant-articles-settings.css', __FILE__ )
|
246 |
);
|
247 |
+
wp_register_style(
|
248 |
+
'instant-articles-wizard',
|
249 |
+
plugins_url( '/css/instant-articles-wizard.css', __FILE__ )
|
250 |
+
);
|
251 |
|
252 |
wp_register_script(
|
253 |
'instant-articles-meta-box',
|
281 |
null,
|
282 |
true
|
283 |
);
|
284 |
+
wp_register_script(
|
285 |
+
'instant-articles-wizard',
|
286 |
+
plugins_url( '/js/instant-articles-wizard.js', __FILE__ ),
|
287 |
+
null,
|
288 |
+
null,
|
289 |
+
true
|
290 |
+
);
|
291 |
}
|
292 |
add_action( 'init', 'instant_articles_register_scripts' );
|
293 |
|
300 |
wp_enqueue_style( 'instant-articles-meta-box' );
|
301 |
wp_enqueue_style( 'instant-articles-settings-wizard' );
|
302 |
wp_enqueue_style( 'instant-articles-settings' );
|
303 |
+
wp_enqueue_style( 'instant-articles-wizard' );
|
304 |
|
305 |
wp_enqueue_script( 'instant-articles-meta-box' );
|
306 |
wp_enqueue_script( 'instant-articles-option-ads' );
|
307 |
wp_enqueue_script( 'instant-articles-option-analytics' );
|
308 |
wp_enqueue_script( 'instant-articles-option-publishing' );
|
309 |
wp_enqueue_script( 'instant-articles-settings' );
|
310 |
+
wp_enqueue_script( 'instant-articles-wizard' );
|
311 |
}
|
312 |
add_action( 'admin_enqueue_scripts', 'instant_articles_enqueue_scripts' );
|
313 |
|
329 |
}
|
330 |
add_action( 'wp_head', 'inject_url_claiming_meta_tag' );
|
331 |
|
|
|
|
|
|
|
332 |
// Initialize the Instant Articles meta box.
|
333 |
Instant_Articles_Meta_Box::init();
|
334 |
|
335 |
// Initialize the Instant Articles publisher.
|
336 |
Instant_Articles_Publisher::init();
|
337 |
+
|
338 |
+
// Initialize the Instant Articles Wizard page.
|
339 |
+
Instant_Articles_Wizard::init();
|
340 |
}
|
js/instant-articles-settings.js
CHANGED
@@ -1,25 +1,8 @@
|
|
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 |
} );
|
1 |
jQuery( function () {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
jQuery( '.instant-articles-settings-box > h2' ).click(function () {
|
3 |
$h2 = jQuery( this );
|
4 |
$h2.siblings('.inside').toggle();
|
5 |
$h2.toggleClass('dashicons-arrow-down');
|
6 |
$h2.toggleClass('dashicons-arrow-right');
|
7 |
+
});
|
8 |
} );
|
js/instant-articles-wizard.js
ADDED
@@ -0,0 +1,136 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
function instant_articles_wizard_load ( data ) {
|
2 |
+
jQuery( '#instant_articles_wizard' ).addClass( 'loading' );
|
3 |
+
jQuery.post( ajaxurl, data, function( response ) {
|
4 |
+
jQuery( '#instant_articles_wizard' ).html( response );
|
5 |
+
instant_articles_wizard_bind_events();
|
6 |
+
jQuery( '#instant_articles_wizard' ).removeClass( 'loading' );
|
7 |
+
window.scrollTo(0, 0);
|
8 |
+
}, 'html' );
|
9 |
+
}
|
10 |
+
|
11 |
+
function instant_articles_wizard_transition ( new_state, params ) {
|
12 |
+
instant_articles_wizard_load ( {
|
13 |
+
'action': 'instant_articles_wizard_transition',
|
14 |
+
'new_state': new_state,
|
15 |
+
'params': JSON.stringify(params)
|
16 |
+
} );
|
17 |
+
}
|
18 |
+
|
19 |
+
function instant_articles_wizard_save_app ( app_id, app_secret ) {
|
20 |
+
instant_articles_wizard_load ( {
|
21 |
+
'action': 'instant_articles_wizard_save_app',
|
22 |
+
'app_id': app_id,
|
23 |
+
'app_secret': app_secret
|
24 |
+
} );
|
25 |
+
}
|
26 |
+
|
27 |
+
function instant_articles_wizard_edit_app () {
|
28 |
+
instant_articles_wizard_load ( {
|
29 |
+
'action': 'instant_articles_wizard_edit_app',
|
30 |
+
} );
|
31 |
+
}
|
32 |
+
|
33 |
+
|
34 |
+
function instant_articles_wizard_submit_for_review () {
|
35 |
+
instant_articles_wizard_load ( {
|
36 |
+
'action': 'instant_articles_wizard_submit_for_review',
|
37 |
+
} );
|
38 |
+
}
|
39 |
+
|
40 |
+
function instant_articles_wizard_bind_events () {
|
41 |
+
|
42 |
+
jQuery( '#instant_articles_wizard a' ).on( 'click', function () {
|
43 |
+
if ( ! jQuery( this ).attr( 'target' ) ) {
|
44 |
+
jQuery( '#instant_articles_wizard' ).addClass( 'loading' );
|
45 |
+
}
|
46 |
+
});
|
47 |
+
|
48 |
+
jQuery( '.instant-articles-wizard-transition' ).on( 'click', function () {
|
49 |
+
if ( jQuery( this ).hasClass( 'instant-articles-button-disabled' ) ) {
|
50 |
+
return false;
|
51 |
+
}
|
52 |
+
instant_articles_wizard_transition( jQuery( this ).attr( 'data-new-state' ) );
|
53 |
+
});
|
54 |
+
|
55 |
+
jQuery('input[name=app_id], input[name=app_secret]').on( 'change', function () {
|
56 |
+
var app_id = jQuery('input[name=app_id]').val();
|
57 |
+
var app_secret = jQuery('input[name=app_secret]').val();
|
58 |
+
if (app_id && app_secret) {
|
59 |
+
jQuery( '#instant-articles-wizard-save-app' ).removeClass( 'instant-articles-button-disabled' );
|
60 |
+
}
|
61 |
+
else {
|
62 |
+
jQuery( '#instant-articles-wizard-save-app' ).addClass( 'instant-articles-button-disabled' );
|
63 |
+
}
|
64 |
+
});
|
65 |
+
|
66 |
+
jQuery('input[name=page_id]').on( 'change', function () {
|
67 |
+
var input = jQuery( this );
|
68 |
+
var page_id = jQuery('input[name=page_id]:checked').val();
|
69 |
+
var signed_up = ( jQuery('input[name=page_id]:checked').attr( 'data-signed-up' ) === 'yes' );
|
70 |
+
if ( page_id && signed_up ) {
|
71 |
+
jQuery( '#instant-articles-wizard-select-page' ).removeClass( 'instant-articles-button-disabled' );
|
72 |
+
}
|
73 |
+
else {
|
74 |
+
jQuery( '#instant-articles-wizard-select-page' ).addClass( 'instant-articles-button-disabled' );
|
75 |
+
}
|
76 |
+
});
|
77 |
+
|
78 |
+
jQuery( '#instant-articles-wizard-save-app' ).on( 'click', function () {
|
79 |
+
if ( jQuery( this ).hasClass( 'instant-articles-button-disabled' ) ) {
|
80 |
+
return false;
|
81 |
+
}
|
82 |
+
var app_id = jQuery('input[name=app_id]').val();
|
83 |
+
var app_secret = jQuery('input[name=app_secret]').val();
|
84 |
+
instant_articles_wizard_save_app( app_id, app_secret );
|
85 |
+
});
|
86 |
+
|
87 |
+
jQuery( '#instant-articles-wizard-edit-app' ).on( 'click', function () {
|
88 |
+
if ( jQuery( this ).hasClass( 'instant-articles-button-disabled' ) ) {
|
89 |
+
return false;
|
90 |
+
}
|
91 |
+
instant_articles_wizard_edit_app();
|
92 |
+
});
|
93 |
+
|
94 |
+
jQuery( '#instant-articles-wizard-submit-for-review' ).on( 'click', function () {
|
95 |
+
if ( jQuery( this ).hasClass( 'instant-articles-button-disabled' ) ) {
|
96 |
+
return false;
|
97 |
+
}
|
98 |
+
instant_articles_wizard_submit_for_review();
|
99 |
+
});
|
100 |
+
|
101 |
+
jQuery( '#instant-articles-wizard-select-page' ).on( 'click', function () {
|
102 |
+
if ( jQuery( this ).hasClass( 'instant-articles-button-disabled' ) ) {
|
103 |
+
return false;
|
104 |
+
}
|
105 |
+
var page_id = jQuery('input[name=page_id]:checked').val();
|
106 |
+
instant_articles_wizard_transition( 'STATE_STYLE_SELECTION', { page_id: page_id } );
|
107 |
+
});
|
108 |
+
|
109 |
+
jQuery( '#instant-articles-wizard-customize-style' ).on( 'click', function () {
|
110 |
+
jQuery( '#instant-articles-wizard-customize-style-next' ).show();
|
111 |
+
});
|
112 |
+
|
113 |
+
jQuery( '.instant-articles-card-content-box li' ).on( 'click', function () {
|
114 |
+
jQuery( '.instant-articles-card-content-box li.instant-articles-radio-selected' ).removeClass( 'instant-articles-radio-selected' );
|
115 |
+
jQuery( this ).find( 'input' ).attr( 'checked', 'checked' );
|
116 |
+
jQuery( this ).find( 'input' ).trigger( 'change' );
|
117 |
+
jQuery( this ).toggleClass( 'instant-articles-radio-selected' );
|
118 |
+
});
|
119 |
+
}
|
120 |
+
|
121 |
+
|
122 |
+
jQuery( document ).ready( function () {
|
123 |
+
instant_articles_wizard_bind_events();
|
124 |
+
|
125 |
+
jQuery( '.instant-articles-wizard-toggle' ).on( 'click', function () {
|
126 |
+
var text = jQuery( this ).text();
|
127 |
+
if ( text.indexOf( '►' ) !== -1 ) {
|
128 |
+
text = text.replace( '►', '▼' );
|
129 |
+
}
|
130 |
+
else {
|
131 |
+
text = text.replace( '▼', '►' );
|
132 |
+
}
|
133 |
+
jQuery( this ).text( text ).next().slideToggle();
|
134 |
+
return false;
|
135 |
+
});
|
136 |
+
});
|
meta-box/class-instant-articles-meta-box.php
CHANGED
@@ -65,8 +65,8 @@ class Instant_Articles_Meta_Box {
|
|
65 |
$submission_status = null;
|
66 |
$published = 'publish' === $post->post_status;
|
67 |
|
68 |
-
|
69 |
-
$settings_page_href =
|
70 |
|
71 |
if ( $published ) {
|
72 |
try {
|
65 |
$submission_status = null;
|
66 |
$published = 'publish' === $post->post_status;
|
67 |
|
68 |
+
Instant_Articles_Wizard::menu_items();
|
69 |
+
$settings_page_href = Instant_Articles_Wizard::get_url();
|
70 |
|
71 |
if ( $published ) {
|
72 |
try {
|
readme.txt
CHANGED
@@ -3,7 +3,7 @@ Contributors: trrine, olethomas, bjornjohansen, dekode, automattic, facebook
|
|
3 |
Tags: instant articles, facebook, mobile
|
4 |
Requires at least: 4.3
|
5 |
Tested up to: 4.6
|
6 |
-
Stable tag: 3.
|
7 |
License: GPLv2 or later
|
8 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
9 |
|
@@ -85,6 +85,24 @@ Usually simply visiting the permalinks settings page in the WordPress dashboard
|
|
85 |
|
86 |
== Changelog ==
|
87 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
= 3.0.1 =
|
89 |
|
90 |
* Fix overzealous escaping
|
3 |
Tags: instant articles, facebook, mobile
|
4 |
Requires at least: 4.3
|
5 |
Tested up to: 4.6
|
6 |
+
Stable tag: 3.1
|
7 |
License: GPLv2 or later
|
8 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
9 |
|
85 |
|
86 |
== Changelog ==
|
87 |
|
88 |
+
= 3.1 =
|
89 |
+
* New on-boarding flow wizard
|
90 |
+
* Automattic URL claiming
|
91 |
+
* Submit for review from wizard
|
92 |
+
* Improved transformation rules
|
93 |
+
* Option to submit only articles without warnings
|
94 |
+
* Jetpack compatibility
|
95 |
+
* Added Jetpack carousel rules
|
96 |
+
* Compatibility layer for Get The Image plugin
|
97 |
+
* Fix for relative URL checking
|
98 |
+
* Fix for missing subtitles
|
99 |
+
* Fix for double call of wpautop
|
100 |
+
* Fix for loadHTML warnings
|
101 |
+
* Fix for get_cover_media function
|
102 |
+
* Fix to prevent publishing of password protected posts
|
103 |
+
|
104 |
+
props diegoquinteiro everton-rosario gemedet jacobarriola menzow rinatkhaziev srtfisher
|
105 |
+
|
106 |
= 3.0.1 =
|
107 |
|
108 |
* Fix overzealous escaping
|
rules-configuration.json
CHANGED
@@ -63,8 +63,8 @@
|
|
63 |
"class": "PassThroughRule",
|
64 |
"selector": "blockquote p"
|
65 |
}, {
|
66 |
-
"class": "
|
67 |
-
"selector": "
|
68 |
"properties": {
|
69 |
"image.url": {
|
70 |
"type": "string",
|
@@ -142,21 +142,60 @@
|
|
142 |
"interactive.iframe" : {
|
143 |
"type" : "children",
|
144 |
"selector" : "iframe"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
145 |
},
|
146 |
-
"interactive.
|
147 |
-
"type" : "
|
148 |
-
"selector" : "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
149 |
}
|
150 |
}
|
151 |
}, {
|
152 |
"class": "InteractiveRule",
|
153 |
-
"selector" : "//
|
154 |
"properties" : {
|
155 |
"interactive.url" : {
|
156 |
"type" : "string",
|
157 |
"selector" : "iframe",
|
158 |
"attribute": "src"
|
159 |
},
|
|
|
|
|
|
|
|
|
|
|
160 |
"interactive.width" : {
|
161 |
"type" : "int",
|
162 |
"selector" : "iframe",
|
@@ -166,27 +205,92 @@
|
|
166 |
"type" : "int",
|
167 |
"selector" : "iframe",
|
168 |
"attribute": "height"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
169 |
},
|
170 |
"interactive.iframe" : {
|
171 |
"type" : "children",
|
172 |
"selector" : "iframe"
|
173 |
},
|
174 |
-
"interactive.
|
175 |
-
"type" : "
|
176 |
-
"selector" : "
|
|
|
|
|
|
|
|
|
|
|
|
|
177 |
}
|
178 |
}
|
179 |
}, {
|
180 |
"class": "InteractiveRule",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
181 |
"selector" : "div.embed",
|
182 |
"properties" : {
|
183 |
"interactive.iframe" : {
|
184 |
"type" : "children",
|
185 |
"selector" : "div.embed"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
186 |
}
|
187 |
}
|
188 |
}, {
|
189 |
-
"class": "
|
190 |
"selector" : "div.interactive",
|
191 |
"properties" : {
|
192 |
"interactive.iframe" : {
|
@@ -198,13 +302,14 @@
|
|
198 |
"selector" : "iframe",
|
199 |
"attribute": "height"
|
200 |
},
|
201 |
-
"interactive.
|
202 |
-
"type" : "
|
203 |
-
"selector" : "iframe"
|
|
|
204 |
}
|
205 |
}
|
206 |
}, {
|
207 |
-
"class": "
|
208 |
"selector" : "//div[@class='embed' and iframe]",
|
209 |
"properties" : {
|
210 |
"interactive.url" : {
|
@@ -212,6 +317,11 @@
|
|
212 |
"selector" : "iframe",
|
213 |
"attribute": "src"
|
214 |
},
|
|
|
|
|
|
|
|
|
|
|
215 |
"interactive.width" : {
|
216 |
"type" : "int",
|
217 |
"selector" : "iframe",
|
@@ -224,23 +334,47 @@
|
|
224 |
}
|
225 |
}
|
226 |
}, {
|
227 |
-
"class": "
|
228 |
"selector" : "//div[@class='interactive' and iframe]",
|
229 |
"properties" : {
|
230 |
"interactive.url" : {
|
231 |
"type" : "string",
|
232 |
"selector" : "iframe",
|
233 |
"attribute": "src"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
234 |
}
|
235 |
}
|
236 |
}, {
|
237 |
-
"class": "
|
238 |
-
"selector": "
|
239 |
-
"properties": {
|
240 |
-
"
|
241 |
-
"type": "
|
242 |
-
"selector": "
|
243 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
244 |
}
|
245 |
}
|
246 |
}, {
|
@@ -290,14 +424,5 @@
|
|
290 |
"attribute": "type"
|
291 |
}
|
292 |
}
|
293 |
-
}
|
294 |
-
"class": "InteractiveRule",
|
295 |
-
"selector" : "table",
|
296 |
-
"properties" : {
|
297 |
-
"interactive.iframe" : {
|
298 |
-
"type" : "element",
|
299 |
-
"selector" : "table"
|
300 |
-
}
|
301 |
-
}
|
302 |
-
}]
|
303 |
}
|
63 |
"class": "PassThroughRule",
|
64 |
"selector": "blockquote p"
|
65 |
}, {
|
66 |
+
"class": "ImageInsideParagraphRule",
|
67 |
+
"selector": "img",
|
68 |
"properties": {
|
69 |
"image.url": {
|
70 |
"type": "string",
|
142 |
"interactive.iframe" : {
|
143 |
"type" : "children",
|
144 |
"selector" : "iframe"
|
145 |
+
}
|
146 |
+
}
|
147 |
+
}, {
|
148 |
+
"class": "InteractiveRule",
|
149 |
+
"selector" : "div.embed",
|
150 |
+
"properties" : {
|
151 |
+
"interactive.iframe" : {
|
152 |
+
"type" : "children",
|
153 |
+
"selector" : "div.embed"
|
154 |
},
|
155 |
+
"interactive.height" : {
|
156 |
+
"type" : "int",
|
157 |
+
"selector" : "iframe",
|
158 |
+
"attribute": "height"
|
159 |
+
},
|
160 |
+
"interactive.width" : {
|
161 |
+
"type" : "int",
|
162 |
+
"selector" : "iframe",
|
163 |
+
"attribute": "width"
|
164 |
+
}
|
165 |
+
}
|
166 |
+
}, {
|
167 |
+
"class": "InteractiveRule",
|
168 |
+
"selector" : "div.interactive",
|
169 |
+
"properties" : {
|
170 |
+
"interactive.iframe" : {
|
171 |
+
"type" : "children",
|
172 |
+
"selector" : "div.interactive"
|
173 |
+
},
|
174 |
+
"interactive.height" : {
|
175 |
+
"type" : "int",
|
176 |
+
"selector" : "iframe",
|
177 |
+
"attribute": "height"
|
178 |
+
},
|
179 |
+
"interactive.width" : {
|
180 |
+
"type" : "int",
|
181 |
+
"selector" : "iframe",
|
182 |
+
"attribute": "width"
|
183 |
}
|
184 |
}
|
185 |
}, {
|
186 |
"class": "InteractiveRule",
|
187 |
+
"selector" : "//div[@class='embed' and iframe]",
|
188 |
"properties" : {
|
189 |
"interactive.url" : {
|
190 |
"type" : "string",
|
191 |
"selector" : "iframe",
|
192 |
"attribute": "src"
|
193 |
},
|
194 |
+
"interactive.iframe" : {
|
195 |
+
"type" : "children",
|
196 |
+
"selector" : "iframe",
|
197 |
+
"attribute": "src"
|
198 |
+
},
|
199 |
"interactive.width" : {
|
200 |
"type" : "int",
|
201 |
"selector" : "iframe",
|
205 |
"type" : "int",
|
206 |
"selector" : "iframe",
|
207 |
"attribute": "height"
|
208 |
+
}
|
209 |
+
}
|
210 |
+
}, {
|
211 |
+
"class": "InteractiveRule",
|
212 |
+
"selector" : "//div[@class='interactive' and iframe]",
|
213 |
+
"properties" : {
|
214 |
+
"interactive.url" : {
|
215 |
+
"type" : "string",
|
216 |
+
"selector" : "iframe",
|
217 |
+
"attribute": "src"
|
218 |
},
|
219 |
"interactive.iframe" : {
|
220 |
"type" : "children",
|
221 |
"selector" : "iframe"
|
222 |
},
|
223 |
+
"interactive.height" : {
|
224 |
+
"type" : "int",
|
225 |
+
"selector" : "iframe",
|
226 |
+
"attribute": "height"
|
227 |
+
},
|
228 |
+
"interactive.width" : {
|
229 |
+
"type" : "int",
|
230 |
+
"selector" : "iframe",
|
231 |
+
"attribute": "width"
|
232 |
}
|
233 |
}
|
234 |
}, {
|
235 |
"class": "InteractiveRule",
|
236 |
+
"selector" : "table",
|
237 |
+
"properties" : {
|
238 |
+
"interactive.iframe" : {
|
239 |
+
"type" : "element",
|
240 |
+
"selector" : "table"
|
241 |
+
},
|
242 |
+
"interactive.height" : {
|
243 |
+
"type" : "int",
|
244 |
+
"selector" : "table",
|
245 |
+
"attribute": "height"
|
246 |
+
},
|
247 |
+
"interactive.width" : {
|
248 |
+
"type" : "int",
|
249 |
+
"selector" : "iframe",
|
250 |
+
"attribute": "width"
|
251 |
+
}
|
252 |
+
}
|
253 |
+
}, {
|
254 |
+
"class": "InteractiveInsideParagraphRule",
|
255 |
+
"selector" : "iframe",
|
256 |
+
"properties" : {
|
257 |
+
"interactive.url" : {
|
258 |
+
"type" : "string",
|
259 |
+
"selector" : "iframe",
|
260 |
+
"attribute": "src"
|
261 |
+
},
|
262 |
+
"interactive.height" : {
|
263 |
+
"type" : "int",
|
264 |
+
"selector" : "iframe",
|
265 |
+
"attribute": "height"
|
266 |
+
},
|
267 |
+
"interactive.width" : {
|
268 |
+
"type" : "int",
|
269 |
+
"selector" : "iframe",
|
270 |
+
"attribute": "width"
|
271 |
+
}
|
272 |
+
}
|
273 |
+
},{
|
274 |
+
"class": "InteractiveInsideParagraphRule",
|
275 |
"selector" : "div.embed",
|
276 |
"properties" : {
|
277 |
"interactive.iframe" : {
|
278 |
"type" : "children",
|
279 |
"selector" : "div.embed"
|
280 |
+
},
|
281 |
+
"interactive.height" : {
|
282 |
+
"type" : "int",
|
283 |
+
"selector" : "iframe",
|
284 |
+
"attribute": "height"
|
285 |
+
},
|
286 |
+
"interactive.width" : {
|
287 |
+
"type" : "int",
|
288 |
+
"selector" : "iframe",
|
289 |
+
"attribute": "width"
|
290 |
}
|
291 |
}
|
292 |
}, {
|
293 |
+
"class": "InteractiveInsideParagraphRule",
|
294 |
"selector" : "div.interactive",
|
295 |
"properties" : {
|
296 |
"interactive.iframe" : {
|
302 |
"selector" : "iframe",
|
303 |
"attribute": "height"
|
304 |
},
|
305 |
+
"interactive.width" : {
|
306 |
+
"type" : "int",
|
307 |
+
"selector" : "iframe",
|
308 |
+
"attribute": "width"
|
309 |
}
|
310 |
}
|
311 |
}, {
|
312 |
+
"class": "InteractiveInsideParagraphRule",
|
313 |
"selector" : "//div[@class='embed' and iframe]",
|
314 |
"properties" : {
|
315 |
"interactive.url" : {
|
317 |
"selector" : "iframe",
|
318 |
"attribute": "src"
|
319 |
},
|
320 |
+
"interactive.iframe" : {
|
321 |
+
"type" : "children",
|
322 |
+
"selector" : "iframe",
|
323 |
+
"attribute": "src"
|
324 |
+
},
|
325 |
"interactive.width" : {
|
326 |
"type" : "int",
|
327 |
"selector" : "iframe",
|
334 |
}
|
335 |
}
|
336 |
}, {
|
337 |
+
"class": "InteractiveInsideParagraphRule",
|
338 |
"selector" : "//div[@class='interactive' and iframe]",
|
339 |
"properties" : {
|
340 |
"interactive.url" : {
|
341 |
"type" : "string",
|
342 |
"selector" : "iframe",
|
343 |
"attribute": "src"
|
344 |
+
},
|
345 |
+
"interactive.iframe" : {
|
346 |
+
"type" : "children",
|
347 |
+
"selector" : "iframe",
|
348 |
+
"attribute": "src"
|
349 |
+
},
|
350 |
+
"interactive.height" : {
|
351 |
+
"type" : "int",
|
352 |
+
"selector" : "iframe",
|
353 |
+
"attribute": "height"
|
354 |
+
},
|
355 |
+
"interactive.width" : {
|
356 |
+
"type" : "int",
|
357 |
+
"selector" : "iframe",
|
358 |
+
"attribute": "width"
|
359 |
}
|
360 |
}
|
361 |
}, {
|
362 |
+
"class": "InteractiveInsideParagraphRule",
|
363 |
+
"selector" : "table",
|
364 |
+
"properties" : {
|
365 |
+
"interactive.iframe" : {
|
366 |
+
"type" : "element",
|
367 |
+
"selector" : "table"
|
368 |
+
},
|
369 |
+
"interactive.height" : {
|
370 |
+
"type" : "int",
|
371 |
+
"selector" : "table",
|
372 |
+
"attribute": "height"
|
373 |
+
},
|
374 |
+
"interactive.width" : {
|
375 |
+
"type" : "int",
|
376 |
+
"selector" : "table",
|
377 |
+
"attribute": "width"
|
378 |
}
|
379 |
}
|
380 |
}, {
|
424 |
"attribute": "type"
|
425 |
}
|
426 |
}
|
427 |
+
}]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
428 |
}
|
vendor/autoload.php
CHANGED
@@ -4,4 +4,4 @@
|
|
4 |
|
5 |
require_once __DIR__ . '/composer' . '/autoload_real.php';
|
6 |
|
7 |
-
return
|
4 |
|
5 |
require_once __DIR__ . '/composer' . '/autoload_real.php';
|
6 |
|
7 |
+
return ComposerAutoloaderInit84d77f682115366106947dee11e898d3::getLoader();
|
vendor/composer/autoload_real.php
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
// autoload_real.php @generated by Composer
|
4 |
|
5 |
-
class
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
@@ -19,15 +19,15 @@ class ComposerAutoloaderInit337744729a91b1fdea5f68820e3d1dfe
|
|
19 |
return self::$loader;
|
20 |
}
|
21 |
|
22 |
-
spl_autoload_register(array('
|
23 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
24 |
-
spl_autoload_unregister(array('
|
25 |
|
26 |
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION');
|
27 |
if ($useStaticLoader) {
|
28 |
require_once __DIR__ . '/autoload_static.php';
|
29 |
|
30 |
-
call_user_func(\Composer\Autoload\
|
31 |
} else {
|
32 |
$map = require __DIR__ . '/autoload_namespaces.php';
|
33 |
foreach ($map as $namespace => $path) {
|
@@ -48,19 +48,19 @@ class ComposerAutoloaderInit337744729a91b1fdea5f68820e3d1dfe
|
|
48 |
$loader->register(true);
|
49 |
|
50 |
if ($useStaticLoader) {
|
51 |
-
$includeFiles = Composer\Autoload\
|
52 |
} else {
|
53 |
$includeFiles = require __DIR__ . '/autoload_files.php';
|
54 |
}
|
55 |
foreach ($includeFiles as $fileIdentifier => $file) {
|
56 |
-
|
57 |
}
|
58 |
|
59 |
return $loader;
|
60 |
}
|
61 |
}
|
62 |
|
63 |
-
function
|
64 |
{
|
65 |
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
66 |
require $file;
|
2 |
|
3 |
// autoload_real.php @generated by Composer
|
4 |
|
5 |
+
class ComposerAutoloaderInit84d77f682115366106947dee11e898d3
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
19 |
return self::$loader;
|
20 |
}
|
21 |
|
22 |
+
spl_autoload_register(array('ComposerAutoloaderInit84d77f682115366106947dee11e898d3', 'loadClassLoader'), true, true);
|
23 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
24 |
+
spl_autoload_unregister(array('ComposerAutoloaderInit84d77f682115366106947dee11e898d3', 'loadClassLoader'));
|
25 |
|
26 |
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION');
|
27 |
if ($useStaticLoader) {
|
28 |
require_once __DIR__ . '/autoload_static.php';
|
29 |
|
30 |
+
call_user_func(\Composer\Autoload\ComposerStaticInit84d77f682115366106947dee11e898d3::getInitializer($loader));
|
31 |
} else {
|
32 |
$map = require __DIR__ . '/autoload_namespaces.php';
|
33 |
foreach ($map as $namespace => $path) {
|
48 |
$loader->register(true);
|
49 |
|
50 |
if ($useStaticLoader) {
|
51 |
+
$includeFiles = Composer\Autoload\ComposerStaticInit84d77f682115366106947dee11e898d3::$files;
|
52 |
} else {
|
53 |
$includeFiles = require __DIR__ . '/autoload_files.php';
|
54 |
}
|
55 |
foreach ($includeFiles as $fileIdentifier => $file) {
|
56 |
+
composerRequire84d77f682115366106947dee11e898d3($fileIdentifier, $file);
|
57 |
}
|
58 |
|
59 |
return $loader;
|
60 |
}
|
61 |
}
|
62 |
|
63 |
+
function composerRequire84d77f682115366106947dee11e898d3($fileIdentifier, $file)
|
64 |
{
|
65 |
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
66 |
require $file;
|
vendor/composer/autoload_static.php
CHANGED
@@ -4,7 +4,7 @@
|
|
4 |
|
5 |
namespace Composer\Autoload;
|
6 |
|
7 |
-
class
|
8 |
{
|
9 |
public static $files = array (
|
10 |
'7e702cccdb9dd904f2ccf22e5f37abae' => __DIR__ . '/..' . '/facebook/php-sdk-v4/src/Facebook/polyfills.php',
|
@@ -122,9 +122,9 @@ class ComposerStaticInit337744729a91b1fdea5f68820e3d1dfe
|
|
122 |
public static function getInitializer(ClassLoader $loader)
|
123 |
{
|
124 |
return \Closure::bind(function () use ($loader) {
|
125 |
-
$loader->prefixLengthsPsr4 =
|
126 |
-
$loader->prefixDirsPsr4 =
|
127 |
-
$loader->classMap =
|
128 |
|
129 |
}, null, ClassLoader::class);
|
130 |
}
|
4 |
|
5 |
namespace Composer\Autoload;
|
6 |
|
7 |
+
class ComposerStaticInit84d77f682115366106947dee11e898d3
|
8 |
{
|
9 |
public static $files = array (
|
10 |
'7e702cccdb9dd904f2ccf22e5f37abae' => __DIR__ . '/..' . '/facebook/php-sdk-v4/src/Facebook/polyfills.php',
|
122 |
public static function getInitializer(ClassLoader $loader)
|
123 |
{
|
124 |
return \Closure::bind(function () use ($loader) {
|
125 |
+
$loader->prefixLengthsPsr4 = ComposerStaticInit84d77f682115366106947dee11e898d3::$prefixLengthsPsr4;
|
126 |
+
$loader->prefixDirsPsr4 = ComposerStaticInit84d77f682115366106947dee11e898d3::$prefixDirsPsr4;
|
127 |
+
$loader->classMap = ComposerStaticInit84d77f682115366106947dee11e898d3::$classMap;
|
128 |
|
129 |
}, null, ClassLoader::class);
|
130 |
}
|
vendor/composer/installed.json
CHANGED
@@ -33,17 +33,17 @@
|
|
33 |
},
|
34 |
{
|
35 |
"name": "facebook/php-sdk-v4",
|
36 |
-
"version": "5.
|
37 |
-
"version_normalized": "5.
|
38 |
"source": {
|
39 |
"type": "git",
|
40 |
-
"url": "https://github.com/facebook/
|
41 |
-
"reference": "
|
42 |
},
|
43 |
"dist": {
|
44 |
"type": "zip",
|
45 |
-
"url": "https://api.github.com/repos/facebook/
|
46 |
-
"reference": "
|
47 |
"shasum": ""
|
48 |
},
|
49 |
"require": {
|
@@ -57,7 +57,7 @@
|
|
57 |
"suggest": {
|
58 |
"guzzlehttp/guzzle": "Allows for implementation of the Guzzle HTTP client"
|
59 |
},
|
60 |
-
"time": "2016-
|
61 |
"type": "library",
|
62 |
"extra": {
|
63 |
"branch-alias": {
|
@@ -88,12 +88,13 @@
|
|
88 |
"keywords": [
|
89 |
"facebook",
|
90 |
"sdk"
|
91 |
-
]
|
|
|
92 |
},
|
93 |
{
|
94 |
"name": "symfony/css-selector",
|
95 |
-
"version": "v2.8.
|
96 |
-
"version_normalized": "2.8.
|
97 |
"source": {
|
98 |
"type": "git",
|
99 |
"url": "https://github.com/symfony/css-selector.git",
|
@@ -147,17 +148,17 @@
|
|
147 |
},
|
148 |
{
|
149 |
"name": "facebook/facebook-instant-articles-sdk-php",
|
150 |
-
"version": "v1.
|
151 |
-
"version_normalized": "1.
|
152 |
"source": {
|
153 |
"type": "git",
|
154 |
"url": "https://github.com/facebook/facebook-instant-articles-sdk-php.git",
|
155 |
-
"reference": "
|
156 |
},
|
157 |
"dist": {
|
158 |
"type": "zip",
|
159 |
-
"url": "https://api.github.com/repos/facebook/facebook-instant-articles-sdk-php/zipball/
|
160 |
-
"reference": "
|
161 |
"shasum": ""
|
162 |
},
|
163 |
"require": {
|
@@ -171,7 +172,7 @@
|
|
171 |
"phpunit/phpunit": "^4.8",
|
172 |
"squizlabs/php_codesniffer": "^2.6.0"
|
173 |
},
|
174 |
-
"time": "2016-
|
175 |
"type": "library",
|
176 |
"installation-source": "dist",
|
177 |
"autoload": {
|
33 |
},
|
34 |
{
|
35 |
"name": "facebook/php-sdk-v4",
|
36 |
+
"version": "5.3.1",
|
37 |
+
"version_normalized": "5.3.1.0",
|
38 |
"source": {
|
39 |
"type": "git",
|
40 |
+
"url": "https://github.com/facebook/php-graph-sdk.git",
|
41 |
+
"reference": "7ed1ecdae6a5b2f8b8f60e132d06594b39b16fb1"
|
42 |
},
|
43 |
"dist": {
|
44 |
"type": "zip",
|
45 |
+
"url": "https://api.github.com/repos/facebook/php-graph-sdk/zipball/7ed1ecdae6a5b2f8b8f60e132d06594b39b16fb1",
|
46 |
+
"reference": "7ed1ecdae6a5b2f8b8f60e132d06594b39b16fb1",
|
47 |
"shasum": ""
|
48 |
},
|
49 |
"require": {
|
57 |
"suggest": {
|
58 |
"guzzlehttp/guzzle": "Allows for implementation of the Guzzle HTTP client"
|
59 |
},
|
60 |
+
"time": "2016-08-09 11:32:26",
|
61 |
"type": "library",
|
62 |
"extra": {
|
63 |
"branch-alias": {
|
88 |
"keywords": [
|
89 |
"facebook",
|
90 |
"sdk"
|
91 |
+
],
|
92 |
+
"abandoned": "facebook/graph-sdk"
|
93 |
},
|
94 |
{
|
95 |
"name": "symfony/css-selector",
|
96 |
+
"version": "v2.8.9",
|
97 |
+
"version_normalized": "2.8.9.0",
|
98 |
"source": {
|
99 |
"type": "git",
|
100 |
"url": "https://github.com/symfony/css-selector.git",
|
148 |
},
|
149 |
{
|
150 |
"name": "facebook/facebook-instant-articles-sdk-php",
|
151 |
+
"version": "v1.4.0",
|
152 |
+
"version_normalized": "1.4.0.0",
|
153 |
"source": {
|
154 |
"type": "git",
|
155 |
"url": "https://github.com/facebook/facebook-instant-articles-sdk-php.git",
|
156 |
+
"reference": "c46c25b2d1c4100885383667cde1a863440aff2a"
|
157 |
},
|
158 |
"dist": {
|
159 |
"type": "zip",
|
160 |
+
"url": "https://api.github.com/repos/facebook/facebook-instant-articles-sdk-php/zipball/c46c25b2d1c4100885383667cde1a863440aff2a",
|
161 |
+
"reference": "c46c25b2d1c4100885383667cde1a863440aff2a",
|
162 |
"shasum": ""
|
163 |
},
|
164 |
"require": {
|
172 |
"phpunit/phpunit": "^4.8",
|
173 |
"squizlabs/php_codesniffer": "^2.6.0"
|
174 |
},
|
175 |
+
"time": "2016-08-13 06:34:04",
|
176 |
"type": "library",
|
177 |
"installation-source": "dist",
|
178 |
"autoload": {
|
vendor/facebook/facebook-instant-articles-sdk-php/.gitignore
DELETED
@@ -1,4 +0,0 @@
|
|
1 |
-
composer.phar
|
2 |
-
/vendor/
|
3 |
-
*.ignored
|
4 |
-
**/IgnoredTest.php
|
|
|
|
|
|
|
|
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Client/Client.php
CHANGED
@@ -242,4 +242,42 @@ class Client
|
|
242 |
|
243 |
return $articleURLs;
|
244 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
245 |
}
|
242 |
|
243 |
return $articleURLs;
|
244 |
}
|
245 |
+
|
246 |
+
/**
|
247 |
+
* Claims an URL for the page
|
248 |
+
*
|
249 |
+
* @param string $url The root URL of the site
|
250 |
+
*/
|
251 |
+
public function claimURL($url)
|
252 |
+
{
|
253 |
+
// Remove protocol from the URL
|
254 |
+
$url = preg_replace('/^https?:\/\//i', '', $url);
|
255 |
+
$response = $this->facebook->post($this->pageID . '/claimed_urls?url=' . urlencode($url));
|
256 |
+
$node = $response->getGraphNode();
|
257 |
+
$error = $node->getField('error');
|
258 |
+
$success = $node->getField('success');
|
259 |
+
if ($error) {
|
260 |
+
throw new ClientException($error['error_user_msg']);
|
261 |
+
}
|
262 |
+
if (!$success) {
|
263 |
+
throw new ClientException('Could not claim the URL');
|
264 |
+
}
|
265 |
+
}
|
266 |
+
|
267 |
+
/**
|
268 |
+
* Submits the page for review
|
269 |
+
*/
|
270 |
+
public function submitForReview()
|
271 |
+
{
|
272 |
+
$response = $this->facebook->post($this->pageID . '/?instant_articles_submit_for_review=true');
|
273 |
+
$node = $response->getGraphNode();
|
274 |
+
$error = $node->getField('error');
|
275 |
+
$success = $node->getField('success');
|
276 |
+
if ($error) {
|
277 |
+
throw new ClientException($error['error_user_msg']);
|
278 |
+
}
|
279 |
+
if (!$success) {
|
280 |
+
throw new ClientException('Could not submit for review');
|
281 |
+
}
|
282 |
+
}
|
283 |
}
|
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Client/Helper.php
CHANGED
@@ -89,7 +89,7 @@ class Helper
|
|
89 |
// Request the list of pages and associated page tokens that are
|
90 |
// connected to this user
|
91 |
try {
|
92 |
-
$response = $this->facebook->get('/me/accounts?fields=name,id,access_token,supports_instant_articles');
|
93 |
} catch (FacebookResponseException $e) {
|
94 |
throw new FacebookSDKException('Graph API returned an error: ' . $e->getMessage());
|
95 |
}
|
89 |
// Request the list of pages and associated page tokens that are
|
90 |
// connected to this user
|
91 |
try {
|
92 |
+
$response = $this->facebook->get('/me/accounts?fields=name,id,access_token,supports_instant_articles,picture');
|
93 |
} catch (FacebookResponseException $e) {
|
94 |
throw new FacebookSDKException('Graph API returned an error: ' . $e->getMessage());
|
95 |
}
|
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/InstantArticle.php
CHANGED
@@ -34,7 +34,7 @@ use Facebook\InstantArticles\Validators\Type;
|
|
34 |
|
35 |
class InstantArticle extends Element implements Container, InstantArticleInterface
|
36 |
{
|
37 |
-
const CURRENT_VERSION = '1.
|
38 |
|
39 |
/**
|
40 |
* The meta properties that are used on <head>
|
@@ -231,6 +231,50 @@ class InstantArticle extends Element implements Container, InstantArticleInterfa
|
|
231 |
return $this;
|
232 |
}
|
233 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
234 |
/**
|
235 |
* @return Header header element from the InstantArticle
|
236 |
*/
|
34 |
|
35 |
class InstantArticle extends Element implements Container, InstantArticleInterface
|
36 |
{
|
37 |
+
const CURRENT_VERSION = '1.4.0';
|
38 |
|
39 |
/**
|
40 |
* The meta properties that are used on <head>
|
231 |
return $this;
|
232 |
}
|
233 |
|
234 |
+
/**
|
235 |
+
* Adds new child elements to the front of this InstantArticle
|
236 |
+
*
|
237 |
+
* @param Element to be added to this Article.
|
238 |
+
*
|
239 |
+
* @return $this
|
240 |
+
*/
|
241 |
+
public function unshiftChild($child)
|
242 |
+
{
|
243 |
+
Type::enforce(
|
244 |
+
$child,
|
245 |
+
[
|
246 |
+
Ad::getClassName(),
|
247 |
+
Analytics::getClassName(),
|
248 |
+
AnimatedGIF::getClassName(),
|
249 |
+
Audio::getClassName(),
|
250 |
+
Blockquote::getClassName(),
|
251 |
+
Image::getClassName(),
|
252 |
+
H1::getClassName(),
|
253 |
+
H2::getClassName(),
|
254 |
+
Interactive::getClassName(),
|
255 |
+
ListElement::getClassName(),
|
256 |
+
Map::getClassName(),
|
257 |
+
Paragraph::getClassName(),
|
258 |
+
Pullquote::getClassName(),
|
259 |
+
RelatedArticles::getClassName(),
|
260 |
+
Slideshow::getClassName(),
|
261 |
+
SocialEmbed::getClassName(),
|
262 |
+
Video::getClassName()
|
263 |
+
]
|
264 |
+
);
|
265 |
+
array_unshift($this->children, $child);
|
266 |
+
|
267 |
+
return $this;
|
268 |
+
}
|
269 |
+
|
270 |
+
/**
|
271 |
+
* @return string canonicalURL from the InstantArticle
|
272 |
+
*/
|
273 |
+
public function getCanonicalURL()
|
274 |
+
{
|
275 |
+
return $this->canonicalURL;
|
276 |
+
}
|
277 |
+
|
278 |
/**
|
279 |
* @return Header header element from the InstantArticle
|
280 |
*/
|
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Elements/Interactive.php
CHANGED
@@ -250,7 +250,7 @@ class Interactive extends ElementWithHTML implements Container
|
|
250 |
*/
|
251 |
public function isValid()
|
252 |
{
|
253 |
-
return !Type::isTextEmpty($this->source)
|
254 |
}
|
255 |
|
256 |
/**
|
250 |
*/
|
251 |
public function isValid()
|
252 |
{
|
253 |
+
return $this->html || (!Type::isTextEmpty($this->source) && $this->height && $this->width);
|
254 |
}
|
255 |
|
256 |
/**
|
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Parser/instant-articles-rules.json
CHANGED
@@ -444,6 +444,22 @@
|
|
444 |
"selector" : "figure[data-feedback*='fb:likes']",
|
445 |
"attribute": "data-feedback"
|
446 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
447 |
"image.comments" : {
|
448 |
"type" : "exists",
|
449 |
"selector" : "figure[data-feedback*='fb:comments']",
|
444 |
"selector" : "figure[data-feedback*='fb:likes']",
|
445 |
"attribute": "data-feedback"
|
446 |
},
|
447 |
+
"aspect-fit": {
|
448 |
+
"type": "exists",
|
449 |
+
"selector" : "figure[data-mode=aspect-fit]"
|
450 |
+
},
|
451 |
+
"aspect-fit-only": {
|
452 |
+
"type": "exists",
|
453 |
+
"selector" : "figure[data-mode=aspect-fit-only]"
|
454 |
+
},
|
455 |
+
"fullscreen": {
|
456 |
+
"type": "exists",
|
457 |
+
"selector" : "figure[data-mode=fullscreen]"
|
458 |
+
},
|
459 |
+
"non-interactive": {
|
460 |
+
"type": "exists",
|
461 |
+
"selector" : "figure[data-mode=non-interactive]"
|
462 |
+
},
|
463 |
"image.comments" : {
|
464 |
"type" : "exists",
|
465 |
"selector" : "figure[data-feedback*='fb:comments']",
|
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Getters/GetterFactory.php
CHANGED
@@ -16,6 +16,7 @@ class GetterFactory
|
|
16 |
const TYPE_ELEMENT_GETTER = 'element';
|
17 |
const TYPE_NEXTSIBLING_GETTER = 'sibling';
|
18 |
const TYPE_EXISTS_GETTER = 'exists';
|
|
|
19 |
const TYPE_XPATH_GETTER = 'xpath';
|
20 |
|
21 |
/**
|
@@ -32,6 +33,7 @@ class GetterFactory
|
|
32 |
* @see ElementGetter
|
33 |
* @see NextSiblingGetter
|
34 |
* @see ExistsGetter
|
|
|
35 |
* @see XpathGetter
|
36 |
*
|
37 |
* @param string[] $getter_configuration that maps the properties for getter
|
@@ -47,6 +49,7 @@ class GetterFactory
|
|
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 |
|
16 |
const TYPE_ELEMENT_GETTER = 'element';
|
17 |
const TYPE_NEXTSIBLING_GETTER = 'sibling';
|
18 |
const TYPE_EXISTS_GETTER = 'exists';
|
19 |
+
const TYPE_JSON_GETTER = 'json';
|
20 |
const TYPE_XPATH_GETTER = 'xpath';
|
21 |
|
22 |
/**
|
33 |
* @see ElementGetter
|
34 |
* @see NextSiblingGetter
|
35 |
* @see ExistsGetter
|
36 |
+
* @see JSONGetter
|
37 |
* @see XpathGetter
|
38 |
*
|
39 |
* @param string[] $getter_configuration that maps the properties for getter
|
49 |
self::TYPE_ELEMENT_GETTER => ElementGetter::getClassName(),
|
50 |
self::TYPE_NEXTSIBLING_GETTER => NextSiblingGetter::getClassName(),
|
51 |
self::TYPE_EXISTS_GETTER => ExistsGetter::getClassName(),
|
52 |
+
self::TYPE_JSON_GETTER => JSONGetter::getClassName(),
|
53 |
self::TYPE_XPATH_GETTER => XpathGetter::getClassName()
|
54 |
];
|
55 |
|
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Getters/JSONGetter.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\Getters;
|
10 |
+
|
11 |
+
use Facebook\InstantArticles\Validators\Type;
|
12 |
+
|
13 |
+
class JSONGetter extends ChildrenGetter
|
14 |
+
{
|
15 |
+
/**
|
16 |
+
* @var string
|
17 |
+
*/
|
18 |
+
protected $attribute;
|
19 |
+
|
20 |
+
public function createFrom($properties)
|
21 |
+
{
|
22 |
+
if (isset($properties['selector'])) {
|
23 |
+
$this->withSelector($properties['selector']);
|
24 |
+
}
|
25 |
+
if (isset($properties['attribute'])) {
|
26 |
+
$this->withAttribute($properties['attribute']);
|
27 |
+
}
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* @param string $attribute
|
32 |
+
*
|
33 |
+
* @return $this
|
34 |
+
*/
|
35 |
+
public function withAttribute($attribute)
|
36 |
+
{
|
37 |
+
Type::enforce($attribute, Type::STRING);
|
38 |
+
$this->attribute = $attribute;
|
39 |
+
|
40 |
+
return $this;
|
41 |
+
}
|
42 |
+
|
43 |
+
public function get($node)
|
44 |
+
{
|
45 |
+
$content = null;
|
46 |
+
|
47 |
+
Type::enforce($node, 'DOMNode');
|
48 |
+
$elements = self::findAll($node, $this->selector);
|
49 |
+
if (!empty($elements) && $elements->item(0)) {
|
50 |
+
$element = $elements->item(0);
|
51 |
+
if ($this->attribute) {
|
52 |
+
$content = $element->getAttribute($this->attribute);
|
53 |
+
} else {
|
54 |
+
$content = $element->textContent;
|
55 |
+
}
|
56 |
+
}
|
57 |
+
|
58 |
+
if (!Type::isTextEmpty($content)) {
|
59 |
+
return json_decode($content, true);
|
60 |
+
}
|
61 |
+
return null;
|
62 |
+
}
|
63 |
+
}
|
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/Compat/JetpackSlideshowRule.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\Transformer\Rules\Compat;
|
10 |
+
|
11 |
+
use Facebook\InstantArticles\Transformer\Rules\ConfigurationSelectorRule;
|
12 |
+
use Facebook\InstantArticles\Validators\Type;
|
13 |
+
use Facebook\InstantArticles\Elements\InstantArticle;
|
14 |
+
use Facebook\InstantArticles\Elements\Image;
|
15 |
+
use Facebook\InstantArticles\Elements\Caption;
|
16 |
+
use Facebook\InstantArticles\Elements\Slideshow;
|
17 |
+
|
18 |
+
class JetpackSlideshowRule extends ConfigurationSelectorRule
|
19 |
+
{
|
20 |
+
const PROPERTY_JETPACK_DATA_GALLERY = 'jetpack.data-gallery';
|
21 |
+
|
22 |
+
public function getContextClass()
|
23 |
+
{
|
24 |
+
return InstantArticle::getClassName();
|
25 |
+
}
|
26 |
+
|
27 |
+
public static function create()
|
28 |
+
{
|
29 |
+
return new JetpackSlideshowRule();
|
30 |
+
}
|
31 |
+
|
32 |
+
public static function createFrom($configuration)
|
33 |
+
{
|
34 |
+
$slideshow_rule = self::create();
|
35 |
+
$slideshow_rule->withSelector($configuration['selector']);
|
36 |
+
|
37 |
+
$slideshow_rule->withProperties(
|
38 |
+
[
|
39 |
+
self::PROPERTY_JETPACK_DATA_GALLERY
|
40 |
+
],
|
41 |
+
$configuration
|
42 |
+
);
|
43 |
+
|
44 |
+
return $slideshow_rule;
|
45 |
+
}
|
46 |
+
|
47 |
+
public function apply($transformer, $instant_article, $node)
|
48 |
+
{
|
49 |
+
// Builds the slideshow
|
50 |
+
$slideshow = Slideshow::create();
|
51 |
+
$instant_article->addChild($slideshow);
|
52 |
+
|
53 |
+
$gallery = $this->getProperty(self::PROPERTY_JETPACK_DATA_GALLERY, $node);
|
54 |
+
|
55 |
+
if ($gallery && isset($gallery)) {
|
56 |
+
foreach ($gallery as $gallery_image) {
|
57 |
+
// Constructs Image if it contains URL
|
58 |
+
if (!Type::isTextEmpty($gallery_image['src'])) {
|
59 |
+
$image = Image::create();
|
60 |
+
$image->withURL($gallery_image['src']);
|
61 |
+
|
62 |
+
// Constructs Caption element when present in the JSON
|
63 |
+
if (!Type::isTextEmpty($gallery_image['caption'])) {
|
64 |
+
$caption = Caption::create();
|
65 |
+
$caption->appendText($gallery_image['caption']);
|
66 |
+
$image->withCaption($caption);
|
67 |
+
}
|
68 |
+
$slideshow->addImage($image);
|
69 |
+
}
|
70 |
+
}
|
71 |
+
}
|
72 |
+
|
73 |
+
$transformer->transform($slideshow, $node);
|
74 |
+
|
75 |
+
return $instant_article;
|
76 |
+
}
|
77 |
+
}
|
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/ConfigurationSelectorRule.php
CHANGED
@@ -130,7 +130,7 @@ abstract class ConfigurationSelectorRule extends Rule
|
|
130 |
}
|
131 |
}
|
132 |
}
|
133 |
-
|
134 |
return false;
|
135 |
}
|
136 |
|
130 |
}
|
131 |
}
|
132 |
}
|
133 |
+
|
134 |
return false;
|
135 |
}
|
136 |
|
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/H1Rule.php
CHANGED
@@ -11,7 +11,7 @@ namespace Facebook\InstantArticles\Transformer\Rules;
|
|
11 |
use Facebook\InstantArticles\Elements\Header;
|
12 |
use Facebook\InstantArticles\Elements\Caption;
|
13 |
use Facebook\InstantArticles\Elements\H1;
|
14 |
-
use Facebook\InstantArticles\Elements\
|
15 |
use Facebook\InstantArticles\Validators\Type;
|
16 |
|
17 |
class H1Rule extends ConfigurationSelectorRule
|
11 |
use Facebook\InstantArticles\Elements\Header;
|
12 |
use Facebook\InstantArticles\Elements\Caption;
|
13 |
use Facebook\InstantArticles\Elements\H1;
|
14 |
+
use Facebook\InstantArticles\Elements\InstantArticle;
|
15 |
use Facebook\InstantArticles\Validators\Type;
|
16 |
|
17 |
class H1Rule extends ConfigurationSelectorRule
|
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/H2Rule.php
CHANGED
@@ -11,7 +11,7 @@ namespace Facebook\InstantArticles\Transformer\Rules;
|
|
11 |
use Facebook\InstantArticles\Elements\Header;
|
12 |
use Facebook\InstantArticles\Elements\Caption;
|
13 |
use Facebook\InstantArticles\Elements\H2;
|
14 |
-
use Facebook\InstantArticles\Elements\
|
15 |
use Facebook\InstantArticles\Validators\Type;
|
16 |
|
17 |
class H2Rule extends ConfigurationSelectorRule
|
11 |
use Facebook\InstantArticles\Elements\Header;
|
12 |
use Facebook\InstantArticles\Elements\Caption;
|
13 |
use Facebook\InstantArticles\Elements\H2;
|
14 |
+
use Facebook\InstantArticles\Elements\InstantArticle;
|
15 |
use Facebook\InstantArticles\Validators\Type;
|
16 |
|
17 |
class H2Rule extends ConfigurationSelectorRule
|
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/ImageRule.php
CHANGED
@@ -18,6 +18,11 @@ class ImageRule extends ConfigurationSelectorRule
|
|
18 |
const PROPERTY_LIKE = 'image.like';
|
19 |
const PROPERTY_COMMENTS = 'image.comments';
|
20 |
|
|
|
|
|
|
|
|
|
|
|
21 |
public function getContextClass()
|
22 |
{
|
23 |
return InstantArticle::getClassName();
|
@@ -37,7 +42,11 @@ class ImageRule extends ConfigurationSelectorRule
|
|
37 |
[
|
38 |
self::PROPERTY_IMAGE_URL,
|
39 |
self::PROPERTY_LIKE,
|
40 |
-
self::PROPERTY_COMMENTS
|
|
|
|
|
|
|
|
|
41 |
],
|
42 |
$configuration
|
43 |
);
|
@@ -65,6 +74,16 @@ class ImageRule extends ConfigurationSelectorRule
|
|
65 |
);
|
66 |
}
|
67 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
68 |
if ($this->getProperty(self::PROPERTY_LIKE, $node)) {
|
69 |
$image->enableLike();
|
70 |
}
|
18 |
const PROPERTY_LIKE = 'image.like';
|
19 |
const PROPERTY_COMMENTS = 'image.comments';
|
20 |
|
21 |
+
const ASPECT_FIT = 'aspect-fit';
|
22 |
+
const ASPECT_FIT_ONLY = 'aspect-fit-only';
|
23 |
+
const FULLSCREEN = 'fullscreen';
|
24 |
+
const NON_INTERACTIVE = 'non-interactive';
|
25 |
+
|
26 |
public function getContextClass()
|
27 |
{
|
28 |
return InstantArticle::getClassName();
|
42 |
[
|
43 |
self::PROPERTY_IMAGE_URL,
|
44 |
self::PROPERTY_LIKE,
|
45 |
+
self::PROPERTY_COMMENTS,
|
46 |
+
self::ASPECT_FIT,
|
47 |
+
self::ASPECT_FIT_ONLY,
|
48 |
+
self::FULLSCREEN,
|
49 |
+
self::NON_INTERACTIVE
|
50 |
],
|
51 |
$configuration
|
52 |
);
|
74 |
);
|
75 |
}
|
76 |
|
77 |
+
if ($this->getProperty(Image::ASPECT_FIT, $node)) {
|
78 |
+
$image->withPresentation(Image::ASPECT_FIT);
|
79 |
+
} elseif ($this->getProperty(Image::ASPECT_FIT_ONLY, $node)) {
|
80 |
+
$image->withPresentation(Image::ASPECT_FIT_ONLY);
|
81 |
+
} elseif ($this->getProperty(Image::FULLSCREEN, $node)) {
|
82 |
+
$image->withPresentation(Image::FULLSCREEN);
|
83 |
+
} elseif ($this->getProperty(Image::NON_INTERACTIVE, $node)) {
|
84 |
+
$image->withPresentation(Image::NON_INTERACTIVE);
|
85 |
+
}
|
86 |
+
|
87 |
if ($this->getProperty(self::PROPERTY_LIKE, $node)) {
|
88 |
$image->enableLike();
|
89 |
}
|
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/InteractiveInsideParagraphRule.php
ADDED
@@ -0,0 +1,119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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\Paragraph;
|
13 |
+
use Facebook\InstantArticles\Transformer\Warnings\InvalidSelector;
|
14 |
+
use Facebook\InstantArticles\Transformer\Warnings\NoRootInstantArticleFoundWarning;
|
15 |
+
|
16 |
+
class InteractiveInsideParagraphRule 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 |
+
const PROPERTY_WIDTH = 'interactive.width';
|
24 |
+
|
25 |
+
public function getContextClass()
|
26 |
+
{
|
27 |
+
return Paragraph::getClassName();
|
28 |
+
}
|
29 |
+
|
30 |
+
public static function create()
|
31 |
+
{
|
32 |
+
return new InteractiveInsideParagraphRule();
|
33 |
+
}
|
34 |
+
|
35 |
+
public static function createFrom($configuration)
|
36 |
+
{
|
37 |
+
$interactive_rule = self::create();
|
38 |
+
$interactive_rule->withSelector($configuration['selector']);
|
39 |
+
|
40 |
+
$interactive_rule->withProperties(
|
41 |
+
[
|
42 |
+
self::PROPERTY_IFRAME,
|
43 |
+
self::PROPERTY_URL,
|
44 |
+
self::PROPERTY_WIDTH_NO_MARGIN,
|
45 |
+
self::PROPERTY_WIDTH_COLUMN_WIDTH,
|
46 |
+
self::PROPERTY_WIDTH,
|
47 |
+
self::PROPERTY_HEIGHT
|
48 |
+
],
|
49 |
+
$configuration
|
50 |
+
);
|
51 |
+
|
52 |
+
return $interactive_rule;
|
53 |
+
}
|
54 |
+
|
55 |
+
public function apply($transformer, $context, $node)
|
56 |
+
{
|
57 |
+
$interactive = Interactive::create();
|
58 |
+
|
59 |
+
// Builds the interactive
|
60 |
+
$iframe = $this->getProperty(self::PROPERTY_IFRAME, $node);
|
61 |
+
$url = $this->getProperty(self::PROPERTY_URL, $node);
|
62 |
+
if ($iframe) {
|
63 |
+
$interactive->withHTML($iframe);
|
64 |
+
}
|
65 |
+
if ($url) {
|
66 |
+
$interactive->withSource($url);
|
67 |
+
}
|
68 |
+
|
69 |
+
if ($this->getProperty(self::PROPERTY_WIDTH_COLUMN_WIDTH, $node)) {
|
70 |
+
$interactive->withMargin(Interactive::COLUMN_WIDTH);
|
71 |
+
} else {
|
72 |
+
$interactive->withMargin(Interactive::NO_MARGIN);
|
73 |
+
}
|
74 |
+
|
75 |
+
$width = $this->getProperty(self::PROPERTY_WIDTH, $node);
|
76 |
+
if ($width) {
|
77 |
+
$interactive->withWidth($width);
|
78 |
+
}
|
79 |
+
|
80 |
+
$height = $this->getProperty(self::PROPERTY_HEIGHT, $node);
|
81 |
+
if ($height) {
|
82 |
+
$interactive->withHeight($height);
|
83 |
+
}
|
84 |
+
|
85 |
+
|
86 |
+
if ($iframe || $url) {
|
87 |
+
$instant_article = $transformer->getInstantArticle();
|
88 |
+
if ($instant_article) {
|
89 |
+
$instant_article->addChild($interactive);
|
90 |
+
$context->disableEmptyValidation();
|
91 |
+
$context = Paragraph::create();
|
92 |
+
$context->disableEmptyValidation();
|
93 |
+
$instant_article->addChild($context);
|
94 |
+
} else {
|
95 |
+
$transformer->addWarning(
|
96 |
+
// This new error message should be something like:
|
97 |
+
// Could not transform Interactive, as no root InstantArticle was provided.
|
98 |
+
new NoRootInstantArticleFoundWarning(null, $node)
|
99 |
+
);
|
100 |
+
}
|
101 |
+
} else {
|
102 |
+
$transformer->addWarning(
|
103 |
+
new InvalidSelector(
|
104 |
+
self::PROPERTY_IFRAME,
|
105 |
+
$instant_article,
|
106 |
+
$node,
|
107 |
+
$this
|
108 |
+
)
|
109 |
+
);
|
110 |
+
}
|
111 |
+
|
112 |
+
$suppress_warnings = $transformer->suppress_warnings;
|
113 |
+
$transformer->suppress_warnings = true;
|
114 |
+
$transformer->transform($interactive, $node);
|
115 |
+
$transformer->suppress_warnings = $suppress_warnings;
|
116 |
+
|
117 |
+
return $context;
|
118 |
+
}
|
119 |
+
}
|
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/InteractiveRule.php
CHANGED
@@ -55,7 +55,7 @@ class InteractiveRule extends ConfigurationSelectorRule
|
|
55 |
{
|
56 |
$interactive = Interactive::create();
|
57 |
|
58 |
-
// Builds the
|
59 |
$iframe = $this->getProperty(self::PROPERTY_IFRAME, $node);
|
60 |
$url = $this->getProperty(self::PROPERTY_URL, $node);
|
61 |
if ($iframe) {
|
55 |
{
|
56 |
$interactive = Interactive::create();
|
57 |
|
58 |
+
// Builds the interactive
|
59 |
$iframe = $this->getProperty(self::PROPERTY_IFRAME, $node);
|
60 |
$url = $this->getProperty(self::PROPERTY_URL, $node);
|
61 |
if ($iframe) {
|
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Rules/Rule.php
CHANGED
@@ -23,9 +23,8 @@ abstract class Rule
|
|
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 === '
|
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.' />');
|
@@ -34,7 +33,7 @@ abstract class Rule
|
|
34 |
$log->debug('rule: '.get_class($this));
|
35 |
$log->debug('-------');
|
36 |
}
|
37 |
-
return
|
38 |
}
|
39 |
|
40 |
abstract public function matchesContext($context);
|
23 |
$log->debug('node matches: '.($matches_node ? 'MATCHES' : 'no match'));
|
24 |
$log->debug('rule: '.get_class($this));
|
25 |
$log->debug('-------');
|
|
|
26 |
}
|
27 |
+
if ($node->nodeName === 'iframe') {
|
28 |
$log->debug('context class: '.get_class($context));
|
29 |
$log->debug('context matches: '.($matches_context ? 'MATCHES' : 'no match'));
|
30 |
$log->debug('node name: <'.$node->nodeName.' />');
|
33 |
$log->debug('rule: '.get_class($this));
|
34 |
$log->debug('-------');
|
35 |
}
|
36 |
+
return $matches_context && $matches_node;
|
37 |
}
|
38 |
|
39 |
abstract public function matchesContext($context);
|
vendor/facebook/facebook-instant-articles-sdk-php/src/Facebook/InstantArticles/Transformer/Warnings/validator_warning_messages.ini
CHANGED
@@ -24,7 +24,7 @@ H3 = "This is a text container that must not be empty nor contain only whitespac
|
|
24 |
Header = "Header must have at least a title and/or Ad."
|
25 |
Image = "Image must have a URL."
|
26 |
InstantArticle = "InstantArticle relies on InstantArticleValidator."
|
27 |
-
Interactive = "Interactive must have
|
28 |
Italic = "This is a text container that must not be empty nor contain only whitespace characters such as spaces, tabs, new lines or ."
|
29 |
LineBreak = "LineBreak is always valid."
|
30 |
ListElement = "ListElement must have at least one of its ListItem valid."
|
24 |
Header = "Header must have at least a title and/or Ad."
|
25 |
Image = "Image must have a URL."
|
26 |
InstantArticle = "InstantArticle relies on InstantArticleValidator."
|
27 |
+
Interactive = "Interactive embeds must have valid positive integer width and height values for an empty HTML content. In Interactive elements with HTML content, the width/height properties are optional."
|
28 |
Italic = "This is a text container that must not be empty nor contain only whitespace characters such as spaces, tabs, new lines or ."
|
29 |
LineBreak = "LineBreak is always valid."
|
30 |
ListElement = "ListElement must have at least one of its ListItem valid."
|
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Client/ClientTest.php
CHANGED
@@ -630,4 +630,197 @@ class ClientTest extends \PHPUnit_Framework_TestCase
|
|
630 |
$result = $this->client->getArticlesURLs();
|
631 |
$this->assertEquals($expected, $result);
|
632 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
633 |
}
|
630 |
$result = $this->client->getArticlesURLs();
|
631 |
$this->assertEquals($expected, $result);
|
632 |
}
|
633 |
+
|
634 |
+
public function testClaimURL()
|
635 |
+
{
|
636 |
+
$url = 'example.com';
|
637 |
+
|
638 |
+
$serverResponseMock =
|
639 |
+
$this->getMockBuilder('Facebook\FacebookResponse')
|
640 |
+
->disableOriginalConstructor()
|
641 |
+
->getMock();
|
642 |
+
$graphNodeMock =
|
643 |
+
$this->getMockBuilder('Facebook\GraphNodes\GraphNode')
|
644 |
+
->disableOriginalConstructor()
|
645 |
+
->getMock();
|
646 |
+
|
647 |
+
$serverResponseMock
|
648 |
+
->expects($this->once())
|
649 |
+
->method('getGraphNode')
|
650 |
+
->willReturn($graphNodeMock);
|
651 |
+
$graphNodeMock
|
652 |
+
->expects($this->exactly(2))
|
653 |
+
->method('getField')
|
654 |
+
->withConsecutive(
|
655 |
+
[$this->equalTo('error')],
|
656 |
+
[$this->equalTo('success')]
|
657 |
+
)
|
658 |
+
->will($this->onConsecutiveCalls(
|
659 |
+
null,
|
660 |
+
true
|
661 |
+
));
|
662 |
+
|
663 |
+
$this->facebook
|
664 |
+
->expects($this->once())
|
665 |
+
->method('post')
|
666 |
+
->with('PAGE_ID/claimed_urls?url=' . $url)
|
667 |
+
->willReturn($serverResponseMock);
|
668 |
+
|
669 |
+
$result = $this->client->claimURL($url);
|
670 |
+
}
|
671 |
+
|
672 |
+
public function testClaimURLWithProtocl()
|
673 |
+
{
|
674 |
+
$url = 'http://example.com';
|
675 |
+
|
676 |
+
$serverResponseMock =
|
677 |
+
$this->getMockBuilder('Facebook\FacebookResponse')
|
678 |
+
->disableOriginalConstructor()
|
679 |
+
->getMock();
|
680 |
+
$graphNodeMock =
|
681 |
+
$this->getMockBuilder('Facebook\GraphNodes\GraphNode')
|
682 |
+
->disableOriginalConstructor()
|
683 |
+
->getMock();
|
684 |
+
|
685 |
+
$serverResponseMock
|
686 |
+
->expects($this->once())
|
687 |
+
->method('getGraphNode')
|
688 |
+
->willReturn($graphNodeMock);
|
689 |
+
$graphNodeMock
|
690 |
+
->expects($this->exactly(2))
|
691 |
+
->method('getField')
|
692 |
+
->withConsecutive(
|
693 |
+
[$this->equalTo('error')],
|
694 |
+
[$this->equalTo('success')]
|
695 |
+
)
|
696 |
+
->will($this->onConsecutiveCalls(
|
697 |
+
null,
|
698 |
+
true
|
699 |
+
));
|
700 |
+
|
701 |
+
$this->facebook
|
702 |
+
->expects($this->once())
|
703 |
+
->method('post')
|
704 |
+
->with('PAGE_ID/claimed_urls?url=example.com')
|
705 |
+
->willReturn($serverResponseMock);
|
706 |
+
|
707 |
+
$result = $this->client->claimURL($url);
|
708 |
+
}
|
709 |
+
|
710 |
+
public function testClaimURLError()
|
711 |
+
{
|
712 |
+
$url = 'example.com';
|
713 |
+
$error_user_msg = "Error message";
|
714 |
+
|
715 |
+
$serverResponseMock =
|
716 |
+
$this->getMockBuilder('Facebook\FacebookResponse')
|
717 |
+
->disableOriginalConstructor()
|
718 |
+
->getMock();
|
719 |
+
$graphNodeMock =
|
720 |
+
$this->getMockBuilder('Facebook\GraphNodes\GraphNode')
|
721 |
+
->disableOriginalConstructor()
|
722 |
+
->getMock();
|
723 |
+
|
724 |
+
$serverResponseMock
|
725 |
+
->expects($this->once())
|
726 |
+
->method('getGraphNode')
|
727 |
+
->willReturn($graphNodeMock);
|
728 |
+
$graphNodeMock
|
729 |
+
->expects($this->exactly(2))
|
730 |
+
->method('getField')
|
731 |
+
->withConsecutive(
|
732 |
+
[$this->equalTo('error')],
|
733 |
+
[$this->equalTo('success')]
|
734 |
+
)
|
735 |
+
->will($this->onConsecutiveCalls(
|
736 |
+
array( 'error_user_msg' => $error_user_msg ),
|
737 |
+
false
|
738 |
+
));
|
739 |
+
|
740 |
+
$this->facebook
|
741 |
+
->expects($this->once())
|
742 |
+
->method('post')
|
743 |
+
->with('PAGE_ID/claimed_urls?url=' .$url)
|
744 |
+
->willReturn($serverResponseMock);
|
745 |
+
|
746 |
+
$this->setExpectedException('\Facebook\InstantArticles\Client\ClientException');
|
747 |
+
|
748 |
+
$result = $this->client->claimURL($url);
|
749 |
+
}
|
750 |
+
|
751 |
+
public function testSubmitForReview()
|
752 |
+
{
|
753 |
+
$serverResponseMock =
|
754 |
+
$this->getMockBuilder('Facebook\FacebookResponse')
|
755 |
+
->disableOriginalConstructor()
|
756 |
+
->getMock();
|
757 |
+
$graphNodeMock =
|
758 |
+
$this->getMockBuilder('Facebook\GraphNodes\GraphNode')
|
759 |
+
->disableOriginalConstructor()
|
760 |
+
->getMock();
|
761 |
+
|
762 |
+
$serverResponseMock
|
763 |
+
->expects($this->once())
|
764 |
+
->method('getGraphNode')
|
765 |
+
->willReturn($graphNodeMock);
|
766 |
+
$graphNodeMock
|
767 |
+
->expects($this->exactly(2))
|
768 |
+
->method('getField')
|
769 |
+
->withConsecutive(
|
770 |
+
[$this->equalTo('error')],
|
771 |
+
[$this->equalTo('success')]
|
772 |
+
)
|
773 |
+
->will($this->onConsecutiveCalls(
|
774 |
+
null,
|
775 |
+
true
|
776 |
+
));
|
777 |
+
|
778 |
+
$this->facebook
|
779 |
+
->expects($this->once())
|
780 |
+
->method('post')
|
781 |
+
->with('PAGE_ID/?instant_articles_submit_for_review=true')
|
782 |
+
->willReturn($serverResponseMock);
|
783 |
+
|
784 |
+
$result = $this->client->submitForReview();
|
785 |
+
}
|
786 |
+
|
787 |
+
public function testSubmitForReviewError()
|
788 |
+
{
|
789 |
+
$error_user_msg = "Error message";
|
790 |
+
|
791 |
+
$serverResponseMock =
|
792 |
+
$this->getMockBuilder('Facebook\FacebookResponse')
|
793 |
+
->disableOriginalConstructor()
|
794 |
+
->getMock();
|
795 |
+
$graphNodeMock =
|
796 |
+
$this->getMockBuilder('Facebook\GraphNodes\GraphNode')
|
797 |
+
->disableOriginalConstructor()
|
798 |
+
->getMock();
|
799 |
+
|
800 |
+
$serverResponseMock
|
801 |
+
->expects($this->once())
|
802 |
+
->method('getGraphNode')
|
803 |
+
->willReturn($graphNodeMock);
|
804 |
+
$graphNodeMock
|
805 |
+
->expects($this->exactly(2))
|
806 |
+
->method('getField')
|
807 |
+
->withConsecutive(
|
808 |
+
[$this->equalTo('error')],
|
809 |
+
[$this->equalTo('success')]
|
810 |
+
)
|
811 |
+
->will($this->onConsecutiveCalls(
|
812 |
+
array( 'error_user_msg' => $error_user_msg ),
|
813 |
+
false
|
814 |
+
));
|
815 |
+
|
816 |
+
$this->facebook
|
817 |
+
->expects($this->once())
|
818 |
+
->method('post')
|
819 |
+
->with('PAGE_ID/?instant_articles_submit_for_review=true')
|
820 |
+
->willReturn($serverResponseMock);
|
821 |
+
|
822 |
+
$this->setExpectedException('\Facebook\InstantArticles\Client\ClientException');
|
823 |
+
|
824 |
+
$result = $this->client->submitForReview();
|
825 |
+
}
|
826 |
}
|
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Client/HelperTest.php
CHANGED
@@ -54,7 +54,7 @@ class HelperTest extends \PHPUnit_Framework_TestCase
|
|
54 |
$this->facebook
|
55 |
->expects($this->once())
|
56 |
->method('get')
|
57 |
-
->with('/me/accounts?fields=name,id,access_token,supports_instant_articles')
|
58 |
->willReturn($response);
|
59 |
|
60 |
$pagesAndTokensReturned = $this->helper->getPagesAndTokens($accessToken);
|
54 |
$this->facebook
|
55 |
->expects($this->once())
|
56 |
->method('get')
|
57 |
+
->with('/me/accounts?fields=name,id,access_token,supports_instant_articles,picture')
|
58 |
->willReturn($response);
|
59 |
|
60 |
$pagesAndTokensReturned = $this->helper->getPagesAndTokens($accessToken);
|
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Elements/InteractiveTest.php
CHANGED
@@ -21,17 +21,20 @@ class InteractiveTest extends \PHPUnit_Framework_TestCase
|
|
21 |
|
22 |
$rendered = $interactive->render();
|
23 |
$this->assertEquals($expected, $rendered);
|
|
|
24 |
}
|
25 |
|
26 |
public function testRenderBasic()
|
27 |
{
|
28 |
$interactive =
|
29 |
Interactive::create()
|
30 |
-
->withSource('http://foo.com/interactive-graphic')
|
|
|
|
|
31 |
|
32 |
$expected =
|
33 |
'<figure class="op-interactive">'.
|
34 |
-
'<iframe src="http://foo.com/interactive-graphic"></iframe>'.
|
35 |
'</figure>';
|
36 |
|
37 |
$rendered = $interactive->render();
|
@@ -43,6 +46,8 @@ class InteractiveTest extends \PHPUnit_Framework_TestCase
|
|
43 |
$social_embed =
|
44 |
interactive::create()
|
45 |
->withSource('http://foo.com/interactive-graphic')
|
|
|
|
|
46 |
->withCaption(
|
47 |
Caption::create()
|
48 |
->appendText('Some caption to the interactive graphic')
|
@@ -50,7 +55,7 @@ class InteractiveTest extends \PHPUnit_Framework_TestCase
|
|
50 |
|
51 |
$expected =
|
52 |
'<figure class="op-interactive">'.
|
53 |
-
'<iframe src="http://foo.com/interactive-graphic"></iframe>'.
|
54 |
'<figcaption>Some caption to the interactive graphic</figcaption>'.
|
55 |
'</figure>';
|
56 |
|
@@ -58,36 +63,32 @@ class InteractiveTest extends \PHPUnit_Framework_TestCase
|
|
58 |
$this->assertEquals($expected, $rendered);
|
59 |
}
|
60 |
|
61 |
-
public function
|
62 |
{
|
63 |
$interactive =
|
64 |
Interactive::create()
|
65 |
->withSource('http://foo.com/interactive-graphic')
|
66 |
->withHeight(640);
|
67 |
|
68 |
-
$expected =
|
69 |
-
'<figure class="op-interactive">'.
|
70 |
-
'<iframe src="http://foo.com/interactive-graphic" height="640"></iframe>'.
|
71 |
-
'</figure>';
|
72 |
|
73 |
$rendered = $interactive->render();
|
74 |
$this->assertEquals($expected, $rendered);
|
|
|
75 |
}
|
76 |
|
77 |
-
public function
|
78 |
{
|
79 |
$interactive =
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
|
84 |
-
$expected =
|
85 |
-
'<figure class="op-interactive">' .
|
86 |
-
'<iframe src="http://foo.com/interactive-graphic" width="640"></iframe>' .
|
87 |
-
'</figure>';
|
88 |
|
89 |
$rendered = $interactive->render();
|
90 |
$this->assertEquals($expected, $rendered);
|
|
|
91 |
}
|
92 |
|
93 |
public function testRenderBasicWithWidthHeight()
|
@@ -100,46 +101,67 @@ class InteractiveTest extends \PHPUnit_Framework_TestCase
|
|
100 |
|
101 |
$expected =
|
102 |
'<figure class="op-interactive">' .
|
103 |
-
|
104 |
'</figure>';
|
105 |
|
106 |
$rendered = $interactive->render();
|
107 |
$this->assertEquals($expected, $rendered);
|
108 |
}
|
109 |
|
110 |
-
public function
|
111 |
{
|
112 |
$interactive =
|
113 |
Interactive::create()
|
114 |
->withSource('http://foo.com/interactive-graphic')
|
115 |
->withMargin(Interactive::COLUMN_WIDTH);
|
116 |
|
117 |
-
$expected =
|
118 |
-
'<figure class="op-interactive">'.
|
119 |
-
'<iframe src="http://foo.com/interactive-graphic" class="column-width"></iframe>'.
|
120 |
-
'</figure>';
|
121 |
|
122 |
$rendered = $interactive->render();
|
123 |
$this->assertEquals($expected, $rendered);
|
|
|
124 |
}
|
125 |
|
126 |
-
public function
|
127 |
{
|
128 |
$interactive =
|
129 |
Interactive::create()
|
130 |
->withSource('http://foo.com/interactive-graphic')
|
131 |
->withMargin(Interactive::NO_MARGIN);
|
132 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
133 |
$expected =
|
134 |
'<figure class="op-interactive">'.
|
135 |
-
'<iframe
|
|
|
|
|
|
|
136 |
'</figure>';
|
137 |
|
138 |
$rendered = $interactive->render();
|
139 |
$this->assertEquals($expected, $rendered);
|
140 |
}
|
141 |
|
142 |
-
public function
|
143 |
{
|
144 |
$inline =
|
145 |
'<h1>Some custom code</h1>'.
|
@@ -148,12 +170,11 @@ class InteractiveTest extends \PHPUnit_Framework_TestCase
|
|
148 |
$interactive =
|
149 |
Interactive::create()
|
150 |
->withHTML($inline)
|
151 |
-
->withHeight(640)
|
152 |
->withMargin(Interactive::NO_MARGIN);
|
153 |
|
154 |
$expected =
|
155 |
'<figure class="op-interactive">'.
|
156 |
-
'<iframe class="no-margin"
|
157 |
'<h1>Some custom code</h1>'.
|
158 |
'<script>alert("test & more test");</script>'.
|
159 |
'</iframe>'.
|
@@ -161,5 +182,6 @@ class InteractiveTest extends \PHPUnit_Framework_TestCase
|
|
161 |
|
162 |
$rendered = $interactive->render();
|
163 |
$this->assertEquals($expected, $rendered);
|
|
|
164 |
}
|
165 |
}
|
21 |
|
22 |
$rendered = $interactive->render();
|
23 |
$this->assertEquals($expected, $rendered);
|
24 |
+
$this->assertFalse($interactive->isValid());
|
25 |
}
|
26 |
|
27 |
public function testRenderBasic()
|
28 |
{
|
29 |
$interactive =
|
30 |
Interactive::create()
|
31 |
+
->withSource('http://foo.com/interactive-graphic')
|
32 |
+
->withWidth(640)
|
33 |
+
->withHeight(300);
|
34 |
|
35 |
$expected =
|
36 |
'<figure class="op-interactive">'.
|
37 |
+
'<iframe src="http://foo.com/interactive-graphic" width="640" height="300"></iframe>'.
|
38 |
'</figure>';
|
39 |
|
40 |
$rendered = $interactive->render();
|
46 |
$social_embed =
|
47 |
interactive::create()
|
48 |
->withSource('http://foo.com/interactive-graphic')
|
49 |
+
->withWidth(640)
|
50 |
+
->withHeight(300)
|
51 |
->withCaption(
|
52 |
Caption::create()
|
53 |
->appendText('Some caption to the interactive graphic')
|
55 |
|
56 |
$expected =
|
57 |
'<figure class="op-interactive">'.
|
58 |
+
'<iframe src="http://foo.com/interactive-graphic" width="640" height="300"></iframe>'.
|
59 |
'<figcaption>Some caption to the interactive graphic</figcaption>'.
|
60 |
'</figure>';
|
61 |
|
63 |
$this->assertEquals($expected, $rendered);
|
64 |
}
|
65 |
|
66 |
+
public function testRenderBasicWithOnlyHeight()
|
67 |
{
|
68 |
$interactive =
|
69 |
Interactive::create()
|
70 |
->withSource('http://foo.com/interactive-graphic')
|
71 |
->withHeight(640);
|
72 |
|
73 |
+
$expected = '';
|
|
|
|
|
|
|
74 |
|
75 |
$rendered = $interactive->render();
|
76 |
$this->assertEquals($expected, $rendered);
|
77 |
+
$this->assertFalse($interactive->isValid());
|
78 |
}
|
79 |
|
80 |
+
public function testRenderBasicWithOnlyWidth()
|
81 |
{
|
82 |
$interactive =
|
83 |
+
Interactive::create()
|
84 |
+
->withSource('http://foo.com/interactive-graphic')
|
85 |
+
->withWidth(640);
|
86 |
|
87 |
+
$expected = '';
|
|
|
|
|
|
|
88 |
|
89 |
$rendered = $interactive->render();
|
90 |
$this->assertEquals($expected, $rendered);
|
91 |
+
$this->assertFalse($interactive->isValid());
|
92 |
}
|
93 |
|
94 |
public function testRenderBasicWithWidthHeight()
|
101 |
|
102 |
$expected =
|
103 |
'<figure class="op-interactive">' .
|
104 |
+
'<iframe src="http://foo.com/interactive-graphic" width="1600" height="900"></iframe>' .
|
105 |
'</figure>';
|
106 |
|
107 |
$rendered = $interactive->render();
|
108 |
$this->assertEquals($expected, $rendered);
|
109 |
}
|
110 |
|
111 |
+
public function testRenderBasicWithOnlyColumnWidth()
|
112 |
{
|
113 |
$interactive =
|
114 |
Interactive::create()
|
115 |
->withSource('http://foo.com/interactive-graphic')
|
116 |
->withMargin(Interactive::COLUMN_WIDTH);
|
117 |
|
118 |
+
$expected = '';
|
|
|
|
|
|
|
119 |
|
120 |
$rendered = $interactive->render();
|
121 |
$this->assertEquals($expected, $rendered);
|
122 |
+
$this->assertFalse($interactive->isValid());
|
123 |
}
|
124 |
|
125 |
+
public function testRenderBasicWithOnlyNoMargin()
|
126 |
{
|
127 |
$interactive =
|
128 |
Interactive::create()
|
129 |
->withSource('http://foo.com/interactive-graphic')
|
130 |
->withMargin(Interactive::NO_MARGIN);
|
131 |
|
132 |
+
$expected = '';
|
133 |
+
|
134 |
+
$rendered = $interactive->render();
|
135 |
+
$this->assertEquals($expected, $rendered);
|
136 |
+
$this->assertFalse($interactive->isValid());
|
137 |
+
}
|
138 |
+
|
139 |
+
public function testRenderInlineWithHeightAndWidth()
|
140 |
+
{
|
141 |
+
$inline =
|
142 |
+
'<h1>Some custom code</h1>'.
|
143 |
+
'<script>alert("test & more test");</script>';
|
144 |
+
|
145 |
+
$interactive =
|
146 |
+
Interactive::create()
|
147 |
+
->withHTML($inline)
|
148 |
+
->withWidth(600)
|
149 |
+
->withHeight(640)
|
150 |
+
->withMargin(Interactive::NO_MARGIN);
|
151 |
+
|
152 |
$expected =
|
153 |
'<figure class="op-interactive">'.
|
154 |
+
'<iframe class="no-margin" width="600" height="640">'.
|
155 |
+
'<h1>Some custom code</h1>'.
|
156 |
+
'<script>alert("test & more test");</script>'.
|
157 |
+
'</iframe>'.
|
158 |
'</figure>';
|
159 |
|
160 |
$rendered = $interactive->render();
|
161 |
$this->assertEquals($expected, $rendered);
|
162 |
}
|
163 |
|
164 |
+
public function testRenderInline()
|
165 |
{
|
166 |
$inline =
|
167 |
'<h1>Some custom code</h1>'.
|
170 |
$interactive =
|
171 |
Interactive::create()
|
172 |
->withHTML($inline)
|
|
|
173 |
->withMargin(Interactive::NO_MARGIN);
|
174 |
|
175 |
$expected =
|
176 |
'<figure class="op-interactive">'.
|
177 |
+
'<iframe class="no-margin">'.
|
178 |
'<h1>Some custom code</h1>'.
|
179 |
'<script>alert("test & more test");</script>'.
|
180 |
'</iframe>'.
|
182 |
|
183 |
$rendered = $interactive->render();
|
184 |
$this->assertEquals($expected, $rendered);
|
185 |
+
$this->assertTrue($interactive->isValid());
|
186 |
}
|
187 |
}
|
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/CMS/WPTransformerTest.php
CHANGED
@@ -6,14 +6,15 @@
|
|
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\InstantArticle;
|
12 |
use Facebook\InstantArticles\Elements\Header;
|
13 |
use Facebook\InstantArticles\Elements\Time;
|
14 |
use Facebook\InstantArticles\Elements\Author;
|
15 |
|
16 |
-
class
|
17 |
{
|
18 |
protected function setUp()
|
19 |
{
|
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\CMS;
|
10 |
|
11 |
+
use Facebook\InstantArticles\Transformer\Transformer;
|
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 |
|
17 |
+
class WPTransformerTest extends \PHPUnit_Framework_TestCase
|
18 |
{
|
19 |
protected function setUp()
|
20 |
{
|
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/CMS/wp-ia.xml
CHANGED
@@ -16,7 +16,7 @@
|
|
16 |
<address><a>bill</a></address>
|
17 |
</header>
|
18 |
<p>Yes, peace is good for everybody!<br/>
|
19 |
-
Man kind.</p>
|
20 |
<figure>
|
21 |
<img src="http://example.com/image0.jpg"/>
|
22 |
</figure>
|
@@ -30,11 +30,126 @@ Man kind.</p>
|
|
30 |
<img src="http://example.com/image2.jpg"/>
|
31 |
</figure>
|
32 |
<p> and some after img.</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
<ul>
|
34 |
<li>Some text on li before img</li>
|
35 |
<li>Some text on li before imgand after img</li>
|
36 |
<li>Some text after img</li>
|
37 |
</ul>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
</article>
|
39 |
</body>
|
40 |
</html>
|
16 |
<address><a>bill</a></address>
|
17 |
</header>
|
18 |
<p>Yes, peace is good for everybody!<br/>
|
19 |
+
Man kind.</p>
|
20 |
<figure>
|
21 |
<img src="http://example.com/image0.jpg"/>
|
22 |
</figure>
|
30 |
<img src="http://example.com/image2.jpg"/>
|
31 |
</figure>
|
32 |
<p> and some after img.</p>
|
33 |
+
<figure class="op-interactive">
|
34 |
+
<iframe src="http://example.com/0/" class="no-margin" width="300" height="200"></iframe>
|
35 |
+
</figure>
|
36 |
+
<p>Some text before iframe</p>
|
37 |
+
<figure class="op-interactive">
|
38 |
+
<iframe src="http://example.com/1/" class="no-margin" width="300" height="200"></iframe>
|
39 |
+
</figure>
|
40 |
+
<figure class="op-interactive">
|
41 |
+
<iframe src="http://example.com/2/" class="no-margin" width="300" height="200"></iframe>
|
42 |
+
</figure>
|
43 |
+
<p> some after iframe.</p>
|
44 |
+
<p>Some text before iframe</p>
|
45 |
+
<figure class="op-interactive">
|
46 |
+
<iframe src="http://example.com/3/" class="no-margin" width="300" height="200"></iframe>
|
47 |
+
</figure>
|
48 |
+
<p> and some after iframe.</p>
|
49 |
+
<figure class="op-interactive">
|
50 |
+
<iframe src="http://example.com/loose/with_url" class="no-margin" width="300" height="200"></iframe>
|
51 |
+
</figure>
|
52 |
+
<figure class="op-interactive">
|
53 |
+
<iframe class="no-margin">
|
54 |
+
<div>
|
55 |
+
<h1>Iframe loose without url</h1>
|
56 |
+
</div>
|
57 |
+
</iframe>
|
58 |
+
</figure>
|
59 |
+
<figure class="op-interactive">
|
60 |
+
<iframe class="no-margin">
|
61 |
+
<div>
|
62 |
+
<h1>some embed here</h1>
|
63 |
+
</div>
|
64 |
+
</iframe>
|
65 |
+
</figure>
|
66 |
+
<figure class="op-interactive">
|
67 |
+
<iframe class="no-margin">
|
68 |
+
<div>
|
69 |
+
<h1>some embed here</h1>
|
70 |
+
</div>
|
71 |
+
</iframe>
|
72 |
+
</figure>
|
73 |
+
<figure class="op-interactive">
|
74 |
+
<iframe class="no-margin">
|
75 |
+
<div>some content</div>
|
76 |
+
<script>alert('hi & hello to you @ testing!');</script></iframe>
|
77 |
+
</figure>
|
78 |
+
<figure class="op-interactive">
|
79 |
+
<iframe src="http://example.com/4/" class="no-margin" width="300" height="200"></iframe>
|
80 |
+
</figure>
|
81 |
+
<figure class="op-interactive">
|
82 |
+
<iframe class="no-margin">
|
83 |
+
<div>some content</div>
|
84 |
+
<script>alert('hi & hello to you @ testing!');</script></iframe>
|
85 |
+
</figure>
|
86 |
+
<figure class="op-interactive">
|
87 |
+
<iframe src="http://example.com/4/" class="no-margin" width="300" height="200"></iframe>
|
88 |
+
</figure>
|
89 |
+
<figure class="op-interactive">
|
90 |
+
<iframe class="no-margin">
|
91 |
+
<div>some content</div>
|
92 |
+
<script>alert('hi & hello to you @ testing!');</script></iframe>
|
93 |
+
</figure>
|
94 |
+
<figure class="op-interactive">
|
95 |
+
<iframe class="no-margin" height="200">
|
96 |
+
<table width="200" height="200">
|
97 |
+
<thead><td>header 1</td>
|
98 |
+
<td>header 2</td>
|
99 |
+
</thead>
|
100 |
+
<tbody>
|
101 |
+
<tr><td>Line 1 column 1</td>
|
102 |
+
<td>Line 1 column 2</td>
|
103 |
+
</tr>
|
104 |
+
<tr><td>Line 2 column 1</td>
|
105 |
+
<td>Line 2 column 2</td>
|
106 |
+
</tr>
|
107 |
+
</tbody>
|
108 |
+
</table>
|
109 |
+
</iframe>
|
110 |
+
</figure>
|
111 |
<ul>
|
112 |
<li>Some text on li before img</li>
|
113 |
<li>Some text on li before imgand after img</li>
|
114 |
<li>Some text after img</li>
|
115 |
</ul>
|
116 |
+
<figure class="op-slideshow">
|
117 |
+
<figure>
|
118 |
+
<img src="http://example.com/img0.jpg"/>
|
119 |
+
</figure>
|
120 |
+
<figure>
|
121 |
+
<img src="http://example.com/img1.jpg"/>
|
122 |
+
</figure>
|
123 |
+
<figure>
|
124 |
+
<img src="http://example.com/img2.jpg"/>
|
125 |
+
<figcaption>Image 2</figcaption>
|
126 |
+
</figure>
|
127 |
+
<figure>
|
128 |
+
<img src="http://example.com/img3.jpg"/>
|
129 |
+
<figcaption>Image 3</figcaption>
|
130 |
+
</figure>
|
131 |
+
<figure>
|
132 |
+
<img src="http://example.com/img4.jpg"/>
|
133 |
+
</figure>
|
134 |
+
</figure>
|
135 |
+
<figure class="op-slideshow">
|
136 |
+
<figure>
|
137 |
+
<img src="http://example.com/img1.jpg"/>
|
138 |
+
<figcaption> Image 1 </figcaption>
|
139 |
+
</figure>
|
140 |
+
<figure>
|
141 |
+
<img src="http://example.com/img2.jpg"/>
|
142 |
+
<figcaption> Image 2 </figcaption>
|
143 |
+
</figure>
|
144 |
+
<figure>
|
145 |
+
<img src="http://example.com/img3.jpg"/>
|
146 |
+
<figcaption> Image 3 </figcaption>
|
147 |
+
</figure>
|
148 |
+
</figure>
|
149 |
+
<figure>
|
150 |
+
<img src="http://example.com/img.jpg"/>
|
151 |
+
<figcaption>blue eyes</figcaption>
|
152 |
+
</figure>
|
153 |
</article>
|
154 |
</body>
|
155 |
</html>
|
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/CMS/wp-rules.json
CHANGED
@@ -17,6 +17,9 @@
|
|
17 |
},{
|
18 |
"class": "PassThroughRule",
|
19 |
"selector" : "del"
|
|
|
|
|
|
|
20 |
}, {
|
21 |
"class": "PassThroughRule",
|
22 |
"selector" : "span"
|
@@ -59,8 +62,8 @@
|
|
59 |
}, {
|
60 |
"class": "PassThroughRule",
|
61 |
"selector": "blockquote p"
|
62 |
-
},{
|
63 |
-
"class": "
|
64 |
"selector": "img",
|
65 |
"properties": {
|
66 |
"image.url": {
|
@@ -69,8 +72,8 @@
|
|
69 |
"attribute": "src"
|
70 |
}
|
71 |
}
|
72 |
-
},
|
73 |
-
"class": "
|
74 |
"selector": "img",
|
75 |
"properties": {
|
76 |
"image.url": {
|
@@ -117,6 +120,49 @@
|
|
117 |
}, {
|
118 |
"class": "H2Rule",
|
119 |
"selector" : "h3,h4,h5,h6"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
120 |
}, {
|
121 |
"class": "InteractiveRule",
|
122 |
"selector" : "div.interactive",
|
@@ -130,19 +176,205 @@
|
|
130 |
"selector" : "iframe",
|
131 |
"attribute": "height"
|
132 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
133 |
"interactive.iframe" : {
|
134 |
"type" : "children",
|
135 |
"selector" : "iframe"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
136 |
}
|
137 |
}
|
138 |
}, {
|
139 |
"class": "InteractiveRule",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
140 |
"selector" : "//div[@class='interactive' and iframe]",
|
141 |
"properties" : {
|
142 |
"interactive.url" : {
|
143 |
"type" : "string",
|
144 |
"selector" : "iframe",
|
145 |
"attribute": "src"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
146 |
}
|
147 |
}
|
148 |
}, {
|
@@ -192,14 +424,95 @@
|
|
192 |
"attribute": "type"
|
193 |
}
|
194 |
}
|
195 |
-
},
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
202 |
}
|
203 |
}
|
204 |
-
}
|
|
|
205 |
}
|
17 |
},{
|
18 |
"class": "PassThroughRule",
|
19 |
"selector" : "del"
|
20 |
+
},{
|
21 |
+
"class": "PassThroughRule",
|
22 |
+
"selector" : "mark"
|
23 |
}, {
|
24 |
"class": "PassThroughRule",
|
25 |
"selector" : "span"
|
62 |
}, {
|
63 |
"class": "PassThroughRule",
|
64 |
"selector": "blockquote p"
|
65 |
+
}, {
|
66 |
+
"class": "ImageInsideParagraphRule",
|
67 |
"selector": "img",
|
68 |
"properties": {
|
69 |
"image.url": {
|
72 |
"attribute": "src"
|
73 |
}
|
74 |
}
|
75 |
+
},{
|
76 |
+
"class": "ImageRule",
|
77 |
"selector": "img",
|
78 |
"properties": {
|
79 |
"image.url": {
|
120 |
}, {
|
121 |
"class": "H2Rule",
|
122 |
"selector" : "h3,h4,h5,h6"
|
123 |
+
}, {
|
124 |
+
"class": "InteractiveRule",
|
125 |
+
"selector" : "iframe",
|
126 |
+
"properties" : {
|
127 |
+
"interactive.url" : {
|
128 |
+
"type" : "string",
|
129 |
+
"selector" : "iframe",
|
130 |
+
"attribute": "src"
|
131 |
+
},
|
132 |
+
"interactive.width" : {
|
133 |
+
"type" : "int",
|
134 |
+
"selector" : "iframe",
|
135 |
+
"attribute": "width"
|
136 |
+
},
|
137 |
+
"interactive.height" : {
|
138 |
+
"type" : "int",
|
139 |
+
"selector" : "iframe",
|
140 |
+
"attribute": "height"
|
141 |
+
},
|
142 |
+
"interactive.iframe" : {
|
143 |
+
"type" : "children",
|
144 |
+
"selector" : "iframe"
|
145 |
+
}
|
146 |
+
}
|
147 |
+
}, {
|
148 |
+
"class": "InteractiveRule",
|
149 |
+
"selector" : "div.embed",
|
150 |
+
"properties" : {
|
151 |
+
"interactive.iframe" : {
|
152 |
+
"type" : "children",
|
153 |
+
"selector" : "div.embed"
|
154 |
+
},
|
155 |
+
"interactive.height" : {
|
156 |
+
"type" : "int",
|
157 |
+
"selector" : "iframe",
|
158 |
+
"attribute": "height"
|
159 |
+
},
|
160 |
+
"interactive.width" : {
|
161 |
+
"type" : "int",
|
162 |
+
"selector" : "iframe",
|
163 |
+
"attribute": "width"
|
164 |
+
}
|
165 |
+
}
|
166 |
}, {
|
167 |
"class": "InteractiveRule",
|
168 |
"selector" : "div.interactive",
|
176 |
"selector" : "iframe",
|
177 |
"attribute": "height"
|
178 |
},
|
179 |
+
"interactive.width" : {
|
180 |
+
"type" : "int",
|
181 |
+
"selector" : "iframe",
|
182 |
+
"attribute": "width"
|
183 |
+
}
|
184 |
+
}
|
185 |
+
}, {
|
186 |
+
"class": "InteractiveRule",
|
187 |
+
"selector" : "//div[@class='embed' and iframe]",
|
188 |
+
"properties" : {
|
189 |
+
"interactive.url" : {
|
190 |
+
"type" : "string",
|
191 |
+
"selector" : "iframe",
|
192 |
+
"attribute": "src"
|
193 |
+
},
|
194 |
+
"interactive.iframe" : {
|
195 |
+
"type" : "children",
|
196 |
+
"selector" : "iframe",
|
197 |
+
"attribute": "src"
|
198 |
+
},
|
199 |
+
"interactive.width" : {
|
200 |
+
"type" : "int",
|
201 |
+
"selector" : "iframe",
|
202 |
+
"attribute": "width"
|
203 |
+
},
|
204 |
+
"interactive.height" : {
|
205 |
+
"type" : "int",
|
206 |
+
"selector" : "iframe",
|
207 |
+
"attribute": "height"
|
208 |
+
}
|
209 |
+
}
|
210 |
+
}, {
|
211 |
+
"class": "InteractiveRule",
|
212 |
+
"selector" : "//div[@class='interactive' and iframe]",
|
213 |
+
"properties" : {
|
214 |
+
"interactive.url" : {
|
215 |
+
"type" : "string",
|
216 |
+
"selector" : "iframe",
|
217 |
+
"attribute": "src"
|
218 |
+
},
|
219 |
"interactive.iframe" : {
|
220 |
"type" : "children",
|
221 |
"selector" : "iframe"
|
222 |
+
},
|
223 |
+
"interactive.height" : {
|
224 |
+
"type" : "int",
|
225 |
+
"selector" : "iframe",
|
226 |
+
"attribute": "height"
|
227 |
+
},
|
228 |
+
"interactive.width" : {
|
229 |
+
"type" : "int",
|
230 |
+
"selector" : "iframe",
|
231 |
+
"attribute": "width"
|
232 |
}
|
233 |
}
|
234 |
}, {
|
235 |
"class": "InteractiveRule",
|
236 |
+
"selector" : "table",
|
237 |
+
"properties" : {
|
238 |
+
"interactive.iframe" : {
|
239 |
+
"type" : "element",
|
240 |
+
"selector" : "table"
|
241 |
+
},
|
242 |
+
"interactive.height" : {
|
243 |
+
"type" : "int",
|
244 |
+
"selector" : "table",
|
245 |
+
"attribute": "height"
|
246 |
+
},
|
247 |
+
"interactive.width" : {
|
248 |
+
"type" : "int",
|
249 |
+
"selector" : "iframe",
|
250 |
+
"attribute": "width"
|
251 |
+
}
|
252 |
+
}
|
253 |
+
}, {
|
254 |
+
"class": "InteractiveInsideParagraphRule",
|
255 |
+
"selector" : "iframe",
|
256 |
+
"properties" : {
|
257 |
+
"interactive.url" : {
|
258 |
+
"type" : "string",
|
259 |
+
"selector" : "iframe",
|
260 |
+
"attribute": "src"
|
261 |
+
},
|
262 |
+
"interactive.height" : {
|
263 |
+
"type" : "int",
|
264 |
+
"selector" : "iframe",
|
265 |
+
"attribute": "height"
|
266 |
+
},
|
267 |
+
"interactive.width" : {
|
268 |
+
"type" : "int",
|
269 |
+
"selector" : "iframe",
|
270 |
+
"attribute": "width"
|
271 |
+
}
|
272 |
+
}
|
273 |
+
},{
|
274 |
+
"class": "InteractiveInsideParagraphRule",
|
275 |
+
"selector" : "div.embed",
|
276 |
+
"properties" : {
|
277 |
+
"interactive.iframe" : {
|
278 |
+
"type" : "children",
|
279 |
+
"selector" : "div.embed"
|
280 |
+
},
|
281 |
+
"interactive.height" : {
|
282 |
+
"type" : "int",
|
283 |
+
"selector" : "iframe",
|
284 |
+
"attribute": "height"
|
285 |
+
},
|
286 |
+
"interactive.width" : {
|
287 |
+
"type" : "int",
|
288 |
+
"selector" : "iframe",
|
289 |
+
"attribute": "width"
|
290 |
+
}
|
291 |
+
}
|
292 |
+
}, {
|
293 |
+
"class": "InteractiveInsideParagraphRule",
|
294 |
+
"selector" : "div.interactive",
|
295 |
+
"properties" : {
|
296 |
+
"interactive.iframe" : {
|
297 |
+
"type" : "children",
|
298 |
+
"selector" : "div.interactive"
|
299 |
+
},
|
300 |
+
"interactive.height" : {
|
301 |
+
"type" : "int",
|
302 |
+
"selector" : "iframe",
|
303 |
+
"attribute": "height"
|
304 |
+
},
|
305 |
+
"interactive.width" : {
|
306 |
+
"type" : "int",
|
307 |
+
"selector" : "iframe",
|
308 |
+
"attribute": "width"
|
309 |
+
}
|
310 |
+
}
|
311 |
+
}, {
|
312 |
+
"class": "InteractiveInsideParagraphRule",
|
313 |
+
"selector" : "//div[@class='embed' and iframe]",
|
314 |
+
"properties" : {
|
315 |
+
"interactive.url" : {
|
316 |
+
"type" : "string",
|
317 |
+
"selector" : "iframe",
|
318 |
+
"attribute": "src"
|
319 |
+
},
|
320 |
+
"interactive.iframe" : {
|
321 |
+
"type" : "children",
|
322 |
+
"selector" : "iframe",
|
323 |
+
"attribute": "src"
|
324 |
+
},
|
325 |
+
"interactive.width" : {
|
326 |
+
"type" : "int",
|
327 |
+
"selector" : "iframe",
|
328 |
+
"attribute": "width"
|
329 |
+
},
|
330 |
+
"interactive.height" : {
|
331 |
+
"type" : "int",
|
332 |
+
"selector" : "iframe",
|
333 |
+
"attribute": "height"
|
334 |
+
}
|
335 |
+
}
|
336 |
+
}, {
|
337 |
+
"class": "InteractiveInsideParagraphRule",
|
338 |
"selector" : "//div[@class='interactive' and iframe]",
|
339 |
"properties" : {
|
340 |
"interactive.url" : {
|
341 |
"type" : "string",
|
342 |
"selector" : "iframe",
|
343 |
"attribute": "src"
|
344 |
+
},
|
345 |
+
"interactive.iframe" : {
|
346 |
+
"type" : "children",
|
347 |
+
"selector" : "iframe",
|
348 |
+
"attribute": "src"
|
349 |
+
},
|
350 |
+
"interactive.height" : {
|
351 |
+
"type" : "int",
|
352 |
+
"selector" : "iframe",
|
353 |
+
"attribute": "height"
|
354 |
+
},
|
355 |
+
"interactive.width" : {
|
356 |
+
"type" : "int",
|
357 |
+
"selector" : "iframe",
|
358 |
+
"attribute": "width"
|
359 |
+
}
|
360 |
+
}
|
361 |
+
}, {
|
362 |
+
"class": "InteractiveInsideParagraphRule",
|
363 |
+
"selector" : "table",
|
364 |
+
"properties" : {
|
365 |
+
"interactive.iframe" : {
|
366 |
+
"type" : "element",
|
367 |
+
"selector" : "table"
|
368 |
+
},
|
369 |
+
"interactive.height" : {
|
370 |
+
"type" : "int",
|
371 |
+
"selector" : "table",
|
372 |
+
"attribute": "height"
|
373 |
+
},
|
374 |
+
"interactive.width" : {
|
375 |
+
"type" : "int",
|
376 |
+
"selector" : "table",
|
377 |
+
"attribute": "width"
|
378 |
}
|
379 |
}
|
380 |
}, {
|
424 |
"attribute": "type"
|
425 |
}
|
426 |
}
|
427 |
+
},
|
428 |
+
|
429 |
+
|
430 |
+
|
431 |
+
{
|
432 |
+
"class" : "IgnoreRule",
|
433 |
+
"selector" : "p.jetpack-slideshow-noscript"
|
434 |
+
},
|
435 |
+
{
|
436 |
+
"class": "CaptionRule",
|
437 |
+
"selector" : "div.wp-caption-text"
|
438 |
+
},
|
439 |
+
{
|
440 |
+
"class" : "PassThroughRule",
|
441 |
+
"selector" : "div.gallery-row"
|
442 |
+
},
|
443 |
+
{
|
444 |
+
"class" : "PassThroughRule",
|
445 |
+
"selector" : "div.tiled-gallery p"
|
446 |
+
},
|
447 |
+
{
|
448 |
+
"class" : "PassThroughRule",
|
449 |
+
"selector" : "div.gallery-row p"
|
450 |
+
},
|
451 |
+
{
|
452 |
+
"class" : "PassThroughRule",
|
453 |
+
"selector" : "div.gallery-group p"
|
454 |
+
},
|
455 |
+
{
|
456 |
+
"class" : "PassThroughRule",
|
457 |
+
"selector" : "div.gallery-group"
|
458 |
+
},
|
459 |
+
{
|
460 |
+
"class": "ImageRule",
|
461 |
+
"selector" : "div.wp-caption",
|
462 |
+
"properties" : {
|
463 |
+
"image.url" : {
|
464 |
+
"type" : "string",
|
465 |
+
"selector" : "img",
|
466 |
+
"attribute": "src"
|
467 |
+
}
|
468 |
+
}
|
469 |
+
},
|
470 |
+
{
|
471 |
+
"class": "SlideshowImageRule",
|
472 |
+
"selector" : "div.tiled-gallery-item",
|
473 |
+
"properties" : {
|
474 |
+
"image.url" : {
|
475 |
+
"type" : "string",
|
476 |
+
"selector" : "img",
|
477 |
+
"attribute": "data-orig-file"
|
478 |
+
},
|
479 |
+
"caption.title" : {
|
480 |
+
"type" : "string",
|
481 |
+
"selector" : "div.tiled-gallery-caption"
|
482 |
+
}
|
483 |
+
}
|
484 |
+
},
|
485 |
+
{
|
486 |
+
"class": "SlideshowRule",
|
487 |
+
"selector" : "div.tiled-gallery"
|
488 |
+
},
|
489 |
+
{
|
490 |
+
"class": "Compat\\JetpackSlideshowRule",
|
491 |
+
"selector" : "div.jetpack-slideshow",
|
492 |
+
"properties": {
|
493 |
+
"jetpack.data-gallery": {
|
494 |
+
"type": "json",
|
495 |
+
"selector": "div.jetpack-slideshow",
|
496 |
+
"attribute": "data-gallery"
|
497 |
+
}
|
498 |
+
}
|
499 |
+
},
|
500 |
+
{
|
501 |
+
"class": "CaptionRule",
|
502 |
+
"selector" : "div.tiled-gallery-caption"
|
503 |
+
},
|
504 |
+
|
505 |
+
|
506 |
+
{
|
507 |
+
"class": "ImageInsideParagraphRule",
|
508 |
+
"selector": "figure.wp-caption",
|
509 |
+
"properties": {
|
510 |
+
"image.url": {
|
511 |
+
"type": "string",
|
512 |
+
"selector": "img",
|
513 |
+
"attribute": "src"
|
514 |
}
|
515 |
}
|
516 |
+
}
|
517 |
+
]
|
518 |
}
|
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/CMS/wp.html
CHANGED
@@ -1,12 +1,133 @@
|
|
1 |
<!DOCTYPE html>
|
2 |
-
<html
|
3 |
-
|
4 |
-
<p
|
5 |
-
|
6 |
-
<p
|
7 |
-
<
|
8 |
-
<
|
9 |
-
<
|
10 |
-
<
|
11 |
-
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
<!DOCTYPE html>
|
2 |
+
<html>
|
3 |
+
<body>
|
4 |
+
<p>Yes, peace is good for everybody!<br>
|
5 |
+
Man kind.</p>
|
6 |
+
<p><img src="http://example.com/image0.jpg" />Some text after img.</p>
|
7 |
+
<p>Some text before img<img src="http://example.com/image1.jpg" /></p>
|
8 |
+
<p>Some text before img<img src="http://example.com/image2.jpg" /> and some after img.</p>
|
9 |
+
<p><iframe width="300" height="200" src="http://example.com/0/"/></p>
|
10 |
+
<p>Some text before iframe<iframe width="300" height="200" src="http://example.com/1/"/></p>
|
11 |
+
<p><iframe width="300" height="200" src="http://example.com/2/"></iframe> some after iframe.</p>
|
12 |
+
<p>Some text before iframe<iframe width="300" height="200" src="http://example.com/3/"/> and some after iframe.</p>
|
13 |
+
<iframe width="300" height="200" src="http://example.com/loose/with_url"></iframe>
|
14 |
+
<iframe>
|
15 |
+
<div>
|
16 |
+
<h1>Iframe loose without url</h1>
|
17 |
+
</div>
|
18 |
+
</iframe>
|
19 |
+
<div class="embed">
|
20 |
+
<div>
|
21 |
+
<h1>some embed here</h1>
|
22 |
+
</div>
|
23 |
+
</div>
|
24 |
+
<div class="interactive">
|
25 |
+
<div>
|
26 |
+
<h1>some embed here</h1>
|
27 |
+
</div>
|
28 |
+
</div>
|
29 |
+
<div class="interactive">
|
30 |
+
<iframe>
|
31 |
+
<div>some content</div>
|
32 |
+
<script>alert('hi & hello to you @ testing!');</script>
|
33 |
+
</iframe>
|
34 |
+
</div>
|
35 |
+
<div class="interactive">
|
36 |
+
<iframe width="300" height="200" src="http://example.com/4/"></iframe>
|
37 |
+
</div>
|
38 |
+
<div class="interactive">
|
39 |
+
<iframe>
|
40 |
+
<div>some content</div>
|
41 |
+
<script>alert('hi & hello to you @ testing!');</script>
|
42 |
+
</iframe>
|
43 |
+
</div>
|
44 |
+
<div class="embed">
|
45 |
+
<iframe width="300" height="200" src="http://example.com/4/"></iframe>
|
46 |
+
</div>
|
47 |
+
<div class="embed">
|
48 |
+
<iframe>
|
49 |
+
<div>some content</div>
|
50 |
+
<script>alert('hi & hello to you @ testing!');</script>
|
51 |
+
</iframe>
|
52 |
+
</div>
|
53 |
+
<table width="200" height="200">
|
54 |
+
<thead>
|
55 |
+
<td>header 1</td>
|
56 |
+
<td>header 2</td>
|
57 |
+
</thead>
|
58 |
+
<tbody>
|
59 |
+
<tr>
|
60 |
+
<td>Line 1 column 1</td>
|
61 |
+
<td>Line 1 column 2</td>
|
62 |
+
</tr>
|
63 |
+
<tr>
|
64 |
+
<td>Line 2 column 1</td>
|
65 |
+
<td>Line 2 column 2</td>
|
66 |
+
</tr>
|
67 |
+
</tbody>
|
68 |
+
</table>
|
69 |
+
<ul>
|
70 |
+
<li>Some text on li before img<img src="http://example.com/image.jpg" width="600" height="360"/></li>
|
71 |
+
<li>Some text on li before img<img src="http://example.com/image.jpg" width="600" height="360"/>and after img</li>
|
72 |
+
<li><img src="http://example.com/image.jpg" width="600" height="360"/>Some text after img</li>
|
73 |
+
</ul>
|
74 |
+
<p class="jetpack-slideshow-noscript robots-nocontent">This slideshow requires JavaScript.</p>
|
75 |
+
<div
|
76 |
+
class="slideshow-window jetpack-slideshow slideshow-black"
|
77 |
+
data-trans="fade" data-autostart="1"
|
78 |
+
data-gallery="[{"src":"http:\/\/example.com/img0.jpg","id":"434","title":"img0","alt":"","caption":"","itemprop":"image"},{"src":"http:\/\/example.com\/img1.jpg","id":"474","title":"img1","alt":"","caption":"","itemprop":"image"},{"src":"http:\/\/example.com\/img2.jpg","id":"470","title":"img2","alt":"","caption":"Image 2","itemprop":"image"},{"src":"http:\/\/example.com\/img3.jpg","id":"466","title":"Image 3","alt":"","caption":"Image 3","itemprop":"image"},{"src":"http:\/\/example.com\/img4.jpg","id":"462","title":"img4","alt":"","caption":"","itemprop":"image"}]"
|
79 |
+
itemscope itemtype="http://schema.org/ImageGallery">
|
80 |
+
</div>
|
81 |
+
|
82 |
+
<div class="tiled-gallery type-rectangular tiled-gallery-unresized" >
|
83 |
+
<div class="gallery-row">
|
84 |
+
<div class="gallery-group images-1">
|
85 |
+
<div class="tiled-gallery-item tiled-gallery-item-large">
|
86 |
+
<a href="http://www.diegoquinteiro.com/15-razoes-para-ser-contra-o-impeachment/forum/">
|
87 |
+
<meta itemprop="width" content="318">
|
88 |
+
<meta itemprop="height" content="211">
|
89 |
+
<img data-orig-file="http://example.com/img1.jpg"
|
90 |
+
data-image-meta="{"aperture":"0","credit":"","camera":"","caption":"","created_timestamp":"0","copyright":"","focal_length":"0","iso":"0","shutter_speed":"0","title":"","orientation":"0"}" data-image-title="Forum" data-image-description="" data-medium-file="http://http://example.com/img1.jpg" data-large-file="http://example.com/img1.jpg" src="http://example.com/img1.jpg?resize=318%2C211"
|
91 |
+
width="318" height="211" data-original-width="318" data-original-height="211" title="Forum" alt="riots" style="width: 318px; height: 211px;" />
|
92 |
+
</a>
|
93 |
+
<div class="tiled-gallery-caption" itemprop="caption description"> Image 1 </div>
|
94 |
+
</p>
|
95 |
+
</div>
|
96 |
+
</p>
|
97 |
+
</div>
|
98 |
+
<p> <!-- close group -->
|
99 |
+
<div class="gallery-group images-2">
|
100 |
+
<div class="tiled-gallery-item tiled-gallery-item-small" itemprop="associatedMedia">
|
101 |
+
<a href="http://example.com/link" border="0" itemprop="url">
|
102 |
+
<meta itemprop="width" content="174">
|
103 |
+
<meta itemprop="height" content="109">
|
104 |
+
<img data-attachment-id="519" data-orig-file="http://example.com/img2.jpg" data-orig-size="2078,1310" data-comments-opened="" data-image-meta="{"aperture":"0","credit":"","camera":"","caption":"","created_timestamp":"0","copyright":"","focal_length":"0","iso":"0","shutter_speed":"0","title":"","orientation":"0"}" data-image-title="Chaplin – Fábrica" data-image-description="" data-medium-file="http://example.com/img2.jpg" data-large-file="http://example.com/img2.jpg" src="http://example.com/img2.jpg?resize=174%2C109" width="174" height="109" data-original-width="174" data-original-height="109" itemprop="http://schema.org/image" title="Image Title" alt="chaplin" style="width: 174px; height: 109px;" />
|
105 |
+
</a>
|
106 |
+
<div class="tiled-gallery-caption" itemprop="caption description"> Image 2 </div>
|
107 |
+
</p>
|
108 |
+
</div>
|
109 |
+
<div class="tiled-gallery-item tiled-gallery-item-small" itemprop="associatedMedia">
|
110 |
+
<a href="http://example.com/link" border="0" itemprop="url">
|
111 |
+
<meta itemprop="width" content="174">
|
112 |
+
<meta itemprop="height" content="98">
|
113 |
+
<img data-attachment-id="532" data-orig-file="http://example.com/img3.jpg" data-image-meta="{"aperture":"0","credit":"","camera":"","caption":"","created_timestamp":"0","copyright":"","focal_length":"0","iso":"0","shutter_speed":"0","title":"","orientation":"0"}" data-image-title="highlight image" data-image-description="" data-medium-file="http://www.diegoquinteiro.com/wp-content/uploads/2016/06/highlight-image-300x169.jpg" data-large-file="http://www.diegoquinteiro.com/wp-content/uploads/2016/06/highlight-image-1024x576.jpg" src="http://i1.wp.com/www.diegoquinteiro.com/wp-content/uploads/2016/06/highlight-image.jpg?resize=174%2C98" width="174" height="98" data-original-width="174" data-original-height="98" itemprop="http://schema.org/image" title="highlight image" alt="Dog cat" style="width: 174px; height: 98px;" />
|
114 |
+
</a>
|
115 |
+
<div class="tiled-gallery-caption" itemprop="caption description"> Image 3 </div>
|
116 |
+
</p>
|
117 |
+
</div>
|
118 |
+
</p>
|
119 |
+
</div>
|
120 |
+
<p> <!-- close group -->
|
121 |
+
</div>
|
122 |
+
<p> <!-- close row -->
|
123 |
+
</div>
|
124 |
+
<p>
|
125 |
+
<figure style="width: 1280px" class="wp-caption alignnone">
|
126 |
+
<img src="http://example.com/img.jpg" width="1280" height="740" class />
|
127 |
+
<br />
|
128 |
+
<figcaption class="wp-caption-text">blue eyes</figcaption>
|
129 |
+
</figure>
|
130 |
+
</p>
|
131 |
+
|
132 |
+
</body>
|
133 |
+
</html>
|
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/Example/simple-ia.html
CHANGED
@@ -26,6 +26,11 @@
|
|
26 |
<figcaption>Photographer</figcaption>
|
27 |
</figure>
|
28 |
<p>Curabitur vulputate odio eu justo <i>venenatis</i>, a pretium orci placerat. Nam sed neque quis eros vestibulum mattis. Donec vitae mi egestas, laoreet massa et, fringilla libero.</p>
|
|
|
|
|
|
|
|
|
|
|
29 |
<figure class="op-interactive">
|
30 |
<iframe>
|
31 |
<h1>Custom code for your social embed</h1>
|
26 |
<figcaption>Photographer</figcaption>
|
27 |
</figure>
|
28 |
<p>Curabitur vulputate odio eu justo <i>venenatis</i>, a pretium orci placerat. Nam sed neque quis eros vestibulum mattis. Donec vitae mi egestas, laoreet massa et, fringilla libero.</p>
|
29 |
+
<figure class="op-interactive">
|
30 |
+
<iframe>
|
31 |
+
<iframe width="620" height="349" src="https://www.youtube.com/embed/s1tN0ggNreA?feature=oembed" frameborder="0" allowfullscreen=""/>
|
32 |
+
</iframe>
|
33 |
+
</figure>
|
34 |
<figure class="op-interactive">
|
35 |
<iframe>
|
36 |
<h1>Custom code for your social embed</h1>
|
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/Example/simple.html
CHANGED
@@ -18,6 +18,9 @@
|
|
18 |
<img src="http://domain.com/image-body.png" alt="Photographer"/>
|
19 |
</div>
|
20 |
<p>Curabitur vulputate odio eu justo <i>venenatis</i>, a pretium orci placerat. Nam sed neque quis eros vestibulum mattis. Donec vitae mi egestas, laoreet massa et, fringilla libero.</p>
|
|
|
|
|
|
|
21 |
<div class="embed">
|
22 |
<h1>Custom code for your social embed</h1>
|
23 |
<script>alert("test & more test");</script>
|
18 |
<img src="http://domain.com/image-body.png" alt="Photographer"/>
|
19 |
</div>
|
20 |
<p>Curabitur vulputate odio eu justo <i>venenatis</i>, a pretium orci placerat. Nam sed neque quis eros vestibulum mattis. Donec vitae mi egestas, laoreet massa et, fringilla libero.</p>
|
21 |
+
<div class="embed">
|
22 |
+
<iframe width="620" height="349" src="https://www.youtube.com/embed/s1tN0ggNreA?feature=oembed" frameborder="0" allowfullscreen></iframe>
|
23 |
+
</div>
|
24 |
<div class="embed">
|
25 |
<h1>Custom code for your social embed</h1>
|
26 |
<script>alert("test & more test");</script>
|
vendor/facebook/facebook-instant-articles-sdk-php/tests/Facebook/InstantArticles/Transformer/TransformerTest.php
CHANGED
@@ -97,7 +97,7 @@ class TransformerTest extends \PHPUnit_Framework_TestCase
|
|
97 |
public function testTitleTransformedWithBold()
|
98 |
{
|
99 |
$transformer = new Transformer();
|
100 |
-
$json_file = file_get_contents(__DIR__ . '/wp-rules.json');
|
101 |
$transformer->loadRules($json_file);
|
102 |
|
103 |
$title_html_string = '<?xml encoding="utf-8" ?><h1>Title <b>in bold</b></h1>';
|
97 |
public function testTitleTransformedWithBold()
|
98 |
{
|
99 |
$transformer = new Transformer();
|
100 |
+
$json_file = file_get_contents(__DIR__ . '/CMS/wp-rules.json');
|
101 |
$transformer->loadRules($json_file);
|
102 |
|
103 |
$title_html_string = '<?xml encoding="utf-8" ?><h1>Title <b>in bold</b></h1>';
|
vendor/facebook/php-sdk-v4/src/Facebook/Facebook.php
CHANGED
@@ -53,12 +53,12 @@ class Facebook
|
|
53 |
/**
|
54 |
* @const string Version number of the Facebook PHP SDK.
|
55 |
*/
|
56 |
-
const VERSION = '5.
|
57 |
|
58 |
/**
|
59 |
* @const string Default Graph API version for requests.
|
60 |
*/
|
61 |
-
const DEFAULT_GRAPH_VERSION = 'v2.
|
62 |
|
63 |
/**
|
64 |
* @const string The name of the environment variable that contains the app ID.
|
53 |
/**
|
54 |
* @const string Version number of the Facebook PHP SDK.
|
55 |
*/
|
56 |
+
const VERSION = '5.3.1';
|
57 |
|
58 |
/**
|
59 |
* @const string Default Graph API version for requests.
|
60 |
*/
|
61 |
+
const DEFAULT_GRAPH_VERSION = 'v2.7';
|
62 |
|
63 |
/**
|
64 |
* @const string The name of the environment variable that contains the app ID.
|
vendor/facebook/php-sdk-v4/src/Facebook/FacebookResponse.php
CHANGED
@@ -213,7 +213,7 @@ class FacebookResponse
|
|
213 |
/**
|
214 |
* Returns the exception that was thrown for this request.
|
215 |
*
|
216 |
-
* @return
|
217 |
*/
|
218 |
public function getThrownException()
|
219 |
{
|
213 |
/**
|
214 |
* Returns the exception that was thrown for this request.
|
215 |
*
|
216 |
+
* @return FacebookResponseException|null
|
217 |
*/
|
218 |
public function getThrownException()
|
219 |
{
|
vendor/facebook/php-sdk-v4/src/Facebook/Helpers/FacebookRedirectLoginHelper.php
CHANGED
@@ -122,7 +122,7 @@ class FacebookRedirectLoginHelper
|
|
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);
|
@@ -219,6 +219,7 @@ class FacebookRedirectLoginHelper
|
|
219 |
}
|
220 |
|
221 |
$this->validateCsrf();
|
|
|
222 |
|
223 |
$redirectUrl = $redirectUrl ?: $this->urlDetectionHandler->getCurrentUrl();
|
224 |
// At minimum we need to remove the state param
|
@@ -250,6 +251,14 @@ class FacebookRedirectLoginHelper
|
|
250 |
throw new FacebookSDKException('Cross-site request forgery validation failed. The "state" param from the URL and session do not match.');
|
251 |
}
|
252 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
253 |
/**
|
254 |
* Return the code.
|
255 |
*
|
122 |
*/
|
123 |
private function makeUrl($redirectUrl, array $scope, array $params = [], $separator = '&')
|
124 |
{
|
125 |
+
$state = $this->persistentDataHandler->get('state') ?: $this->pseudoRandomStringGenerator->getPseudoRandomString(static::CSRF_LENGTH);
|
126 |
$this->persistentDataHandler->set('state', $state);
|
127 |
|
128 |
return $this->oAuth2Client->getAuthorizationUrl($redirectUrl, $state, $scope, $params, $separator);
|
219 |
}
|
220 |
|
221 |
$this->validateCsrf();
|
222 |
+
$this->resetCsrf();
|
223 |
|
224 |
$redirectUrl = $redirectUrl ?: $this->urlDetectionHandler->getCurrentUrl();
|
225 |
// At minimum we need to remove the state param
|
251 |
throw new FacebookSDKException('Cross-site request forgery validation failed. The "state" param from the URL and session do not match.');
|
252 |
}
|
253 |
|
254 |
+
/**
|
255 |
+
* Resets the CSRF so that it doesn't get reused.
|
256 |
+
*/
|
257 |
+
private function resetCsrf()
|
258 |
+
{
|
259 |
+
$this->persistentDataHandler->set('state', null);
|
260 |
+
}
|
261 |
+
|
262 |
/**
|
263 |
* Return the code.
|
264 |
*
|
vendor/facebook/php-sdk-v4/src/Facebook/PseudoRandomString/PseudoRandomStringGeneratorTrait.php
CHANGED
@@ -48,7 +48,6 @@ trait PseudoRandomStringGeneratorTrait
|
|
48 |
*
|
49 |
* @param string $binaryData The binary data to convert to hex.
|
50 |
* @param int $length The length of the string to return.
|
51 |
-
* @throws \RuntimeException Throws an exception when multibyte support is not enabled
|
52 |
*
|
53 |
* @return string
|
54 |
*/
|
48 |
*
|
49 |
* @param string $binaryData The binary data to convert to hex.
|
50 |
* @param int $length The length of the string to return.
|
|
|
51 |
*
|
52 |
* @return string
|
53 |
*/
|
vendor/facebook/php-sdk-v4/src/Facebook/Url/FacebookUrlDetectionHandler.php
CHANGED
@@ -95,7 +95,8 @@ class FacebookUrlDetectionHandler implements UrlDetectionInterface
|
|
95 |
protected function getHostName()
|
96 |
{
|
97 |
// Check for proxy first
|
98 |
-
|
|
|
99 |
$elements = explode(',', $header);
|
100 |
$host = $elements[count($elements) - 1];
|
101 |
} elseif (!$host = $this->getHeader('HOST')) {
|
95 |
protected function getHostName()
|
96 |
{
|
97 |
// Check for proxy first
|
98 |
+
$header = $this->getHeader('X_FORWARDED_HOST');
|
99 |
+
if ($header && $this->isValidForwardedHost($header)) {
|
100 |
$elements = explode(',', $header);
|
101 |
$host = $elements[count($elements) - 1];
|
102 |
} elseif (!$host = $this->getHeader('HOST')) {
|
vendor/facebook/php-sdk-v4/src/Facebook/autoload.php
CHANGED
@@ -32,6 +32,8 @@ if (version_compare(PHP_VERSION, '5.4.0', '<')) {
|
|
32 |
throw new Exception('The Facebook SDK requires PHP version 5.4 or higher.');
|
33 |
}
|
34 |
|
|
|
|
|
35 |
/**
|
36 |
* Register the autoloader for the Facebook SDK classes.
|
37 |
*
|
32 |
throw new Exception('The Facebook SDK requires PHP version 5.4 or higher.');
|
33 |
}
|
34 |
|
35 |
+
require_once __DIR__ . '/polyfills.php';
|
36 |
+
|
37 |
/**
|
38 |
* Register the autoloader for the Facebook SDK classes.
|
39 |
*
|
wizard/class-instant-articles-invalid-wizard-transition-exception.php
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
* Exception thrown when triggering an invalid transition on the state machine.
|
12 |
+
*
|
13 |
+
* @since 3.1
|
14 |
+
*/
|
15 |
+
class Instant_Articles_Invalid_Wizard_Transition_Exception extends Exception {
|
16 |
+
public function __construct ( $original_state, $new_state ) {
|
17 |
+
parent::__construct( "Invalid transition: $original_state => $new_state." );
|
18 |
+
}
|
19 |
+
}
|
wizard/class-instant-articles-option-ads.php
ADDED
@@ -0,0 +1,245 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
'double_encode' => true,
|
59 |
+
),
|
60 |
+
|
61 |
+
'dimensions' => array(
|
62 |
+
'label' => 'Ad Dimensions',
|
63 |
+
'render' => 'select',
|
64 |
+
'select_options' => array(
|
65 |
+
'300x250' => 'Large (300 x 250)',
|
66 |
+
'320x50' => 'Small (320 x 50)',
|
67 |
+
),
|
68 |
+
'default' => '300x250',
|
69 |
+
),
|
70 |
+
|
71 |
+
);
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Constructor.
|
75 |
+
*
|
76 |
+
* @since 0.4
|
77 |
+
*/
|
78 |
+
public function __construct() {
|
79 |
+
parent::__construct(
|
80 |
+
self::OPTION_KEY,
|
81 |
+
self::$sections,
|
82 |
+
self::$fields
|
83 |
+
);
|
84 |
+
wp_localize_script( 'instant-articles-option-ads', 'INSTANT_ARTICLES_OPTION_ADS', array(
|
85 |
+
'option_field_id_source' => self::OPTION_KEY . '-ad_source',
|
86 |
+
'option_field_id_fan' => self::OPTION_KEY . '-fan_placement_id',
|
87 |
+
'option_field_id_iframe' => self::OPTION_KEY . '-iframe_url',
|
88 |
+
'option_field_id_embed' => self::OPTION_KEY . '-embed_code',
|
89 |
+
'option_field_id_dimensions' => self::OPTION_KEY . '-dimensions',
|
90 |
+
) );
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Renders the ad source.
|
95 |
+
*
|
96 |
+
* @param array $args configuration fields for the ad.
|
97 |
+
* @since 0.4
|
98 |
+
*/
|
99 |
+
public static function custom_render_ad_source( $args ) {
|
100 |
+
$id = $args['label_for'];
|
101 |
+
$name = $args['serialized_with_group'] . '[ad_source]';
|
102 |
+
|
103 |
+
$description = isset( $args['description'] )
|
104 |
+
? '<p class="description">' . esc_html( $args['description'] ) . '</p>'
|
105 |
+
: '';
|
106 |
+
|
107 |
+
?>
|
108 |
+
<select id="<?php echo esc_attr( $id ); ?>" name="<?php echo esc_attr( $name ); ?>" >
|
109 |
+
<?php foreach ( $args['select_options'] as $ad_source_key => $ad_source_name ) : ?>
|
110 |
+
<option
|
111 |
+
value="<?php echo esc_attr( $ad_source_key ); ?>"
|
112 |
+
<?php echo selected( self::$settings['ad_source'], $ad_source_key ) ?>
|
113 |
+
>
|
114 |
+
<?php echo esc_html( $ad_source_name ); ?>
|
115 |
+
</option>
|
116 |
+
<?php endforeach; ?>
|
117 |
+
|
118 |
+
<?php
|
119 |
+
$compat_plugins = parent::get_registered_compat( 'instant_articles_compat_registry_ads' );
|
120 |
+
asort( $compat_plugins );
|
121 |
+
if ( count( $compat_plugins ) > 0 ) :
|
122 |
+
?>
|
123 |
+
<optgroup label="From Supported Plugins">
|
124 |
+
<?php foreach ( $compat_plugins as $ad_source_key => $ad_source_info ) : ?>
|
125 |
+
<option
|
126 |
+
value="<?php echo esc_attr( $ad_source_key ); ?>"
|
127 |
+
<?php echo selected( self::$settings['ad_source'], $ad_source_key ) ?>
|
128 |
+
>
|
129 |
+
<?php echo esc_html( $ad_source_info['name'] ); ?>
|
130 |
+
</option>
|
131 |
+
<?php endforeach; ?>
|
132 |
+
</optgroup>
|
133 |
+
<?php endif; ?>
|
134 |
+
|
135 |
+
?>
|
136 |
+
</select>
|
137 |
+
<?php echo wp_kses_post( $description ); ?>
|
138 |
+
<?php
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Sanitize and return all the field values.
|
143 |
+
*
|
144 |
+
* This method receives a payload containing all value for its fields and
|
145 |
+
* should return the same payload after having been sanitized.
|
146 |
+
*
|
147 |
+
* Do not, encode the payload as this is performed by the
|
148 |
+
* universal_sanitize_and_encode_handler() of the parent class.
|
149 |
+
*
|
150 |
+
* @param array $field_values The array map with field values.
|
151 |
+
* @since 0.5
|
152 |
+
*/
|
153 |
+
public function sanitize_option_fields( $field_values ) {
|
154 |
+
foreach ( $field_values as $field_id => $field_value ) {
|
155 |
+
$field = self::$fields[ $field_id ];
|
156 |
+
|
157 |
+
switch ( $field_id ) {
|
158 |
+
case 'ad_source':
|
159 |
+
$all_options = array();
|
160 |
+
|
161 |
+
$registered_compat_ads = Instant_Articles_Option::get_registered_compat(
|
162 |
+
'instant_articles_compat_registry_ads'
|
163 |
+
);
|
164 |
+
|
165 |
+
foreach ( $field['select_options'] as $option_id => $option_info ) {
|
166 |
+
$all_options[] = $option_id;
|
167 |
+
}
|
168 |
+
foreach ( $registered_compat_ads as $compat_id => $compat_info ) {
|
169 |
+
$all_options[] = $compat_id;
|
170 |
+
}
|
171 |
+
|
172 |
+
if ( ! in_array( $field_value, $all_options, true ) ) {
|
173 |
+
$field_values[ $field_id ] = $field['default'];
|
174 |
+
add_settings_error(
|
175 |
+
$field_id,
|
176 |
+
'invalid_option',
|
177 |
+
'Invalid Ad Source'
|
178 |
+
);
|
179 |
+
}
|
180 |
+
break;
|
181 |
+
|
182 |
+
case 'fan_placement_id':
|
183 |
+
if ( isset( $field_values['ad_source'] ) && 'fan' === $field_values['ad_source'] ) {
|
184 |
+
if ( preg_match( '/^[0-9_]+$/', $field_values[ $field_id ] ) !== 1 ) {
|
185 |
+
add_settings_error(
|
186 |
+
$field_id,
|
187 |
+
'invalid_placement_id',
|
188 |
+
'Invalid Audience Network Placement ID provided'
|
189 |
+
);
|
190 |
+
$field_values[ $field_id ] = $field['default'];
|
191 |
+
}
|
192 |
+
}
|
193 |
+
break;
|
194 |
+
|
195 |
+
case 'iframe_url':
|
196 |
+
if ( isset( $field_values['ad_source'] ) && 'iframe' === $field_values['ad_source'] ) {
|
197 |
+
$url = $field_values[ $field_id ];
|
198 |
+
if ( substr( $url, 0, 2 ) === '//' ) {
|
199 |
+
// Allow URLs without protocol prefix
|
200 |
+
$url = 'http:' . $url;
|
201 |
+
}
|
202 |
+
$url = filter_var( $url , FILTER_VALIDATE_URL );
|
203 |
+
if ( ! $url ) {
|
204 |
+
$field_values[ $field_id ] = $field['default'];
|
205 |
+
add_settings_error(
|
206 |
+
$field_id,
|
207 |
+
'invalid_url',
|
208 |
+
'Invalid URL provided for Ad iframe'
|
209 |
+
);
|
210 |
+
}
|
211 |
+
}
|
212 |
+
break;
|
213 |
+
|
214 |
+
case 'embed_code':
|
215 |
+
if ( isset( $field_values['ad_source'] ) && 'embed' === $field_values['ad_source'] ) {
|
216 |
+
$document = new DOMDocument();
|
217 |
+
$fragment = $document->createDocumentFragment();
|
218 |
+
if ( ! @$fragment->appendXML( $field_values[ $field_id ] ) ) {
|
219 |
+
add_settings_error(
|
220 |
+
'embed_code',
|
221 |
+
'invalid_markup',
|
222 |
+
'Invalid HTML markup provided for ad custom embed code'
|
223 |
+
);
|
224 |
+
}
|
225 |
+
}
|
226 |
+
break;
|
227 |
+
|
228 |
+
case 'dimensions':
|
229 |
+
if ( isset( $field_values['ad_source'] ) && 'none' !== $field_values['ad_source'] ) {
|
230 |
+
if ( ! array_key_exists( $field_value, $field['select_options'] ) ) {
|
231 |
+
$field_values[ $field_id ] = $field['default'];
|
232 |
+
add_settings_error(
|
233 |
+
'embed_code',
|
234 |
+
'invalid_dimensions',
|
235 |
+
'Invalid dimensions provided for Ad'
|
236 |
+
);
|
237 |
+
}
|
238 |
+
}
|
239 |
+
break;
|
240 |
+
}
|
241 |
+
}
|
242 |
+
|
243 |
+
return $field_values;
|
244 |
+
}
|
245 |
+
}
|
wizard/class-instant-articles-option-analytics.php
ADDED
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 <op-tracker> tags. The plugin will automatically include them in the article markup.',
|
45 |
+
'default' => '',
|
46 |
+
'double_encode' => true,
|
47 |
+
),
|
48 |
+
);
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Constructor.
|
52 |
+
*
|
53 |
+
* @since 0.4
|
54 |
+
*/
|
55 |
+
public function __construct() {
|
56 |
+
parent::__construct(
|
57 |
+
self::OPTION_KEY,
|
58 |
+
self::$sections,
|
59 |
+
self::$fields
|
60 |
+
);
|
61 |
+
wp_localize_script( 'instant-articles-option-analytics', 'INSTANT_ARTICLES_OPTION_ANALYTICS', array(
|
62 |
+
'option_field_id_embed_code_enabled' => self::OPTION_KEY . '-embed_code_enabled',
|
63 |
+
'option_field_id_embed_code' => self::OPTION_KEY . '-embed_code',
|
64 |
+
) );
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Renders the markup for the `integrations` field.
|
69 |
+
*
|
70 |
+
* @param array $args The array with configuration of fields.
|
71 |
+
* @since 0.4
|
72 |
+
*/
|
73 |
+
public static function custom_render_integrations( $args ) {
|
74 |
+
$name = $args['serialized_with_group'] . '[integrations][]';
|
75 |
+
|
76 |
+
$compat_plugins = parent::get_registered_compat( 'instant_articles_compat_registry_analytics' );
|
77 |
+
|
78 |
+
if ( empty( $compat_plugins ) ) {
|
79 |
+
?>
|
80 |
+
<em>
|
81 |
+
<?php echo esc_html( 'No supported analytics plugins are installed nor activated' ); ?>
|
82 |
+
</em>
|
83 |
+
<?php
|
84 |
+
|
85 |
+
return;
|
86 |
+
}
|
87 |
+
|
88 |
+
asort( $compat_plugins );
|
89 |
+
foreach ( $compat_plugins as $plugin_id => $plugin_info ) {
|
90 |
+
?>
|
91 |
+
<label>
|
92 |
+
<input
|
93 |
+
type="checkbox"
|
94 |
+
name="<?php echo esc_attr( $name ); ?>"
|
95 |
+
value="<?php echo esc_attr( $plugin_id ); ?>"
|
96 |
+
<?php echo checked( in_array( $plugin_id, self::$settings['integrations'], true ) ) ?>
|
97 |
+
>
|
98 |
+
<?php echo esc_html( $plugin_info['name'] ); ?>
|
99 |
+
</label>
|
100 |
+
<br />
|
101 |
+
<?php
|
102 |
+
}
|
103 |
+
?>
|
104 |
+
<p class="description">Select which analytics services you'd like to use with Instant Articles.</p>
|
105 |
+
<?php
|
106 |
+
}
|
107 |
+
|
108 |
+
/**
|
109 |
+
* Sanitize and return all the field values.
|
110 |
+
*
|
111 |
+
* This method receives a payload containing all value for its fields and
|
112 |
+
* should return the same payload after having been sanitized.
|
113 |
+
*
|
114 |
+
* Do not encode the payload as this is performed by the
|
115 |
+
* universal_sanitize_and_encode_handler() of the parent class.
|
116 |
+
*
|
117 |
+
* @param array $field_values The values in an array mapped keys.
|
118 |
+
* @since 0.5
|
119 |
+
*/
|
120 |
+
public function sanitize_option_fields( $field_values ) {
|
121 |
+
foreach ( $field_values as $field_id => $field_value ) {
|
122 |
+
$field = self::$fields[ $field_id ];
|
123 |
+
|
124 |
+
switch ( $field_id ) {
|
125 |
+
case 'embed_code':
|
126 |
+
if ( isset( $field_values['embed_code_enabled'] ) && $field_values['embed_code_enabled'] ) {
|
127 |
+
$document = new DOMDocument();
|
128 |
+
$fragment = $document->createDocumentFragment();
|
129 |
+
if ( ! @$fragment->appendXML( $field_values[ $field_id ] ) ) {
|
130 |
+
add_settings_error(
|
131 |
+
'embed_code',
|
132 |
+
'invalid_markup',
|
133 |
+
'Invalid HTML markup provided for custom analytics tracker code'
|
134 |
+
);
|
135 |
+
}
|
136 |
+
}
|
137 |
+
|
138 |
+
break;
|
139 |
+
}
|
140 |
+
}
|
141 |
+
|
142 |
+
return $field_values;
|
143 |
+
}
|
144 |
+
}
|
wizard/class-instant-articles-option-fb-app.php
ADDED
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
'user_access_token' => array(
|
38 |
+
'visible' => false,
|
39 |
+
'label' => 'User Access Token',
|
40 |
+
'render' => 'password',
|
41 |
+
'default' => '',
|
42 |
+
),
|
43 |
+
|
44 |
+
);
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Consturctor.
|
48 |
+
*
|
49 |
+
* @since 0.4
|
50 |
+
*/
|
51 |
+
public function __construct() {
|
52 |
+
$this->options_manager = new parent(
|
53 |
+
self::OPTION_KEY,
|
54 |
+
self::$sections,
|
55 |
+
self::$fields,
|
56 |
+
/**
|
57 |
+
* Register this Option on a specific page group (used as the first
|
58 |
+
* argument of `register_setting()` and called by `settings_fields()`).
|
59 |
+
*
|
60 |
+
* @since 0.5
|
61 |
+
*/
|
62 |
+
Instant_Articles_Option::PAGE_OPTION_GROUP_WIZARD
|
63 |
+
);
|
64 |
+
}
|
65 |
+
}
|
wizard/class-instant-articles-option-fb-page.php
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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_picture' => array(
|
39 |
+
'visible' => false,
|
40 |
+
'label' => 'Page Picture',
|
41 |
+
'default' => '',
|
42 |
+
),
|
43 |
+
|
44 |
+
'page_access_token' => array(
|
45 |
+
'visible' => false,
|
46 |
+
'label' => 'Page Access Token',
|
47 |
+
'default' => '',
|
48 |
+
),
|
49 |
+
|
50 |
+
'page_access_token_expiration' => array(
|
51 |
+
'visible' => false,
|
52 |
+
'label' => 'Page Token Expiration',
|
53 |
+
'default' => '',
|
54 |
+
),
|
55 |
+
|
56 |
+
);
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Constructor.
|
60 |
+
*
|
61 |
+
* @since 0.4
|
62 |
+
*/
|
63 |
+
public function __construct() {
|
64 |
+
$this->options_manager = new parent(
|
65 |
+
self::OPTION_KEY,
|
66 |
+
self::$sections,
|
67 |
+
self::$fields,
|
68 |
+
/**
|
69 |
+
* Register this Option on a specific page group (used as the first
|
70 |
+
* argument of `register_setting()` and called by `settings_fields()`).
|
71 |
+
*
|
72 |
+
* @since 0.5
|
73 |
+
*/
|
74 |
+
Instant_Articles_Option::PAGE_OPTION_GROUP_WIZARD
|
75 |
+
);
|
76 |
+
}
|
77 |
+
}
|
wizard/class-instant-articles-option-publishing.php
ADDED
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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' => 'Articles published while in Development Mode are saved as "drafts" within Facebook and will not be made live. Note: Since articles in "draft" are not reviewed, Development Mode should be disabled when publishing articles to Facebook which you intend to use in your <a href="https://developers.facebook.com/docs/instant-articles/publishing#review" target="_blank">one-time review</a>.',
|
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' => 'Define your own rules to customize the transformation of your content into 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' => 'Read more about <a href="https://github.com/facebook/facebook-instant-articles-sdk-php/blob/master/docs/QuickStart.md#custom-transformer-rules" target="_blank">defining your own custom rules</a> to extend/override the <a href="https://github.com/Automattic/facebook-instant-articles-wp/blob/master/rules-configuration.json" target="_blank">built-in ruleset</a>. If you\'ve defined a common rule which you think this plugin should include by default, <a href="https://github.com/Automattic/facebook-instant-articles-wp/issues/new" target="_blank">tell us about it</a>!',
|
47 |
+
'default' => '',
|
48 |
+
),
|
49 |
+
|
50 |
+
'block_publish_with_warnings' => array(
|
51 |
+
'label' => 'Transformation warnings',
|
52 |
+
'description' => 'Articles won\'t be available as Instant Articles if transformation process contains warnings. Note: All warnings should be fixed in order to have them available as Instant Articles.',
|
53 |
+
'render' => 'checkbox',
|
54 |
+
'default' => false,
|
55 |
+
'checkbox_label' => 'Don\'t publish with warnings',
|
56 |
+
),
|
57 |
+
);
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Constructor.
|
61 |
+
*
|
62 |
+
* @since 0.4
|
63 |
+
*/
|
64 |
+
public function __construct() {
|
65 |
+
parent::__construct(
|
66 |
+
self::OPTION_KEY,
|
67 |
+
self::$sections,
|
68 |
+
self::$fields
|
69 |
+
);
|
70 |
+
wp_localize_script( 'instant-articles-option-publishing', 'INSTANT_ARTICLES_OPTION_PUBLISHING', array(
|
71 |
+
'option_field_id_custom_rules_enabled' => self::OPTION_KEY . '-custom_rules_enabled',
|
72 |
+
'option_field_id_custom_rules' => self::OPTION_KEY . '-custom_rules',
|
73 |
+
) );
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Sanitize and return all the field values.
|
78 |
+
*
|
79 |
+
* This method receives a payload containing all value for its fields and
|
80 |
+
* should return the same payload after having been sanitized.
|
81 |
+
*
|
82 |
+
* Do not encode the payload as this is performed by the
|
83 |
+
* universal_sanitize_and_encode_handler() of the parent class.
|
84 |
+
*
|
85 |
+
* @param array $field_values array map with key field_id => value.
|
86 |
+
* @since 0.5
|
87 |
+
*/
|
88 |
+
public function sanitize_option_fields( $field_values ) {
|
89 |
+
foreach ( $field_values as $field_id => $field_value ) {
|
90 |
+
$field = self::$fields[ $field_id ];
|
91 |
+
|
92 |
+
switch ( $field_id ) {
|
93 |
+
case 'dev_mode':
|
94 |
+
$field_values[ $field_id ] = (bool) $field_value
|
95 |
+
? (string) true
|
96 |
+
: (string) $field['default'];
|
97 |
+
break;
|
98 |
+
|
99 |
+
case 'custom_rules':
|
100 |
+
if ( isset( $field_values['custom_rules_enabled'] ) && $field_values['custom_rules_enabled'] ) {
|
101 |
+
$custom_rules_json = json_decode( $field_values['custom_rules'] );
|
102 |
+
if ( null === $custom_rules_json ) {
|
103 |
+
$field_values['custom_rules'] = $field['default'];
|
104 |
+
add_settings_error(
|
105 |
+
'custom_embed',
|
106 |
+
'invalid_json',
|
107 |
+
'Invalid JSON provided for custom rules code'
|
108 |
+
);
|
109 |
+
}
|
110 |
+
}
|
111 |
+
break;
|
112 |
+
|
113 |
+
default:
|
114 |
+
// Should never happen.
|
115 |
+
break;
|
116 |
+
}
|
117 |
+
}
|
118 |
+
|
119 |
+
return $field_values;
|
120 |
+
}
|
121 |
+
}
|
wizard/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 |
+
}
|
wizard/class-instant-articles-option.php
ADDED
@@ -0,0 +1,490 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 wp_kses_post( $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 wp_kses_post( $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 wp_kses_post( $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 wp_kses_post( $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 array_key_exists( 'double_encode', $args ) && $args[ 'double_encode' ] ? htmlspecialchars( $option_value ) : esc_html( $option_value ); ?></textarea>
|
387 |
+
<?php if ( $field_description ) : ?>
|
388 |
+
<p class="description">
|
389 |
+
<?php echo wp_kses_post( $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 wp_kses_post( $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 |
+
|
458 |
+
/**
|
459 |
+
* Updates options from decoded map
|
460 |
+
*
|
461 |
+
* @param string $option_key to be returned.
|
462 |
+
* @return array from a json decoded content.
|
463 |
+
* @since 0.4
|
464 |
+
*/
|
465 |
+
public static function update_option( $option = array(), $option_key = null ) {
|
466 |
+
if ( ! isset( $option_key ) ) {
|
467 |
+
// Late Static Binding to use the const OPTION_KEY from the child class which called this function.
|
468 |
+
$option_key = static::OPTION_KEY;
|
469 |
+
}
|
470 |
+
|
471 |
+
wp_cache_delete ( 'alloptions', 'options' );
|
472 |
+
update_option( $option_key, $option );
|
473 |
+
}
|
474 |
+
/**
|
475 |
+
* Updates options from decoded map
|
476 |
+
*
|
477 |
+
* @param string $option_key to be returned.
|
478 |
+
* @return array from a json decoded content.
|
479 |
+
* @since 0.4
|
480 |
+
*/
|
481 |
+
public static function delete_option( $option_key = null ) {
|
482 |
+
if ( ! isset( $option_key ) ) {
|
483 |
+
// Late Static Binding to use the const OPTION_KEY from the child class which called this function.
|
484 |
+
$option_key = static::OPTION_KEY;
|
485 |
+
}
|
486 |
+
|
487 |
+
wp_cache_delete ( 'alloptions', 'options' );
|
488 |
+
delete_option( $option_key );
|
489 |
+
}
|
490 |
+
}
|
wizard/class-instant-articles-wizard-fb-helper.php
ADDED
@@ -0,0 +1,212 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
require_once( dirname( __FILE__ ) . '/class-instant-articles-option-fb-app.php' );
|
10 |
+
require_once( dirname( __FILE__ ) . '/class-instant-articles-option-fb-page.php' );
|
11 |
+
require_once( dirname( __FILE__ ) . '/class-instant-articles-wizard-state.php' );
|
12 |
+
|
13 |
+
use Facebook\PersistentData\PersistentDataInterface;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Class responsible for functionality and rendering of the settings
|
17 |
+
*
|
18 |
+
* @since 0.4
|
19 |
+
*/
|
20 |
+
class Instant_Articles_Wizard_FB_Helper implements PersistentDataInterface {
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @var string Prefix to use for session options.
|
24 |
+
*/
|
25 |
+
protected $session_prefix = 'instant_articles_fbrlh_';
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @inheritdoc
|
29 |
+
*/
|
30 |
+
public function get( $key ) {
|
31 |
+
|
32 |
+
return get_option( $this->session_prefix . $key );
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* @inheritdoc
|
37 |
+
*/
|
38 |
+
public function set( $key, $value ) {
|
39 |
+
|
40 |
+
update_option( $this->session_prefix . $key, $value );
|
41 |
+
}
|
42 |
+
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Facebook Permissions.
|
46 |
+
*
|
47 |
+
* @var array $fb_app_permissions The permissions asked for FB user to list pages he manages.
|
48 |
+
*/
|
49 |
+
public static $fb_app_permissions = array( 'pages_manage_instant_articles', 'pages_show_list' );
|
50 |
+
|
51 |
+
/**
|
52 |
+
* SDK instance.
|
53 |
+
*
|
54 |
+
* @var Facebook $fb_sdk the instance reference to FB sdk
|
55 |
+
*/
|
56 |
+
public $fb_sdk;
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Settings structure.
|
60 |
+
*
|
61 |
+
* @var array $fb_app_settings The map data structure to store settings.
|
62 |
+
*/
|
63 |
+
protected $fb_app_settings;
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Constructor for Settings page.
|
67 |
+
*
|
68 |
+
* @since 0.4
|
69 |
+
*/
|
70 |
+
public function __construct() {
|
71 |
+
$this->fb_app_settings = Instant_Articles_Option_FB_App::get_option_decoded();
|
72 |
+
|
73 |
+
if ( isset( $this->fb_app_settings['app_id'] ) && isset( $this->fb_app_settings['app_secret'] ) ) {
|
74 |
+
$app_id = $this->fb_app_settings['app_id'];
|
75 |
+
$app_secret = $this->fb_app_settings['app_secret'];
|
76 |
+
}
|
77 |
+
|
78 |
+
if ( ! empty( $app_id ) && ! empty( $app_secret ) ) {
|
79 |
+
$this->fb_sdk = new Facebook\Facebook(array(
|
80 |
+
'app_id' => $app_id,
|
81 |
+
'app_secret' => $app_secret,
|
82 |
+
'default_graph_version' => 'v2.6',
|
83 |
+
'persistent_data_handler' => $this
|
84 |
+
));
|
85 |
+
}
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Gets the login url.
|
90 |
+
*
|
91 |
+
* @since 0.4
|
92 |
+
*/
|
93 |
+
public function get_login_url() {
|
94 |
+
if ( isset( $this->fb_sdk ) ) {
|
95 |
+
$helper = $this->fb_sdk->getRedirectLoginHelper();
|
96 |
+
$redirect_url = Instant_Articles_Wizard::get_url();
|
97 |
+
|
98 |
+
$login_url = $helper->getLoginUrl(
|
99 |
+
$redirect_url,
|
100 |
+
self::$fb_app_permissions
|
101 |
+
);
|
102 |
+
|
103 |
+
return $login_url;
|
104 |
+
}
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Retrieves granted permissions.
|
109 |
+
*
|
110 |
+
* @param string $access_token The user access token.
|
111 |
+
* @since 0.5
|
112 |
+
*/
|
113 |
+
public function get_fb_permissions( $access_token ) {
|
114 |
+
|
115 |
+
$permissions = array();
|
116 |
+
|
117 |
+
if ( isset( $this->fb_sdk ) && $access_token ) {
|
118 |
+
|
119 |
+
try {
|
120 |
+
$permissions_query = $this->fb_sdk->get( '/me/permissions', $access_token );
|
121 |
+
$decoded_permissions = $permissions_query->getDecodedBody();
|
122 |
+
if ( isset( $decoded_permissions['data'] ) ) {
|
123 |
+
foreach ( $decoded_permissions['data'] as $permission ) {
|
124 |
+
if ( 'granted' === $permission['status'] ) {
|
125 |
+
$permissions[ $permission['permission'] ] = 'granted';
|
126 |
+
}
|
127 |
+
}
|
128 |
+
}
|
129 |
+
} catch (Facebook\Exceptions\FacebookResponseException $e) {
|
130 |
+
// When Graph returns an error.
|
131 |
+
Logger::getLogger( 'instantarticles-wp-plugin' )->error(
|
132 |
+
'Graph returned an error: '.$e->getMessage(),
|
133 |
+
$e->getTraceAsString()
|
134 |
+
);
|
135 |
+
|
136 |
+
} catch (Facebook\Exceptions\FacebookSDKException $e) {
|
137 |
+
// When validation fails or other local issues.
|
138 |
+
Logger::getLogger( 'instantarticles-wp-plugin' )->error(
|
139 |
+
'Facebook SDK returned an error: '.$e->getMessage(),
|
140 |
+
$e->getTraceAsString()
|
141 |
+
);
|
142 |
+
|
143 |
+
}
|
144 |
+
}
|
145 |
+
|
146 |
+
if ( isset( $permissions ) ) {
|
147 |
+
// Logged in.
|
148 |
+
return $permissions;
|
149 |
+
}
|
150 |
+
}
|
151 |
+
|
152 |
+
/**
|
153 |
+
* Retrieves Facebook access token.
|
154 |
+
*
|
155 |
+
* @since 0.4
|
156 |
+
*/
|
157 |
+
public function get_fb_access_token() {
|
158 |
+
$access_token = null;
|
159 |
+
|
160 |
+
if ( isset( $this->fb_sdk ) ) {
|
161 |
+
try {
|
162 |
+
$helper = $this->fb_sdk->getRedirectLoginHelper();
|
163 |
+
$access_token = $helper->getAccessToken();
|
164 |
+
} catch (Facebook\Exceptions\FacebookResponseException $e) {
|
165 |
+
// When Graph returns an error.
|
166 |
+
Logger::getLogger( 'instantarticles-wp-plugin' )->error(
|
167 |
+
'Graph returned an error: '.$e->getMessage(),
|
168 |
+
$e->getTraceAsString()
|
169 |
+
);
|
170 |
+
|
171 |
+
} catch (Facebook\Exceptions\FacebookSDKException $e) {
|
172 |
+
// When validation fails or other local issues.
|
173 |
+
Logger::getLogger( 'instantarticles-wp-plugin' )->error(
|
174 |
+
'Facebook SDK returned an error: '.$e->getMessage(),
|
175 |
+
$e->getTraceAsString()
|
176 |
+
);
|
177 |
+
}
|
178 |
+
}
|
179 |
+
|
180 |
+
if ( null !== $access_token ) {
|
181 |
+
// Logged in.
|
182 |
+
return $access_token;
|
183 |
+
}
|
184 |
+
}
|
185 |
+
|
186 |
+
public function get_pages() {
|
187 |
+
$helper = new Facebook\InstantArticles\Client\Helper(
|
188 |
+
$this->fb_sdk
|
189 |
+
);
|
190 |
+
|
191 |
+
$fb_app_settings = Instant_Articles_Option_FB_App::get_option_decoded();
|
192 |
+
|
193 |
+
$page_nodes = $helper->getPagesAndTokens(
|
194 |
+
new Facebook\Authentication\AccessToken( $fb_app_settings[ 'user_access_token' ] )
|
195 |
+
)->all();
|
196 |
+
|
197 |
+
$pages = array();
|
198 |
+
|
199 |
+
// Map GraphNode objects to simple value objects that are smaller when serialized.
|
200 |
+
foreach ( $page_nodes as $page_node ) {
|
201 |
+
$pages[ $page_node->getField( 'id' ) ] = array(
|
202 |
+
'page_id' => $page_node->getField( 'id' ),
|
203 |
+
'page_name' => $page_node->getField( 'name' ),
|
204 |
+
'page_picture' => $page_node->getField( 'picture' )->getField( 'url' ),
|
205 |
+
'page_access_token' => $page_node->getField( 'access_token' ),
|
206 |
+
'supports_instant_articles' => $page_node->getField( 'supports_instant_articles' ),
|
207 |
+
);
|
208 |
+
}
|
209 |
+
|
210 |
+
return $pages;
|
211 |
+
}
|
212 |
+
}
|
wizard/class-instant-articles-wizard-review-submission.php
ADDED
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
require_once( dirname( __FILE__ ) . '/class-instant-articles-option-fb-app.php' );
|
10 |
+
require_once( dirname( __FILE__ ) . '/class-instant-articles-option-fb-page.php' );
|
11 |
+
|
12 |
+
use Facebook\InstantArticles\Client\Client;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Class responsible for functionality and rendering of the review settings
|
16 |
+
*
|
17 |
+
* @since 3.1
|
18 |
+
*/
|
19 |
+
class Instant_Articles_Wizard_Review_Submission {
|
20 |
+
|
21 |
+
const MIN_ARTICLES = 5;
|
22 |
+
|
23 |
+
const STATUS_REJECTED = 'REJECTED';
|
24 |
+
const STATUS_APPROVED = 'APPROVED';
|
25 |
+
const STATUS_PENDING = 'PENDING';
|
26 |
+
const STATUS_NOT_SUBMITTED = 'NOT_SUBMITTED';
|
27 |
+
|
28 |
+
public static function getArticlesForReview() {
|
29 |
+
$post_types = apply_filters( 'instant_articles_post_types', array( 'post' ) );
|
30 |
+
|
31 |
+
// Cap the number of articles returned to
|
32 |
+
// 100 because of performance concerns.
|
33 |
+
return wp_get_recent_posts(
|
34 |
+
array(
|
35 |
+
'numberposts' => min( self::MIN_ARTICLES, 100 ),
|
36 |
+
'post_type' => $post_types
|
37 |
+
),
|
38 |
+
'OBJECT'
|
39 |
+
);
|
40 |
+
}
|
41 |
+
|
42 |
+
public static function getPageID() {
|
43 |
+
if ( ! static::isPageSet() ) {
|
44 |
+
return null;
|
45 |
+
}
|
46 |
+
$fb_page_settings = Instant_Articles_Option_FB_Page::get_option_decoded();
|
47 |
+
return $fb_page_settings['page_id'];
|
48 |
+
}
|
49 |
+
|
50 |
+
public static function isPageSet() {
|
51 |
+
$fb_app_settings = Instant_Articles_Option_FB_App::get_option_decoded();
|
52 |
+
$fb_page_settings = Instant_Articles_Option_FB_Page::get_option_decoded();
|
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 |
+
return true;
|
59 |
+
}
|
60 |
+
|
61 |
+
return false;
|
62 |
+
}
|
63 |
+
|
64 |
+
public static function getClient() {
|
65 |
+
if ( ! static::isPageSet() ) {
|
66 |
+
return null;
|
67 |
+
}
|
68 |
+
|
69 |
+
$fb_app_settings = Instant_Articles_Option_FB_App::get_option_decoded();
|
70 |
+
$fb_page_settings = Instant_Articles_Option_FB_Page::get_option_decoded();
|
71 |
+
|
72 |
+
$client = Client::create(
|
73 |
+
$fb_app_settings['app_id'],
|
74 |
+
$fb_app_settings['app_secret'],
|
75 |
+
$fb_page_settings['page_access_token'],
|
76 |
+
$fb_page_settings['page_id'],
|
77 |
+
false
|
78 |
+
);
|
79 |
+
|
80 |
+
return $client;
|
81 |
+
}
|
82 |
+
|
83 |
+
public static function getReviewSubmissionStatus() {
|
84 |
+
if ( ! static::isPageSet() ) {
|
85 |
+
return null;
|
86 |
+
}
|
87 |
+
return static::getClient()->getReviewSubmissionStatus();
|
88 |
+
}
|
89 |
+
|
90 |
+
public static function getArticlesURLs() {
|
91 |
+
if ( ! static::isPageSet() ) {
|
92 |
+
return null;
|
93 |
+
}
|
94 |
+
return static::getClient()->getArticlesURLs(static::MIN_ARTICLES);
|
95 |
+
}
|
96 |
+
}
|
wizard/class-instant-articles-wizard-state.php
ADDED
@@ -0,0 +1,352 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
require_once( dirname( __FILE__ ) . '/class-instant-articles-option-ads.php' );
|
10 |
+
require_once( dirname( __FILE__ ) . '/class-instant-articles-option-analytics.php' );
|
11 |
+
require_once( dirname( __FILE__ ) . '/class-instant-articles-option-fb-app.php' );
|
12 |
+
require_once( dirname( __FILE__ ) . '/class-instant-articles-option-fb-page.php' );
|
13 |
+
require_once( dirname( __FILE__ ) . '/class-instant-articles-option-publishing.php' );
|
14 |
+
require_once( dirname( __FILE__ ) . '/class-instant-articles-option-styles.php' );
|
15 |
+
require_once( dirname( __FILE__ ) . '/class-instant-articles-invalid-wizard-transition-exception.php' );
|
16 |
+
require_once( dirname( __FILE__ ) . '/class-instant-articles-wizard-fb-helper.php' );
|
17 |
+
require_once( dirname( __FILE__ ) . '/class-instant-articles-wizard-review-submission.php' );
|
18 |
+
|
19 |
+
use Facebook\InstantArticles\Client\Client;
|
20 |
+
use Facebook\InstantArticles\Client\ClientException;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Set-up wizard state machine.
|
24 |
+
*
|
25 |
+
* @since 3.1
|
26 |
+
* @see ./state_machine.txt
|
27 |
+
*/
|
28 |
+
class Instant_Articles_Wizard_State {
|
29 |
+
|
30 |
+
// STATES
|
31 |
+
const STATE_OVERVIEW = 'STATE_OVERVIEW';
|
32 |
+
const STATE_APP_SETUP = 'STATE_APP_SETUP';
|
33 |
+
const STATE_PAGE_SELECTION = 'STATE_PAGE_SELECTION';
|
34 |
+
const STATE_STYLE_SELECTION = 'STATE_STYLE_SELECTION';
|
35 |
+
const STATE_REVIEW_SUBMISSION = 'STATE_REVIEW_SUBMISSION';
|
36 |
+
|
37 |
+
// TRANSITIONS
|
38 |
+
const TRANSITION_START_WIZARD = 'TRANSITION_START_WIZARD';
|
39 |
+
const TRANSITION_SET_UP_APP = 'TRANSITION_SET_UP_APP';
|
40 |
+
const TRANSITION_SELECT_PAGE = 'TRANSITION_SELECT_PAGE';
|
41 |
+
const TRANSITION_SELECT_STYLE = 'TRANSITION_SELECT_STYLE';
|
42 |
+
const TRANSITION_EDIT_STYLE = 'TRANSITION_EDIT_STYLE';
|
43 |
+
const TRANSITION_EDIT_PAGE = 'TRANSITION_EDIT_PAGE';
|
44 |
+
const TRANSITION_EDIT_APP = 'TRANSITION_EDIT_APP';
|
45 |
+
|
46 |
+
// WIZARD TIMELINE
|
47 |
+
const TIMELINE_PAST = 'TIMELINE_PAST';
|
48 |
+
const TIMELINE_CURRENT = 'TIMELINE_CURRENT';
|
49 |
+
const TIMELINE_FUTURE = 'TIMELINE_FUTURE';
|
50 |
+
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Transition vectors, format:
|
54 |
+
*
|
55 |
+
* array(
|
56 |
+
* ORIGINAL_STATE => array(
|
57 |
+
* NEW_STATE => TRANSITION_NAME,
|
58 |
+
* ...
|
59 |
+
* ),
|
60 |
+
* ...
|
61 |
+
* )
|
62 |
+
*
|
63 |
+
*/
|
64 |
+
public static $transition_vectors = array(
|
65 |
+
self::STATE_OVERVIEW => array (
|
66 |
+
self::STATE_APP_SETUP => self::TRANSITION_START_WIZARD
|
67 |
+
),
|
68 |
+
self::STATE_APP_SETUP => array (
|
69 |
+
self::STATE_PAGE_SELECTION => self::TRANSITION_SET_UP_APP
|
70 |
+
),
|
71 |
+
self::STATE_PAGE_SELECTION => array (
|
72 |
+
self::STATE_STYLE_SELECTION => self::TRANSITION_SELECT_PAGE,
|
73 |
+
self::STATE_APP_SETUP => self::TRANSITION_EDIT_APP
|
74 |
+
),
|
75 |
+
self::STATE_STYLE_SELECTION => array (
|
76 |
+
self::STATE_REVIEW_SUBMISSION => self::TRANSITION_SELECT_STYLE,
|
77 |
+
self::STATE_PAGE_SELECTION => self::TRANSITION_EDIT_PAGE,
|
78 |
+
self::STATE_APP_SETUP => self::TRANSITION_EDIT_APP
|
79 |
+
),
|
80 |
+
self::STATE_REVIEW_SUBMISSION => array (
|
81 |
+
self::STATE_STYLE_SELECTION => self::TRANSITION_EDIT_STYLE,
|
82 |
+
self::STATE_PAGE_SELECTION => self::TRANSITION_EDIT_PAGE,
|
83 |
+
self::STATE_APP_SETUP => self::TRANSITION_EDIT_APP
|
84 |
+
),
|
85 |
+
);
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Order of states on the wizard
|
89 |
+
*/
|
90 |
+
public static $timeline = array(
|
91 |
+
self::STATE_OVERVIEW => 0,
|
92 |
+
self::STATE_APP_SETUP => 1,
|
93 |
+
self::STATE_PAGE_SELECTION => 2,
|
94 |
+
self::STATE_STYLE_SELECTION => 3,
|
95 |
+
self::STATE_REVIEW_SUBMISSION => 4
|
96 |
+
);
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Gets the timeline position for a given state.
|
100 |
+
*
|
101 |
+
* @param string $state The state constant
|
102 |
+
* @return string The timeline constant (PAST, CURRENT or FUTURE)
|
103 |
+
*/
|
104 |
+
public static function get_timeline_position( $state ) {
|
105 |
+
$current_state = self::get_current_state();
|
106 |
+
|
107 |
+
if ( self::$timeline[ $current_state ] > self::$timeline[ $state ] ) {
|
108 |
+
return self::TIMELINE_PAST;
|
109 |
+
} elseif ( $state === $current_state ) {
|
110 |
+
if (
|
111 |
+
$current_state === self::STATE_REVIEW_SUBMISSION &&
|
112 |
+
Instant_Articles_Wizard_Review_Submission::getReviewSubmissionStatus() === Instant_Articles_Wizard_Review_Submission::STATUS_APPROVED
|
113 |
+
) {
|
114 |
+
return self::TIMELINE_PAST;
|
115 |
+
}
|
116 |
+
return self::TIMELINE_CURRENT;
|
117 |
+
} else {
|
118 |
+
return self::TIMELINE_FUTURE;
|
119 |
+
}
|
120 |
+
}
|
121 |
+
|
122 |
+
/**
|
123 |
+
* Retrieves the current state of the wizard
|
124 |
+
*
|
125 |
+
* @return string The state constant for the current state
|
126 |
+
*/
|
127 |
+
public static function get_current_state() {
|
128 |
+
|
129 |
+
$option = get_option( 'instant-articles-current-state', null );
|
130 |
+
if ( in_array( $option, array_keys( self::$transition_vectors ) ) ) {
|
131 |
+
return $option;
|
132 |
+
}
|
133 |
+
|
134 |
+
// Legacy compatibility - calculate state from existing setup step
|
135 |
+
$fb_page_settings = Instant_Articles_Option_FB_Page::get_option_decoded();
|
136 |
+
$fb_app_settings = Instant_Articles_Option_FB_App::get_option_decoded();
|
137 |
+
|
138 |
+
$app_set_up = ! empty( $fb_app_settings['app_id'] ) && ! empty( $fb_app_settings['app_secret'] );
|
139 |
+
$user_logged_in = ! empty( $fb_app_settings['user_access_token'] );
|
140 |
+
$page_selected = ! empty( $fb_page_settings['page_id'] ) && ! empty( $fb_page_settings['page_name'] );
|
141 |
+
$review_submitted = Instant_Articles_Wizard_Review_Submission::getReviewSubmissionStatus() === Instant_Articles_Wizard_Review_Submission::STATUS_NOT_SUBMITTED;
|
142 |
+
|
143 |
+
if ( ! $app_set_up ) {
|
144 |
+
return self::STATE_OVERVIEW;
|
145 |
+
} elseif ( ! $user_logged_in && ! $page_selected ) {
|
146 |
+
return self::STATE_APP_SETUP;
|
147 |
+
} elseif ( ! $page_selected ) {
|
148 |
+
return self::STATE_PAGE_SELECTION;
|
149 |
+
} elseif ( ! $review_submitted ) {
|
150 |
+
return self::STATE_REVIEW_SUBMISSION;
|
151 |
+
} else {
|
152 |
+
return self::STATE_STYLE_SELECTION;
|
153 |
+
}
|
154 |
+
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Calculates the transition name for 2 given states
|
159 |
+
*
|
160 |
+
* @param string $from Original state constant
|
161 |
+
* @param string $to New state constant
|
162 |
+
* @return string The transition constant or null for invalid transitions
|
163 |
+
*/
|
164 |
+
public static function get_transition( $from, $to ) {
|
165 |
+
if ( isset ( self::$transition_vectors[ $from ][ $to ] ) ) {
|
166 |
+
return self::$transition_vectors[ $from ][ $to ];
|
167 |
+
}
|
168 |
+
return null;
|
169 |
+
}
|
170 |
+
|
171 |
+
|
172 |
+
/**
|
173 |
+
* Executes the transition from the current state to a new state
|
174 |
+
*
|
175 |
+
* @param string $new_state Constant for the final state of the transition
|
176 |
+
* @param mixed[] $params Parameters for the transition
|
177 |
+
* @throws Instant_Articles_Invalid_Wizard_Transition_Exception if an invalid transition is attempted
|
178 |
+
*/
|
179 |
+
public static function do_transition( $new_state, $params = array() ) {
|
180 |
+
$current_state = self::get_current_state();
|
181 |
+
$transition = self::get_transition( $current_state, $new_state );
|
182 |
+
|
183 |
+
if ( $transition === null ) {
|
184 |
+
throw new Instant_Articles_Invalid_Wizard_Transition_Exception( $current_state, $new_state );
|
185 |
+
}
|
186 |
+
|
187 |
+
switch ( $transition ) {
|
188 |
+
case self::TRANSITION_START_WIZARD:
|
189 |
+
return self::transition_start_wizard();
|
190 |
+
|
191 |
+
case self::TRANSITION_SET_UP_APP:
|
192 |
+
return self::transition_set_up_app( $params[ 'app_id' ], $params[ 'app_secret'], $params[ 'user_access_token' ] );
|
193 |
+
|
194 |
+
case self::TRANSITION_SELECT_PAGE:
|
195 |
+
// TODO: validate params
|
196 |
+
return self::transition_select_page( $params[ 'page_id'] );
|
197 |
+
case self::TRANSITION_SELECT_STYLE:
|
198 |
+
// TODO: validate params
|
199 |
+
return self::transition_select_style();
|
200 |
+
case self::TRANSITION_EDIT_APP:
|
201 |
+
return self::transition_edit_app();
|
202 |
+
case self::TRANSITION_EDIT_PAGE:
|
203 |
+
return self::transition_edit_page();
|
204 |
+
case self::TRANSITION_EDIT_STYLE:
|
205 |
+
return self::transition_edit_style();
|
206 |
+
}
|
207 |
+
}
|
208 |
+
|
209 |
+
/**
|
210 |
+
* Claims the URL for this site.
|
211 |
+
*/
|
212 |
+
public static function claim_url() {
|
213 |
+
$fb_app_settings = Instant_Articles_Option_FB_App::get_option_decoded();
|
214 |
+
$fb_page_settings = Instant_Articles_Option_FB_Page::get_option_decoded();
|
215 |
+
|
216 |
+
if ( ! $fb_app_settings[ 'app_id' ] ) {
|
217 |
+
throw new InvalidArgumentException( 'Missing app_id for claiming the URL.' );
|
218 |
+
}
|
219 |
+
if ( ! $fb_app_settings[ 'app_secret' ] ) {
|
220 |
+
throw new InvalidArgumentException( 'Missing app_secret for claiming the URL.' );
|
221 |
+
}
|
222 |
+
if ( ! $fb_page_settings[ 'page_access_token' ] ) {
|
223 |
+
throw new InvalidArgumentException( 'Missing page_access_token for claiming the URL.' );
|
224 |
+
}
|
225 |
+
if ( ! $fb_page_settings[ 'page_id' ] ) {
|
226 |
+
throw new InvalidArgumentException( 'Missing page_id for claiming the URL.' );
|
227 |
+
}
|
228 |
+
|
229 |
+
$client = Client::create(
|
230 |
+
$fb_app_settings[ 'app_id' ],
|
231 |
+
$fb_app_settings[ 'app_secret' ],
|
232 |
+
$fb_page_settings[ 'page_access_token' ],
|
233 |
+
$fb_page_settings[ 'page_id' ]
|
234 |
+
);
|
235 |
+
|
236 |
+
|
237 |
+
// We need the home URL without the protocol for claiming
|
238 |
+
$url = preg_replace( '/^https?:\/\//i', '', esc_url_raw( home_url( '/' ) ) );
|
239 |
+
|
240 |
+
try {
|
241 |
+
$client->claimURL( $url );
|
242 |
+
} catch (Exception $e) {
|
243 |
+
// Here we override the error message to give an actionable
|
244 |
+
// instruction to the user that is specific for WordPress.
|
245 |
+
throw new Exception("Could not claim the URL for the selected page, please make sure your site is publicly available.");
|
246 |
+
}
|
247 |
+
}
|
248 |
+
|
249 |
+
//---------------------------
|
250 |
+
// Transition implementations
|
251 |
+
//---------------------------
|
252 |
+
|
253 |
+
/**
|
254 |
+
* Transition for when starting the wizard from overview.
|
255 |
+
*/
|
256 |
+
private static function transition_start_wizard() {
|
257 |
+
return update_option( 'instant-articles-current-state', self::STATE_APP_SETUP );
|
258 |
+
}
|
259 |
+
|
260 |
+
/**
|
261 |
+
* Transition for when the user inputs the app info and logs in with it's personal account.
|
262 |
+
*/
|
263 |
+
private static function transition_set_up_app( $app_id, $app_secret, $user_access_token ) {
|
264 |
+
if ( ! $app_id ) {
|
265 |
+
throw new InvalidArgumentException( 'Missing App ID when authenticating the plugin' );
|
266 |
+
}
|
267 |
+
if ( ! $app_secret ) {
|
268 |
+
throw new InvalidArgumentException( 'Missing App Secret when authenticating the plugin' );
|
269 |
+
}
|
270 |
+
if ( ! $user_access_token ) {
|
271 |
+
throw new InvalidArgumentException( 'Missing Access Token when authenticating the plugin' );
|
272 |
+
}
|
273 |
+
|
274 |
+
Instant_Articles_Option_FB_App::update_option( array(
|
275 |
+
'app_id' => $app_id,
|
276 |
+
'app_secret' => $app_secret,
|
277 |
+
'user_access_token' => $user_access_token
|
278 |
+
) );
|
279 |
+
return update_option( 'instant-articles-current-state', self::STATE_PAGE_SELECTION );
|
280 |
+
}
|
281 |
+
|
282 |
+
/**
|
283 |
+
* Transition for when the user selects the page to connect to.
|
284 |
+
*
|
285 |
+
* This transition stores page info including the long-lived access token information.
|
286 |
+
*/
|
287 |
+
private static function transition_select_page( $page_id ) {
|
288 |
+
if ( ! $page_id ) {
|
289 |
+
throw new InvalidArgumentException( 'Missing Page ID when selcting the page' );
|
290 |
+
}
|
291 |
+
|
292 |
+
$fb_helper = new Instant_Articles_Wizard_FB_Helper();
|
293 |
+
$pages = $fb_helper->get_pages();
|
294 |
+
|
295 |
+
if ( ! $pages[ $page_id ] ) {
|
296 |
+
throw new InvalidArgumentException( 'Invalid Page ID when selcting the page' );
|
297 |
+
}
|
298 |
+
if ( ! $pages[ $page_id ][ 'supports_instant_articles'] ) {
|
299 |
+
throw new InvalidArgumentException( 'Selected page is not signed up to Instant Articles' );
|
300 |
+
}
|
301 |
+
|
302 |
+
Instant_Articles_Option_FB_Page::update_option( $pages[ $page_id ] );
|
303 |
+
|
304 |
+
// You should always claim the URL after updating the FB Page option so the fb:pages meta tag is rendered.
|
305 |
+
self::claim_url();
|
306 |
+
|
307 |
+
return update_option( 'instant-articles-current-state', self::STATE_STYLE_SELECTION );
|
308 |
+
}
|
309 |
+
|
310 |
+
/**
|
311 |
+
* Transition for when the user confirms he has selected the style for the articles.
|
312 |
+
*/
|
313 |
+
private static function transition_select_style() {
|
314 |
+
return update_option( 'instant-articles-current-state', self::STATE_REVIEW_SUBMISSION );
|
315 |
+
}
|
316 |
+
|
317 |
+
/**
|
318 |
+
* Transition for when the user decides to change the FB App.
|
319 |
+
*/
|
320 |
+
private static function transition_edit_app() {
|
321 |
+
Instant_Articles_Option_FB_App::delete_option();
|
322 |
+
Instant_Articles_Option_FB_Page::delete_option();
|
323 |
+
return update_option( 'instant-articles-current-state', self::STATE_APP_SETUP );
|
324 |
+
}
|
325 |
+
|
326 |
+
/**
|
327 |
+
* Transition for when the user decides to change the selected page.
|
328 |
+
*/
|
329 |
+
private static function transition_edit_page() {
|
330 |
+
Instant_Articles_Option_FB_Page::delete_option();
|
331 |
+
|
332 |
+
// For backwards compatibility, we transition one step back
|
333 |
+
// for users of the old versions that selected a page but the
|
334 |
+
// plugin didn't save the user access token. In this case
|
335 |
+
// we need the user to log in again.
|
336 |
+
$fb_app_settings = Instant_Articles_Option_FB_App::get_option_decoded();
|
337 |
+
$user_logged_in = ! empty( $fb_app_settings['user_access_token'] );
|
338 |
+
if ( ! $user_logged_in ) {
|
339 |
+
return update_option( 'instant-articles-current-state', self::STATE_APP_SETUP );
|
340 |
+
}
|
341 |
+
|
342 |
+
return update_option( 'instant-articles-current-state', self::STATE_PAGE_SELECTION );
|
343 |
+
}
|
344 |
+
|
345 |
+
/**
|
346 |
+
* Transition for when the user decides to edit the style.
|
347 |
+
*/
|
348 |
+
private static function transition_edit_style() {
|
349 |
+
return update_option( 'instant-articles-current-state', self::STATE_STYLE_SELECTION );
|
350 |
+
}
|
351 |
+
|
352 |
+
}
|
wizard/class-instant-articles-wizard.php
ADDED
@@ -0,0 +1,295 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
require_once( dirname( __FILE__ ) . '/class-instant-articles-option-ads.php' );
|
10 |
+
require_once( dirname( __FILE__ ) . '/class-instant-articles-option-analytics.php' );
|
11 |
+
require_once( dirname( __FILE__ ) . '/class-instant-articles-option-fb-app.php' );
|
12 |
+
require_once( dirname( __FILE__ ) . '/class-instant-articles-option-fb-page.php' );
|
13 |
+
require_once( dirname( __FILE__ ) . '/class-instant-articles-option-publishing.php' );
|
14 |
+
require_once( dirname( __FILE__ ) . '/class-instant-articles-option-styles.php' );
|
15 |
+
require_once( dirname( __FILE__ ) . '/class-instant-articles-wizard-state.php' );
|
16 |
+
require_once( dirname( __FILE__ ) . '/class-instant-articles-wizard-fb-helper.php' );
|
17 |
+
require_once( dirname( __FILE__ ) . '/class-instant-articles-wizard-review-submission.php' );
|
18 |
+
|
19 |
+
use Facebook\InstantArticles\Client\Client;
|
20 |
+
use Facebook\InstantArticles\Client\ClientException;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Controller for Set-up Wizard
|
24 |
+
*
|
25 |
+
* @since 3.1
|
26 |
+
*/
|
27 |
+
class Instant_Articles_Wizard {
|
28 |
+
|
29 |
+
public static function init() {
|
30 |
+
add_action( 'admin_menu', array( 'Instant_Articles_Wizard', 'menu_items' ) );
|
31 |
+
|
32 |
+
add_filter( 'plugin_action_links_' . IA_PLUGIN_PATH, array( 'Instant_Articles_Wizard', 'add_settings_link_to_plugin_actions' ) );
|
33 |
+
|
34 |
+
add_action( 'admin_init', function () {
|
35 |
+
new Instant_Articles_Option_FB_App();
|
36 |
+
new Instant_Articles_Option_FB_Page();
|
37 |
+
new Instant_Articles_Option_Styles();
|
38 |
+
new Instant_Articles_Option_Ads();
|
39 |
+
new Instant_Articles_Option_Analytics();
|
40 |
+
new Instant_Articles_Option_Publishing();
|
41 |
+
});
|
42 |
+
|
43 |
+
add_action(
|
44 |
+
'wp_ajax_instant_articles_wizard_transition',
|
45 |
+
array( 'Instant_Articles_Wizard', 'transition' )
|
46 |
+
);
|
47 |
+
|
48 |
+
add_action(
|
49 |
+
'wp_ajax_instant_articles_wizard_save_app',
|
50 |
+
array( 'Instant_Articles_Wizard', 'save_app' )
|
51 |
+
);
|
52 |
+
|
53 |
+
add_action(
|
54 |
+
'wp_ajax_instant_articles_wizard_edit_app',
|
55 |
+
array( 'Instant_Articles_Wizard', 'edit_app' )
|
56 |
+
);
|
57 |
+
|
58 |
+
add_action(
|
59 |
+
'wp_ajax_instant_articles_wizard_is_page_signed_up',
|
60 |
+
array( 'Instant_Articles_Wizard', 'is_page_signed_up' )
|
61 |
+
);
|
62 |
+
|
63 |
+
add_action(
|
64 |
+
'wp_ajax_instant_articles_wizard_submit_for_review',
|
65 |
+
array( 'Instant_Articles_Wizard', 'submit_for_review' )
|
66 |
+
);
|
67 |
+
}
|
68 |
+
|
69 |
+
public static function add_settings_link_to_plugin_actions( $links ) {
|
70 |
+
$link_text = __( 'Settings' );
|
71 |
+
$settings_href = self::get_url();
|
72 |
+
$settings_link = '<a href="' . esc_url( $settings_href ) . '">' . esc_html( $link_text ) . '</a>';
|
73 |
+
array_push( $links, $settings_link );
|
74 |
+
return $links;
|
75 |
+
}
|
76 |
+
|
77 |
+
public static function menu_items() {
|
78 |
+
add_menu_page(
|
79 |
+
'Instant Articles Setup Wizard',
|
80 |
+
'Instant Articles',
|
81 |
+
'manage_options',
|
82 |
+
'instant-articles-wizard',
|
83 |
+
array( 'Instant_Articles_Wizard', 'render' )
|
84 |
+
,'dashicons-facebook'
|
85 |
+
);
|
86 |
+
// Hack to let the URL visible to ajax handlers
|
87 |
+
update_option( 'instant-articles-wizard-url', menu_page_url( 'instant-articles-wizard', false) );
|
88 |
+
}
|
89 |
+
|
90 |
+
public static function get_url() {
|
91 |
+
$url = menu_page_url( 'instant-articles-wizard', false );
|
92 |
+
|
93 |
+
// Needed when calling from ajax
|
94 |
+
if ( ! $url ) {
|
95 |
+
$url = get_option( 'instant-articles-wizard-url' );
|
96 |
+
}
|
97 |
+
|
98 |
+
return $url;
|
99 |
+
}
|
100 |
+
|
101 |
+
|
102 |
+
public static function get_admin_url() {
|
103 |
+
$url = parse_url( admin_url() );
|
104 |
+
return $url['host'];
|
105 |
+
}
|
106 |
+
|
107 |
+
public static function transition() {
|
108 |
+
if ( ! current_user_can( 'manage_options' ) ) {
|
109 |
+
wp_die( esc_html( 'You do not have sufficient permissions to access this page.' ) );
|
110 |
+
}
|
111 |
+
|
112 |
+
$new_state = sanitize_text_field( $_POST[ 'new_state' ] );
|
113 |
+
|
114 |
+
$params = $_POST[ 'params' ];
|
115 |
+
$params = json_decode( stripslashes( $params ), true );
|
116 |
+
foreach ( $params as $key => $param ) {
|
117 |
+
// escape every key
|
118 |
+
$params[ $key ] = sanitize_text_field( $param );
|
119 |
+
}
|
120 |
+
|
121 |
+
try {
|
122 |
+
Instant_Articles_Wizard_State::do_transition( $new_state, $params );
|
123 |
+
} catch ( Exception $e ) {
|
124 |
+
// If something went wrong, simply render the error + the same state.
|
125 |
+
echo '<div class="error settings-error notice is-dismissible"><p><strong>' . esc_html( $e->getMessage() ) . '</strong></p></div>';
|
126 |
+
}
|
127 |
+
|
128 |
+
self::render( true );
|
129 |
+
die();
|
130 |
+
}
|
131 |
+
|
132 |
+
/**
|
133 |
+
* Saves the App ID and App Secret.
|
134 |
+
*
|
135 |
+
* That does not trigger a state transition, as the state transition will
|
136 |
+
* only happen when the user logs in and we grab the access token.
|
137 |
+
*/
|
138 |
+
public static function save_app() {
|
139 |
+
if ( ! current_user_can( 'manage_options' ) ) {
|
140 |
+
wp_die( esc_html( 'You do not have sufficient permissions to access this page.' ) );
|
141 |
+
}
|
142 |
+
|
143 |
+
$current_state = Instant_Articles_Wizard_State::get_current_state();
|
144 |
+
if ( $current_state !== Instant_Articles_Wizard_State::STATE_APP_SETUP ) {
|
145 |
+
die();
|
146 |
+
}
|
147 |
+
|
148 |
+
$app_id = sanitize_text_field( $_POST[ 'app_id' ] );
|
149 |
+
$app_secret = sanitize_text_field( $_POST[ 'app_secret' ] );
|
150 |
+
|
151 |
+
Instant_Articles_Option_FB_App::update_option( array(
|
152 |
+
'app_id' => $app_id,
|
153 |
+
'app_secret' => $app_secret
|
154 |
+
) );
|
155 |
+
|
156 |
+
self::render( true );
|
157 |
+
die();
|
158 |
+
}
|
159 |
+
|
160 |
+
/**
|
161 |
+
* Submits the select page for review
|
162 |
+
*/
|
163 |
+
public static function submit_for_review() {
|
164 |
+
if ( ! current_user_can( 'manage_options' ) ) {
|
165 |
+
wp_die( esc_html( 'You do not have sufficient permissions to access this page.' ) );
|
166 |
+
}
|
167 |
+
|
168 |
+
$current_state = Instant_Articles_Wizard_State::get_current_state();
|
169 |
+
if ( $current_state !== Instant_Articles_Wizard_State::STATE_REVIEW_SUBMISSION ) {
|
170 |
+
die();
|
171 |
+
}
|
172 |
+
|
173 |
+
$fb_app_settings = Instant_Articles_Option_FB_App::get_option_decoded();
|
174 |
+
$fb_page_settings = Instant_Articles_Option_FB_Page::get_option_decoded();
|
175 |
+
|
176 |
+
$client = Client::create(
|
177 |
+
$fb_app_settings[ 'app_id' ],
|
178 |
+
$fb_app_settings[ 'app_secret' ],
|
179 |
+
$fb_page_settings[ 'page_access_token' ],
|
180 |
+
$fb_page_settings[ 'page_id' ]
|
181 |
+
);
|
182 |
+
|
183 |
+
try {
|
184 |
+
// Bulk upload articles for review
|
185 |
+
$articles_for_review = Instant_Articles_Wizard_Review_Submission::getArticlesForReview();
|
186 |
+
foreach ( $articles_for_review as $post ) {
|
187 |
+
Instant_Articles_Publisher::submit_article( $post->ID, $post );
|
188 |
+
}
|
189 |
+
|
190 |
+
// Trigger review submission
|
191 |
+
$client->submitForReview();
|
192 |
+
} catch ( Exception $e ) {
|
193 |
+
// If something went wrong, simply render the error + the same state.
|
194 |
+
echo '<div class="error settings-error notice is-dismissible"><p><strong>' . esc_html( $e->getMessage() ) . '</strong></p></div>';
|
195 |
+
}
|
196 |
+
|
197 |
+
self::render( true );
|
198 |
+
die();
|
199 |
+
}
|
200 |
+
|
201 |
+
/**
|
202 |
+
* Edits the App ID and App Secret within the APP_SETUP state.
|
203 |
+
*/
|
204 |
+
public static function edit_app() {
|
205 |
+
if ( ! current_user_can( 'manage_options' ) ) {
|
206 |
+
wp_die( esc_html( 'You do not have sufficient permissions to access this page.' ) );
|
207 |
+
}
|
208 |
+
|
209 |
+
$current_state = Instant_Articles_Wizard_State::get_current_state();
|
210 |
+
if ( $current_state !== Instant_Articles_Wizard_State::STATE_APP_SETUP ) {
|
211 |
+
die();
|
212 |
+
}
|
213 |
+
|
214 |
+
Instant_Articles_Option_FB_App::delete_option();
|
215 |
+
|
216 |
+
self::render( true );
|
217 |
+
die();
|
218 |
+
}
|
219 |
+
|
220 |
+
public static function is_page_signed_up() {
|
221 |
+
$page_id = sanitize_text_field( $_POST[ 'page_id' ] );
|
222 |
+
|
223 |
+
$fb_helper = new Instant_Articles_Wizard_FB_Helper();
|
224 |
+
$pages = $fb_helper->get_pages();
|
225 |
+
|
226 |
+
if ( isset( $pages[ $page_id ] ) && $pages[ $page_id ][ 'supports_instant_articles' ] ) {
|
227 |
+
die( 'yes' );
|
228 |
+
}
|
229 |
+
else {
|
230 |
+
die( 'no' );
|
231 |
+
}
|
232 |
+
}
|
233 |
+
|
234 |
+
public static function render( $ajax = false ) {
|
235 |
+
if ( ! current_user_can( 'manage_options' ) ) {
|
236 |
+
wp_die( esc_html( 'You do not have sufficient permissions to access this page.' ) );
|
237 |
+
}
|
238 |
+
|
239 |
+
// Read options (they are used on the templates)
|
240 |
+
$current_state = Instant_Articles_Wizard_State::get_current_state();
|
241 |
+
$fb_page_settings = Instant_Articles_Option_FB_Page::get_option_decoded();
|
242 |
+
$fb_app_settings = Instant_Articles_Option_FB_App::get_option_decoded();
|
243 |
+
$fb_helper = new Instant_Articles_Wizard_FB_Helper();
|
244 |
+
$settings_url = self::get_url();
|
245 |
+
|
246 |
+
// Handle redirection from Login flow
|
247 |
+
// ----------------------------------
|
248 |
+
// Only during STATE_APP_SETUP
|
249 |
+
if ( $current_state === Instant_Articles_Wizard_State::STATE_APP_SETUP ) {
|
250 |
+
$user_access_token = $fb_helper->get_fb_access_token();
|
251 |
+
$permissions = $fb_helper->get_fb_permissions( $user_access_token );
|
252 |
+
|
253 |
+
// Trigger transition if all needed permissions are granted
|
254 |
+
if ( $user_access_token && isset( $permissions[ 'pages_manage_instant_articles' ] ) && isset( $permissions[ 'pages_show_list' ] ) ) {
|
255 |
+
Instant_Articles_Wizard_State::do_transition( Instant_Articles_Wizard_State::STATE_PAGE_SELECTION, array(
|
256 |
+
'app_id' => $fb_app_settings[ 'app_id' ],
|
257 |
+
'app_secret' => $fb_app_settings[ 'app_secret' ],
|
258 |
+
'user_access_token' => $user_access_token->getValue()
|
259 |
+
) );
|
260 |
+
// Override step
|
261 |
+
$current_state = Instant_Articles_Wizard_State::get_current_state();
|
262 |
+
}
|
263 |
+
}
|
264 |
+
// ----------------------------------
|
265 |
+
|
266 |
+
|
267 |
+
// Grabs the current configured style
|
268 |
+
// ----------------------------------
|
269 |
+
// Only during STATE_STYLE_SELECTION
|
270 |
+
if ( $current_state === Instant_Articles_Wizard_State::STATE_STYLE_SELECTION ) {
|
271 |
+
$settings_style = Instant_Articles_Option_Styles::get_option_decoded();
|
272 |
+
if ( isset( $settings_style['article_style'] ) && ! empty( $settings_style['article_style'] ) ) {
|
273 |
+
$article_style = $settings_style['article_style'];
|
274 |
+
} else {
|
275 |
+
$article_style = 'default';
|
276 |
+
}
|
277 |
+
}
|
278 |
+
// ----------------------------------
|
279 |
+
|
280 |
+
|
281 |
+
// Check submission status
|
282 |
+
// ----------------------------------
|
283 |
+
// Only during STATE_REVIEW_SUBMISSION
|
284 |
+
if ( $current_state === Instant_Articles_Wizard_State::STATE_REVIEW_SUBMISSION ) {
|
285 |
+
$review_submission_status = Instant_Articles_Wizard_Review_Submission::getReviewSubmissionStatus();
|
286 |
+
if ( $review_submission_status === Instant_Articles_Wizard_Review_Submission::STATUS_NOT_SUBMITTED ) {
|
287 |
+
$articles_for_review = Instant_Articles_Wizard_Review_Submission::getArticlesForReview();
|
288 |
+
}
|
289 |
+
}
|
290 |
+
// ----------------------------------
|
291 |
+
|
292 |
+
include( dirname( __FILE__ ) . '/templates/wizard-template.php' );
|
293 |
+
}
|
294 |
+
|
295 |
+
}
|
wizard/state_machine.txt
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
-----------------------------------------------------------------------------------------------------------------------
|
2 |
+
Facebook Instant Articles for WordPress
|
3 |
+
-----------------------------------------------------------------------------------------------------------------------
|
4 |
+
Setup Wizard State Machine
|
5 |
+
-----------------------------------------------------------------------------------------------------------------------
|
6 |
+
|
7 |
+
|
8 |
+
┌──────────────────────────────────────────────edit_app───────────────────────────────────────────────┐
|
9 |
+
│ │
|
10 |
+
│ ┌──────────────────────────edit_app─────────────────────────────┐ │
|
11 |
+
│ │ │ │
|
12 |
+
│ │ ┌──────────edit_app──────────┐ │ │
|
13 |
+
│ │ │ │ │ │
|
14 |
+
▼ ▼ ▼ │ │ │
|
15 |
+
┏━━━━━━━━━┓ ┏━━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━━━┓
|
16 |
+
┃APP_SETUP┃───set_up_app───▶┃PAGE_SELECTION┃───select_page──▶┃STYLE_SELECTION┃───select_style──▶┃REVIEW_SUBMISSION┃
|
17 |
+
┗━━━━━━━━━┛ ┗━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━┛
|
18 |
+
▲ ▲ ▲ │ ▲ │ │
|
19 |
+
│ │ │ │ │ │ │
|
20 |
+
│ │ └──────────edit_page───────────┘ └──────────edit_style─────────┘ │
|
21 |
+
start_wizard │ │
|
22 |
+
│ └───────────────────────────edit_page────────────────────────────────┘
|
23 |
+
│
|
24 |
+
┏━━━━━━━━┓
|
25 |
+
┃OVERVIEW┃
|
26 |
+
┗━━━━━━━━┛
|
wizard/templates/advanced-template.php
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
|
12 |
+
<div class="instant-articles-card">
|
13 |
+
<div class="instant-articles-card-content">
|
14 |
+
<div class="instant-articles-card-content-box instant-articles-card-content-full">
|
15 |
+
<form method="post" action="options.php">
|
16 |
+
<?php settings_fields( Instant_Articles_Option::PAGE_OPTION_GROUP ); ?>
|
17 |
+
<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>
|
18 |
+
<hr />
|
19 |
+
<?php do_settings_sections( Instant_Articles_Option_Styles::OPTION_KEY ); ?>
|
20 |
+
<hr />
|
21 |
+
<?php do_settings_sections( Instant_Articles_Option_Ads::OPTION_KEY ); ?>
|
22 |
+
<hr />
|
23 |
+
<?php do_settings_sections( Instant_Articles_Option_Analytics::OPTION_KEY ); ?>
|
24 |
+
<hr />
|
25 |
+
<?php do_settings_sections( Instant_Articles_Option_Publishing::OPTION_KEY ); ?>
|
26 |
+
<hr />
|
27 |
+
<?php submit_button( __( 'Save changes' ) ); ?>
|
28 |
+
</form>
|
29 |
+
</div>
|
30 |
+
</div>
|
31 |
+
</div>
|
wizard/templates/all-steps-wizard.php
ADDED
@@ -0,0 +1,288 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
<div class="instant-articles-card">
|
11 |
+
<div class="instant-articles-card-content">
|
12 |
+
<div class="instant-articles-card-content-box instant-articles-card-content-full">
|
13 |
+
<h3>Setting up Instant Articles</h3>
|
14 |
+
<div class="instant-articles-card-steps">
|
15 |
+
<div class="instant-articles-card-step">
|
16 |
+
<img src="/wp-content/plugins/facebook-instant-articles-wp/assets/key@2x.png">
|
17 |
+
<p>Enter Facebook App ID and connect to Facebook to Enable Plugin</p>
|
18 |
+
</div>
|
19 |
+
<div class="instant-articles-card-step">
|
20 |
+
<img src="/wp-content/plugins/facebook-instant-articles-wp/assets/connect@2x.png">
|
21 |
+
<p>Sign up for Instant Articles and select your Facebook Page</p>
|
22 |
+
</div>
|
23 |
+
<div class="instant-articles-card-step">
|
24 |
+
<img src="/wp-content/plugins/facebook-instant-articles-wp/assets/customize@2x.png">
|
25 |
+
<p>Choose how you want your Instant Articles to look using the Style Editor</p>
|
26 |
+
</div>
|
27 |
+
<div class="instant-articles-card-step">
|
28 |
+
<img src="/wp-content/plugins/facebook-instant-articles-wp/assets/check@2x.png">
|
29 |
+
<p>Submit your Instant Articles for review and start publishing</p>
|
30 |
+
</div>
|
31 |
+
</div>
|
32 |
+
<button class="instant-articles-button instant-articles-button-highlight instant-articles-button-centered">
|
33 |
+
<label>Next</label>
|
34 |
+
</button>
|
35 |
+
</div>
|
36 |
+
</div>
|
37 |
+
</div>
|
38 |
+
|
39 |
+
|
40 |
+
<div class="instant-articles-card-bullet-bar">
|
41 |
+
<div class="instant-articles-card-bullet-step instant-articles-card-bullet-step-completed">
|
42 |
+
<div class="instant-articles-card-bullet">✔</div>
|
43 |
+
<div class="instant-articles-card-bullet-path"></div>
|
44 |
+
<p>Enter Facebook App ID and connect to Facebook to Enable Plugin</p>
|
45 |
+
</div>
|
46 |
+
<div class="instant-articles-card-bullet-step instant-articles-card-bullet-step-completed">
|
47 |
+
<div class="instant-articles-card-bullet">✔</div>
|
48 |
+
<div class="instant-articles-card-bullet-path"></div>
|
49 |
+
<p>Sign up for Instant Articles and select your Facebook Page</p>
|
50 |
+
</div>
|
51 |
+
<div class="instant-articles-card-bullet-step instant-articles-card-bullet-step-current">
|
52 |
+
<div class="instant-articles-card-bullet"></div>
|
53 |
+
<div class="instant-articles-card-bullet-path"></div>
|
54 |
+
<p>Choose how you want your Instant Articles to look using the Style Editor</p>
|
55 |
+
</div>
|
56 |
+
<div class="instant-articles-card-bullet-step">
|
57 |
+
<div class="instant-articles-card-bullet"></div>
|
58 |
+
<p>Submit your Instant Articles for review and start publishing</p>
|
59 |
+
</div>
|
60 |
+
</div>
|
61 |
+
|
62 |
+
<div class="instant-articles-card">
|
63 |
+
<div class="instant-articles-card-title">
|
64 |
+
<h3>Authenticate Plugin</h3>
|
65 |
+
<div class="instant-articles-card-title-right">
|
66 |
+
<span class="instant-articles-card-title-checkmark">✔</span>
|
67 |
+
<label class="instant-articles-card-title-label">App connected:</label>
|
68 |
+
<span class="instant-articles-card-title-value">1273677375983360</span>
|
69 |
+
<a class="instant-articles-card-title-edit" href="#"></a>
|
70 |
+
<span class="instant-articles-card-title-step">Step 1 of 2</span>
|
71 |
+
</div>
|
72 |
+
</div>
|
73 |
+
<div class="instant-articles-card-content">
|
74 |
+
<div class="instant-articles-card-content-box instant-articles-card-content-left">
|
75 |
+
<label>Title of this section</label>
|
76 |
+
<p>Yo dawg, you need a Facebook App to enable this plugin. It's for really cool security reasons. If you already know what I'm sayin' and have an App ID and App Secret, <a href="#">go here</a> to grab it. If you don't have any idea what's going on then go ahead and get an App ID already.</p>
|
77 |
+
<button class="instant-articles-button">
|
78 |
+
<label>Get App ID</label>
|
79 |
+
</button>
|
80 |
+
</div>
|
81 |
+
<div class="instant-articles-card-content-box instant-articles-card-content-right">
|
82 |
+
<label class="instant-articles-label">App ID</label>
|
83 |
+
<input class="instant-articles-input-text"type="text"/>
|
84 |
+
<label class="instant-articles-label">App Secret</label>
|
85 |
+
<input class="instant-articles-input-text" type="password"/>
|
86 |
+
<button class="instant-articles-button instant-articles-button-highlight instant-articles-button-disabled">
|
87 |
+
<label>Submit</label>
|
88 |
+
</button>
|
89 |
+
</div>
|
90 |
+
</div>
|
91 |
+
</div>
|
92 |
+
|
93 |
+
<div class="instant-articles-card">
|
94 |
+
<div class="instant-articles-card-title">
|
95 |
+
<h3>Authenticate Plugin</h3>
|
96 |
+
<div class="instant-articles-card-title-right">
|
97 |
+
<span class="instant-articles-card-title-checkmark">✔</span>
|
98 |
+
<label class="instant-articles-card-title-label">App connected:</label>
|
99 |
+
<span class="instant-articles-card-title-value">1273677375983360</span>
|
100 |
+
<a class="instant-articles-card-title-edit" href="#"></a>
|
101 |
+
<span class="instant-articles-card-title-step">Step 2 of 2</span>
|
102 |
+
</div>
|
103 |
+
</div>
|
104 |
+
<div class="instant-articles-card-content">
|
105 |
+
<div class="instant-articles-card-content-box instant-articles-card-content-full">
|
106 |
+
<span class="instant-articles-card-title-checkmark">✔</span>
|
107 |
+
<label class="instant-articles-card-title-label">App connected:</label>
|
108 |
+
<span class="instant-articles-card-title-value">1273677375983360</span>
|
109 |
+
<a class="instant-articles-card-title-edit" href="#"></a>
|
110 |
+
<hr/>
|
111 |
+
<label>Connect your Facebook Account</label>
|
112 |
+
<p>Login with Facebook to finish activating the Instant Articles Plugin.</p>
|
113 |
+
<button class="instant-articles-button">
|
114 |
+
<span class="instant-articles-button-icon-facebook"></span>
|
115 |
+
<label>Login with Facebook</label>
|
116 |
+
</button>
|
117 |
+
</div>
|
118 |
+
</div>
|
119 |
+
</div>
|
120 |
+
|
121 |
+
|
122 |
+
<div class="instant-articles-card instant-articles-card-collapsed">
|
123 |
+
<div class="instant-articles-card-title">
|
124 |
+
<h3>Authenticate Plugin</h3>
|
125 |
+
<div class="instant-articles-card-title-right">
|
126 |
+
<span class="instant-articles-card-title-checkmark">✔</span>
|
127 |
+
<label class="instant-articles-card-title-label">App connected:</label>
|
128 |
+
<span class="instant-articles-card-title-value">1273677375983360</span>
|
129 |
+
<a class="instant-articles-card-title-edit" href="#"></a>
|
130 |
+
<span class="instant-articles-card-title-step">Step 1 of 2</span>
|
131 |
+
</div>
|
132 |
+
</div>
|
133 |
+
<div class="instant-articles-card-content">
|
134 |
+
<div class="instant-articles-card-content-box instant-articles-card-content-left">
|
135 |
+
<label>Title of this section</label>
|
136 |
+
<p>Yo dawg, you need a Facebook App to enable this plugin. It's for really cool security reasons. If you already know what I'm sayin' and have an App ID and App Secret, <a href="#">go here</a> to grab it. If you don't have any idea what's going on then go ahead and get an App ID already.</p>
|
137 |
+
<button class="instant-articles-button">
|
138 |
+
<label>Get App ID</label>
|
139 |
+
</button>
|
140 |
+
</div>
|
141 |
+
<div class="instant-articles-card-content-box instant-articles-card-content-right">
|
142 |
+
<label class="instant-articles-label">App ID</label>
|
143 |
+
<input class="instant-articles-input-text"type="text"/>
|
144 |
+
<label class="instant-articles-label">App Secret</label>
|
145 |
+
<input class="instant-articles-input-text" type="text"/>
|
146 |
+
<button class="instant-articles-button instant-articles-button-highlight instant-articles-button-disabled">
|
147 |
+
<label>Submit</label>
|
148 |
+
</button>
|
149 |
+
</div>
|
150 |
+
</div>
|
151 |
+
</div>
|
152 |
+
|
153 |
+
<div class="instant-articles-card">
|
154 |
+
<div class="instant-articles-card-title">
|
155 |
+
<h3>Select Facebook Page</h3>
|
156 |
+
</div>
|
157 |
+
<div class="instant-articles-card-content">
|
158 |
+
<div class="instant-articles-card-content-box instant-articles-card-content-full">
|
159 |
+
<p>Select the Facebook Page that you want to enable Instant Articles tools. Anyone with an admin role on that Page will also be able to access your Instant Articles tools.</p>
|
160 |
+
<ul>
|
161 |
+
<li>
|
162 |
+
<input type="radio" name="page-id"/>
|
163 |
+
<img class="instant-articles-page-img" src=""/>
|
164 |
+
<label>The Salty Shop</label>
|
165 |
+
</li>
|
166 |
+
<li>
|
167 |
+
<input type="radio" name="page-id"/>
|
168 |
+
<img class="instant-articles-page-img" src=""/>
|
169 |
+
<label>The Sweet Shop</label>
|
170 |
+
</li>
|
171 |
+
<li>
|
172 |
+
<input type="radio" name="page-id"/>
|
173 |
+
<img class="instant-articles-page-img" src=""/>
|
174 |
+
<label>Free Market street</label>
|
175 |
+
</li>
|
176 |
+
<li>
|
177 |
+
<input type="radio" name="page-id"/>
|
178 |
+
<img class="instant-articles-page-img" src="https://z-1-scontent-atl3-1.xx.fbcdn.net/v/t1.0-1/p160x160/943890_1119857341366295_1442705195804509998_n.jpg?oh=6e5a53e35daeb43b5f31f3d309dce08f&oe=582BADB5"/>
|
179 |
+
<label>The mall</label>
|
180 |
+
</li>
|
181 |
+
<li>
|
182 |
+
<input type="radio" name="page-id"/>
|
183 |
+
<img class="instant-articles-page-img" src="https://z-1-scontent-atl3-1.xx.fbcdn.net/v/t1.0-1/p160x160/12400471_1021643444544180_2130580769920124493_n.png?oh=3018153ee4db69a4737cd96197691d7f&oe=582BE583"/>
|
184 |
+
<label>Hilo CrossFit</label>
|
185 |
+
</li>
|
186 |
+
<li>
|
187 |
+
<input type="radio" name="page-id"/>
|
188 |
+
<img class="instant-articles-page-img" src=""/>
|
189 |
+
<label>Street Dancer</label>
|
190 |
+
</li>
|
191 |
+
</ul>
|
192 |
+
<button class="instant-articles-button instant-articles-button-highlight">
|
193 |
+
<label>Select</label>
|
194 |
+
</button>
|
195 |
+
</div>
|
196 |
+
</div>
|
197 |
+
</div>
|
198 |
+
|
199 |
+
<div class="instant-articles-card instant-articles-card-collapsed">
|
200 |
+
<div class="instant-articles-card-title">
|
201 |
+
<h3>Facebook Page Enabled</h3>
|
202 |
+
<div class="instant-articles-card-title-right">
|
203 |
+
<a href="" class="instant-articles-card-title-link">Hilo CrossFit</a>
|
204 |
+
<img class="instant-articles-page-img" src=""/>
|
205 |
+
<a class="instant-articles-card-title-edit" href="#"></a>
|
206 |
+
</div>
|
207 |
+
</div>
|
208 |
+
<div class="instant-articles-card-content">
|
209 |
+
<div class="instant-articles-card-content-box instant-articles-card-content-full">
|
210 |
+
<p>Select the Facebook Page that you want to enable Instant Articles tools. Anyone with an admin role on that Page will also be able to access your Instant Articles tools.</p>
|
211 |
+
<ul>
|
212 |
+
<li>
|
213 |
+
<input type="radio" name="page-id"/>
|
214 |
+
<img class="instant-articles-page-img" src=""/>
|
215 |
+
<label>The Salty Shop</label>
|
216 |
+
</li>
|
217 |
+
<li>
|
218 |
+
<input type="radio" name="page-id"/>
|
219 |
+
<img class="instant-articles-page-img" src=""/>
|
220 |
+
<label>The Sweet Shop</label>
|
221 |
+
</li>
|
222 |
+
<li>
|
223 |
+
<input type="radio" name="page-id"/>
|
224 |
+
<img class="instant-articles-page-img" src=""/>
|
225 |
+
<label>Free Market street</label>
|
226 |
+
</li>
|
227 |
+
<li>
|
228 |
+
<input type="radio" name="page-id"/>
|
229 |
+
<img class="instant-articles-page-img" src="https://z-1-scontent-atl3-1.xx.fbcdn.net/v/t1.0-1/p160x160/943890_1119857341366295_1442705195804509998_n.jpg?oh=6e5a53e35daeb43b5f31f3d309dce08f&oe=582BADB5"/>
|
230 |
+
<label>The mall</label>
|
231 |
+
</li>
|
232 |
+
<li class="instant-articles-radio-selected">
|
233 |
+
<input type="radio" name="page-id" checked="checked"/>
|
234 |
+
<img class="instant-articles-page-img" src="https://z-1-scontent-atl3-1.xx.fbcdn.net/v/t1.0-1/p160x160/12400471_1021643444544180_2130580769920124493_n.png?oh=3018153ee4db69a4737cd96197691d7f&oe=582BE583"/>
|
235 |
+
<label>Hilo CrossFit</label>
|
236 |
+
</li>
|
237 |
+
<li>
|
238 |
+
<input type="radio" name="page-id"/>
|
239 |
+
<img class="instant-articles-page-img" src=""/>
|
240 |
+
<label>Street Dancer</label>
|
241 |
+
</li>
|
242 |
+
</ul>
|
243 |
+
<button class="instant-articles-button instant-articles-button-highlight">
|
244 |
+
<label>Select</label>
|
245 |
+
</button>
|
246 |
+
</div>
|
247 |
+
</div>
|
248 |
+
</div>
|
249 |
+
|
250 |
+
<div class="instant-articles-card">
|
251 |
+
<div class="instant-articles-card-title">
|
252 |
+
<h3>Style & Preview Articles</h3>
|
253 |
+
</div>
|
254 |
+
<div class="instant-articles-card-content">
|
255 |
+
<div class="instant-articles-card-content-box instant-articles-card-content-full">
|
256 |
+
<p>Lorem ipsum dolor sit amet, consectetuer adipscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis notoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim.</p>
|
257 |
+
<button class="instant-articles-button">
|
258 |
+
<label>Choose style</label>
|
259 |
+
</button>
|
260 |
+
</div>
|
261 |
+
</div>
|
262 |
+
</div>
|
263 |
+
|
264 |
+
<div class="instant-articles-card instant-articles-card-collapsed">
|
265 |
+
<div class="instant-articles-card-title">
|
266 |
+
<h3>Style Selected</h3>
|
267 |
+
<div class="instant-articles-card-title-right">
|
268 |
+
<a href="" class="instant-articles-card-title-link">Sweet Shop Style 01</a>
|
269 |
+
<a class="instant-articles-card-title-edit" href="#"></a>
|
270 |
+
</div>
|
271 |
+
</div>
|
272 |
+
</div>
|
273 |
+
|
274 |
+
<div class="instant-articles-card">
|
275 |
+
<div class="instant-articles-card-title">
|
276 |
+
<h3>Submit for Review</h3>
|
277 |
+
</div>
|
278 |
+
<div class="instant-articles-card-content">
|
279 |
+
<div class="instant-articles-card-content-box instant-articles-card-content-full">
|
280 |
+
<p>Lorem ipsum dolor sit amet, consectetuer adipscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis notoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim.</p>
|
281 |
+
<button class="instant-articles-button instant-articles-button-highlight">
|
282 |
+
<label>Submit for Review</label>
|
283 |
+
</button>
|
284 |
+
</div>
|
285 |
+
</div>
|
286 |
+
</div>
|
287 |
+
|
288 |
+
<a class="instant-articles-advanced-settings" href="#">► Advanced Settings</a>
|
wizard/templates/app-setup-template.php
ADDED
@@ -0,0 +1,115 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
<?php if ( empty( $fb_app_settings['app_id'] ) || empty( $fb_app_settings['app_secret'] ) ) : ?>
|
11 |
+
|
12 |
+
<!-- Step 1: grab your App ID and App Secret -->
|
13 |
+
<div class="instant-articles-card">
|
14 |
+
<div class="instant-articles-card-title">
|
15 |
+
<h3>Log In with Your Developers App and Facebook Account</h3>
|
16 |
+
<div class="instant-articles-card-title-right">
|
17 |
+
<span class="instant-articles-card-title-step">Step 1 of 2</span>
|
18 |
+
</div>
|
19 |
+
</div>
|
20 |
+
<div class="instant-articles-card-content">
|
21 |
+
<div class="instant-articles-card-content-box instant-articles-card-content-left">
|
22 |
+
<label>First, log in with your Facebook Developers App</label>
|
23 |
+
|
24 |
+
<p>You'll need to log in with your Facebook Developers App ID to connect your plugin to the Facebook Page you'll use to publish your Instant Articles.</p>
|
25 |
+
|
26 |
+
<p><strong>Already have an App ID and Secret?</strong> Just enter them to the right.</p>
|
27 |
+
|
28 |
+
<p><strong>Need to create one?</strong></p>
|
29 |
+
|
30 |
+
<p>Click on the 'Get App ID' button below to begin the process of getting your App ID and Secret. This will open the App set up page in a new tab. Then, follow these steps:</p>
|
31 |
+
|
32 |
+
<ol>
|
33 |
+
<li>Click on the green '+ Add a New App' button in the upper right corner of the page.</li>
|
34 |
+
<li>If you are prompted to select a platform, select 'basic setup.' If you don't see this prompt, don't worry; just go directly to Step 3.</li>
|
35 |
+
<li>Create an app name (it can be whatever you want it to be), input your email and select 'Apps for Pages' in the 'Category' dropdown menu. Click 'Create App ID' when you’re ready.</li>
|
36 |
+
<li>Click on 'Settings' in the left nav bar.</li>
|
37 |
+
<li>Click '+Add Platform' at the bottom of the page and select 'Website.'</li>
|
38 |
+
<li>Under both the 'App Domains' in the main section and 'Site URL' in the 'Website' section, enter this domain: <b><?php echo esc_url( self::get_admin_url() ); ?></b></li>
|
39 |
+
<li>Click 'Save Changes' in the lower right corner.</li>
|
40 |
+
<li>Select 'Show' to see your App Secret. Copy your App ID and Secret and enter them to the right.</li>
|
41 |
+
</ol>
|
42 |
+
|
43 |
+
<p><strong>Need more help?</strong> <a href="https://developers.facebook.com/docs/instant-articles/wordpress-quickstart#appid" target="_blank">See detailed instructions on setting up your App ID in our documentation</a>.</p>
|
44 |
+
|
45 |
+
<a class="instant-articles-button" href="https://developers.facebook.com/apps" target="_blank">
|
46 |
+
Get App ID
|
47 |
+
</a>
|
48 |
+
</div>
|
49 |
+
<div class="instant-articles-card-content-box instant-articles-card-content-right">
|
50 |
+
<label class="instant-articles-label">App ID</label>
|
51 |
+
<input name="app_id" class="instant-articles-input-text" type="text"/>
|
52 |
+
<label class="instant-articles-label">App Secret</label>
|
53 |
+
<input name="app_secret" class="instant-articles-input-text" type="password"/>
|
54 |
+
<button id="instant-articles-wizard-save-app" class="instant-articles-button instant-articles-button-highlight instant-articles-button-disabled">
|
55 |
+
<label>Log In</label>
|
56 |
+
</button>
|
57 |
+
</div>
|
58 |
+
<br clear="both" />
|
59 |
+
</div>
|
60 |
+
</div>
|
61 |
+
|
62 |
+
<?php else: ?>
|
63 |
+
|
64 |
+
<!-- Step 2: log in with Facebook -->
|
65 |
+
<div class="instant-articles-card">
|
66 |
+
<div class="instant-articles-card-title">
|
67 |
+
<h3>Log In with Your Developers App and Facebook Account</h3>
|
68 |
+
<div class="instant-articles-card-title-right">
|
69 |
+
<span class="instant-articles-card-title-step">Step 2 of 2</span>
|
70 |
+
</div>
|
71 |
+
</div>
|
72 |
+
<div class="instant-articles-card-content">
|
73 |
+
<div class="instant-articles-card-content-box instant-articles-card-content-full">
|
74 |
+
<span class="instant-articles-card-title-checkmark">✔</span>
|
75 |
+
<label class="instant-articles-card-title-label">App connected:</label>
|
76 |
+
<span class="instant-articles-card-title-value"><?php echo esc_html( $fb_app_settings[ 'app_id' ] ); ?></span>
|
77 |
+
<a id="instant-articles-wizard-edit-app" class="instant-articles-card-title-edit" href="#"></a>
|
78 |
+
<hr/>
|
79 |
+
<label>Next, log into your Facebook account</label>
|
80 |
+
<p>Log in with Facebook to finish connecting the Instant Articles Plugin to your account.</p>
|
81 |
+
<?php
|
82 |
+
if (
|
83 |
+
$user_access_token &&
|
84 |
+
(
|
85 |
+
! isset( $permissions['pages_manage_instant_articles'] ) ||
|
86 |
+
! isset( $permissions['pages_show_list'] )
|
87 |
+
)
|
88 |
+
) :
|
89 |
+
?>
|
90 |
+
<p>In order to finish the activation, you need to grant all the requested permissions:</p>
|
91 |
+
<ul>
|
92 |
+
<?php if ( ! isset( $permissions['pages_show_list'] ) ) : ?>
|
93 |
+
<li>
|
94 |
+
<b>Show a list of the Pages you manage</b>: allows the plugin to show the list of your
|
95 |
+
pages for you to select one.
|
96 |
+
</li>
|
97 |
+
<?php endif; ?>
|
98 |
+
<?php if ( ! isset( $permissions['pages_manage_instant_articles'] ) ) : ?>
|
99 |
+
<li>
|
100 |
+
<b>Manage Instant Articles for your Pages</b>: allows us to publish
|
101 |
+
Instant Articles to your selected page.
|
102 |
+
</li>
|
103 |
+
<?php endif; ?>
|
104 |
+
</ul>
|
105 |
+
<?php endif;?>
|
106 |
+
|
107 |
+
<a href="<?php echo esc_attr( $fb_helper->get_login_url() ); ?>" class="instant-articles-button">
|
108 |
+
<span class="instant-articles-button-icon-facebook"></span>
|
109 |
+
<label>Login with Facebook</label>
|
110 |
+
</a>
|
111 |
+
</div>
|
112 |
+
<div clear="both" />
|
113 |
+
</div>
|
114 |
+
</div>
|
115 |
+
<?php endif; ?>
|
wizard/templates/overview-template.php
ADDED
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
<div class="instant-articles-card">
|
11 |
+
<div class="instant-articles-card-content">
|
12 |
+
<div class="instant-articles-card-content-box instant-articles-card-content-full">
|
13 |
+
<h3>Get Started with the Instant Articles WordPress Plugin</h3>
|
14 |
+
<div class="instant-articles-card-steps">
|
15 |
+
<div class="instant-articles-card-step">
|
16 |
+
<img src="<?php echo esc_url( plugin_dir_url( __FILE__ ) ); ?>../../assets/key@2x.png">
|
17 |
+
<h4>Set Up and Log In</h4>
|
18 |
+
<p>If you don't have one already, set up your Facebook Developers App. Then log in to connect your plugin.</p>
|
19 |
+
</div>
|
20 |
+
<div class="instant-articles-card-step">
|
21 |
+
<img src="<?php echo esc_url( plugin_dir_url( __FILE__ ) ); ?>../../assets/connect@2x.png">
|
22 |
+
<h4>Select Your Page</h4>
|
23 |
+
<p>Select the Page you'll use to publish your Instant Articles.</p>
|
24 |
+
</div>
|
25 |
+
<div class="instant-articles-card-step">
|
26 |
+
<img src="<?php echo esc_url( plugin_dir_url( __FILE__ ) ); ?>../../assets/customize@2x.png">
|
27 |
+
<h4>Customize Your Style</h4>
|
28 |
+
<p>Use our Style Editor to make your Instant Articles look just how you want them to.</p>
|
29 |
+
</div>
|
30 |
+
<div class="instant-articles-card-step">
|
31 |
+
<img src="<?php echo esc_url( plugin_dir_url( __FILE__ ) ); ?>../../assets/check@2x.png">
|
32 |
+
<h4>Submit for Review</h4>
|
33 |
+
<p>Submit your Instant Articles for review and start publishing.</p>
|
34 |
+
</div>
|
35 |
+
</div>
|
36 |
+
<button
|
37 |
+
class="instant-articles-button instant-articles-button-highlight instant-articles-button-centered instant-articles-wizard-transition"
|
38 |
+
data-new-state="STATE_APP_SETUP">
|
39 |
+
<label>Get Started</label>
|
40 |
+
</button>
|
41 |
+
</div>
|
42 |
+
</div>
|
43 |
+
</div>
|
wizard/templates/page-selection-template.php
ADDED
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
<div class="instant-articles-card instant-articles-card-collapsed">
|
11 |
+
<div class="instant-articles-card-title">
|
12 |
+
<h3>Logged In</h3>
|
13 |
+
<div class="instant-articles-card-title-right">
|
14 |
+
<span class="instant-articles-card-title-checkmark">✔</span>
|
15 |
+
<label class="instant-articles-card-title-label">App connected:</label>
|
16 |
+
<span class="instant-articles-card-title-value"><?php echo esc_html( $fb_app_settings[ 'app_id' ] ); ?></span>
|
17 |
+
<a class="instant-articles-wizard-transition instant-articles-card-title-edit" href="#" data-new-state="<?php echo esc_attr( Instant_Articles_Wizard_State::STATE_APP_SETUP ); ?>"></a>
|
18 |
+
</div>
|
19 |
+
</div>
|
20 |
+
</div>
|
21 |
+
|
22 |
+
<div class="instant-articles-card">
|
23 |
+
<div class="instant-articles-card-title">
|
24 |
+
<h3>Which Page Would You Like to Use for Instant Articles?</h3>
|
25 |
+
</div>
|
26 |
+
<div class="instant-articles-card-content">
|
27 |
+
<div class="instant-articles-card-content-box instant-articles-card-content-full">
|
28 |
+
<p>
|
29 |
+
Select the Page you'd like to use to access the Instant Articles tools.
|
30 |
+
Anyone with an admin role will also be able to use the tools.
|
31 |
+
Don't have a Page yet?
|
32 |
+
<strong><a href="https://www.facebook.com/pages/create" target="_blank">Create one</a>.</strong>
|
33 |
+
</p>
|
34 |
+
<ul class="instant-articles-wizard-page-selection">
|
35 |
+
<?php foreach ( $fb_helper->get_pages() as $page ) { ?>
|
36 |
+
<li>
|
37 |
+
<input
|
38 |
+
type="radio"
|
39 |
+
name="page_id"
|
40 |
+
value="<?php echo esc_attr( $page[ 'page_id' ] ) ?>"
|
41 |
+
data-signed-up="<?php echo $page[ 'supports_instant_articles' ] ? 'yes' : 'no'; ?>"
|
42 |
+
/>
|
43 |
+
<img class="instant-articles-page-img" src="<?php echo esc_attr( $page[ 'page_picture' ] ) ?>"/>
|
44 |
+
<label>
|
45 |
+
<?php echo esc_html( $page[ 'page_name' ] ) ?>
|
46 |
+
<?php if ( $page[ 'supports_instant_articles' ] ) : ?>
|
47 |
+
<span class="page-enabled">✔ Enabled</span>
|
48 |
+
<?php else : ?>
|
49 |
+
<span class="page-not-enabled">
|
50 |
+
This page has not been signed up yet.
|
51 |
+
<a href="https://www.facebook.com/instant_articles/signup?redirect_uri=<?php echo urlencode( $settings_url ) ?>&page_id=<?php echo urlencode( $page[ 'page_id' ] ) ?>">Sign Up</a>.
|
52 |
+
</span>
|
53 |
+
<?php endif; ?>
|
54 |
+
</label>
|
55 |
+
</li>
|
56 |
+
<?php } ?>
|
57 |
+
</ul>
|
58 |
+
<button id="instant-articles-wizard-select-page" class="instant-articles-button instant-articles-button-highlight instant-articles-button-disabled">
|
59 |
+
<label>Select</label>
|
60 |
+
</button>
|
61 |
+
</div>
|
62 |
+
</div>
|
63 |
+
</div>
|
wizard/templates/review-submission-template.php
ADDED
@@ -0,0 +1,156 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
<div class="instant-articles-card instant-articles-card-collapsed">
|
11 |
+
<div class="instant-articles-card-title">
|
12 |
+
<h3>Logged In</h3>
|
13 |
+
<div class="instant-articles-card-title-right">
|
14 |
+
<span class="instant-articles-card-title-checkmark">✔</span>
|
15 |
+
<label class="instant-articles-card-title-label">App connected:</label>
|
16 |
+
<span class="instant-articles-card-title-value"><?php echo esc_html( $fb_app_settings[ 'app_id' ] ); ?></span>
|
17 |
+
<a class="instant-articles-wizard-transition instant-articles-card-title-edit" href="#" data-new-state="<?php echo esc_attr( Instant_Articles_Wizard_State::STATE_APP_SETUP ); ?>"></a>
|
18 |
+
</div>
|
19 |
+
</div>
|
20 |
+
</div>
|
21 |
+
|
22 |
+
<div class="instant-articles-card instant-articles-card-collapsed">
|
23 |
+
<div class="instant-articles-card-title">
|
24 |
+
<h3>Facebook Page Enabled</h3>
|
25 |
+
<div class="instant-articles-card-title-right">
|
26 |
+
<a href="" class="instant-articles-card-title-link"><?php echo esc_html( $fb_page_settings[ 'page_name' ] ) ?></a>
|
27 |
+
<?php if ( $fb_page_settings[ 'page_picture' ] ) : ?>
|
28 |
+
<img class="instant-articles-page-img" src="<?php echo esc_attr( $fb_page_settings[ 'page_picture' ] ) ?>"/>
|
29 |
+
<?php endif; ?>
|
30 |
+
<a class="instant-articles-wizard-transition instant-articles-card-title-edit" href="#" data-new-state="<?php echo esc_attr( Instant_Articles_Wizard_State::STATE_PAGE_SELECTION ); ?>"></a>
|
31 |
+
</div>
|
32 |
+
</div>
|
33 |
+
</div>
|
34 |
+
|
35 |
+
<div class="instant-articles-card instant-articles-card-collapsed">
|
36 |
+
<div class="instant-articles-card-title">
|
37 |
+
<h3>Style Customized</h3>
|
38 |
+
<div class="instant-articles-card-title-right">
|
39 |
+
<a class="instant-articles-wizard-transition instant-articles-card-title-edit" href="#" data-new-state="<?php echo esc_attr( Instant_Articles_Wizard_State::STATE_STYLE_SELECTION ); ?>"></a>
|
40 |
+
</div>
|
41 |
+
</div>
|
42 |
+
</div>
|
43 |
+
|
44 |
+
<?php
|
45 |
+
switch ( $review_submission_status ) :
|
46 |
+
|
47 |
+
case Instant_Articles_Wizard_Review_Submission::STATUS_NOT_SUBMITTED : ?>
|
48 |
+
|
49 |
+
<?php if ( count($articles_for_review) >= Instant_Articles_Wizard_Review_Submission::MIN_ARTICLES ) : ?>
|
50 |
+
<div class="instant-articles-card">
|
51 |
+
<div class="instant-articles-card-title">
|
52 |
+
<h3>Submit for Review</h3>
|
53 |
+
</div>
|
54 |
+
<div class="instant-articles-card-content">
|
55 |
+
<div class="instant-articles-card-content-box instant-articles-card-content-full">
|
56 |
+
<p>
|
57 |
+
The Instant Articles team will review a sample batch of your Instant Articles before you can begin to publish.
|
58 |
+
Click the 'Submit for Review" button below to send the last <?php echo esc_html( Instant_Articles_Wizard_Review_Submission::MIN_ARTICLES ); ?>
|
59 |
+
articles you've published to the team for review.
|
60 |
+
</p>
|
61 |
+
<p>
|
62 |
+
It will take us 2 business days to complete the review.
|
63 |
+
Once we've had a chance to take a look, we'll let you know if you're ready to start publishing or if you need to make some updates.
|
64 |
+
</p>
|
65 |
+
<button id="instant-articles-wizard-submit-for-review" class="instant-articles-button instant-articles-button-highlight">
|
66 |
+
<label>Submit for Review</label>
|
67 |
+
</button>
|
68 |
+
</div>
|
69 |
+
</div>
|
70 |
+
</div>
|
71 |
+
<?php else: ?>
|
72 |
+
<div class="instant-articles-card">
|
73 |
+
<div class="instant-articles-card-title">
|
74 |
+
<h3>Create More Articles to Submit for Review</h3>
|
75 |
+
</div>
|
76 |
+
<div class="instant-articles-card-content">
|
77 |
+
<div class="instant-articles-card-content-box instant-articles-card-content-full">
|
78 |
+
<p>
|
79 |
+
In order to begin publishing Instant Articles, our team needs to review a sample batch of <?php echo esc_html( Instant_Articles_Wizard_Review_Submission::MIN_ARTICLES ); ?>
|
80 |
+
of your Instant Articles. It looks like you don't have <?php echo esc_html( Instant_Articles_Wizard_Review_Submission::MIN_ARTICLES ); ?> articles available yet.
|
81 |
+
</p>
|
82 |
+
<p>
|
83 |
+
Once you've created the additional articles and have <?php echo esc_html( Instant_Articles_Wizard_Review_Submission::MIN_ARTICLES ); ?> available to send,
|
84 |
+
please return to this page and click the 'Submit for Review" button below.
|
85 |
+
</p>
|
86 |
+
<button id="instant-articles-wizard-submit-for-review" class="instant-articles-button-disabled instant-articles-button instant-articles-button-highlight">
|
87 |
+
<label>Submit for Review</label>
|
88 |
+
</button>
|
89 |
+
</div>
|
90 |
+
</div>
|
91 |
+
</div>
|
92 |
+
<?php endif; ?>
|
93 |
+
|
94 |
+
|
95 |
+
<?php break; ?>
|
96 |
+
|
97 |
+
<?php case Instant_Articles_Wizard_Review_Submission::STATUS_APPROVED : ?>
|
98 |
+
<div class="instant-articles-card instant-articles-card-success">
|
99 |
+
<div class="instant-articles-card-title">
|
100 |
+
<h3>Review Complete: Begin Publishing Your Instant Articles</h3>
|
101 |
+
</div>
|
102 |
+
<div class="instant-articles-card-content">
|
103 |
+
<div class="instant-articles-card-content-box instant-articles-card-content-full">
|
104 |
+
<p>
|
105 |
+
We reviewed some of your articles and they look great.
|
106 |
+
You're now ready to begin publishing your Instant Articles to Facebook and sharing them with your audience.
|
107 |
+
</p>
|
108 |
+
<p>
|
109 |
+
Next, set up monetization and analytics in Advanced Settings. Or explore the
|
110 |
+
<a href="<?php echo esc_url( 'https://www.facebook.com/' . $fb_page_settings['page_id'] . '/publishing_tools/?section=INSTANT_ARTICLES_SETTINGS' ); ?>" target="_blank">Instant Articles publishing tools</a>
|
111 |
+
through your selected Facebook Page.
|
112 |
+
</p>
|
113 |
+
</div>
|
114 |
+
</div>
|
115 |
+
</div>
|
116 |
+
<?php break; ?>
|
117 |
+
|
118 |
+
<?php case Instant_Articles_Wizard_Review_Submission::STATUS_REJECTED : ?>
|
119 |
+
<div class="instant-articles-card instant-articles-card-fail">
|
120 |
+
<div class="instant-articles-card-title">
|
121 |
+
<h3>Review Complete: Updates Needed</h3>
|
122 |
+
</div>
|
123 |
+
<div class="instant-articles-card-content">
|
124 |
+
<div class="instant-articles-card-content-box instant-articles-card-content-full">
|
125 |
+
<p>
|
126 |
+
We reviewed some of your articles and found a few things that need to be updated.
|
127 |
+
</p>
|
128 |
+
<p>
|
129 |
+
Please go to your selected
|
130 |
+
<a href="<?php echo esc_url( 'https://www.facebook.com/' . $fb_page_settings['page_id'] . '/publishing_tools/?section=INSTANT_ARTICLES_SETTINGS#Step-2' ); ?>" target="_blank">Facebook Page's Publishing Tools</a>
|
131 |
+
to get more specifics on the issues identified. Once these have been cleared up in WordPress, you'll be ready to begin publishing your Instant Articles.
|
132 |
+
</p>
|
133 |
+
</div>
|
134 |
+
</div>
|
135 |
+
</div>
|
136 |
+
<?php break; ?>
|
137 |
+
|
138 |
+
<?php case Instant_Articles_Wizard_Review_Submission::STATUS_PENDING : ?>
|
139 |
+
<div class="instant-articles-card">
|
140 |
+
<div class="instant-articles-card-title">
|
141 |
+
<h3>Review Articles Submitted</h3>
|
142 |
+
</div>
|
143 |
+
<div class="instant-articles-card-content">
|
144 |
+
<div class="instant-articles-card-content-box instant-articles-card-content-full">
|
145 |
+
<p>
|
146 |
+
Your articles have been submitted for review.
|
147 |
+
</p>
|
148 |
+
<p>
|
149 |
+
It will take us 2 business days to complete the review. Check back here to see the status of your review submission.
|
150 |
+
</p>
|
151 |
+
</div>
|
152 |
+
</div>
|
153 |
+
</div>
|
154 |
+
<?php break; ?>
|
155 |
+
|
156 |
+
<?php endswitch; ?>
|
wizard/templates/style-selection-template.php
ADDED
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
<div class="instant-articles-card instant-articles-card-collapsed">
|
11 |
+
<div class="instant-articles-card-title">
|
12 |
+
<h3>Logged In</h3>
|
13 |
+
<div class="instant-articles-card-title-right">
|
14 |
+
<span class="instant-articles-card-title-checkmark">✔</span>
|
15 |
+
<label class="instant-articles-card-title-label">App connected:</label>
|
16 |
+
<span class="instant-articles-card-title-value"><?php echo esc_html( $fb_app_settings[ 'app_id' ] ); ?></span>
|
17 |
+
<a class="instant-articles-wizard-transition instant-articles-card-title-edit" href="#" data-new-state="<?php echo esc_attr( Instant_Articles_Wizard_State::STATE_APP_SETUP ); ?>"></a>
|
18 |
+
</div>
|
19 |
+
</div>
|
20 |
+
</div>
|
21 |
+
|
22 |
+
<div class="instant-articles-card instant-articles-card-collapsed">
|
23 |
+
<div class="instant-articles-card-title">
|
24 |
+
<h3>Page Selected</h3>
|
25 |
+
<div class="instant-articles-card-title-right">
|
26 |
+
<a href="" class="instant-articles-card-title-link"><?php echo esc_html( $fb_page_settings[ 'page_name' ] ) ?></a>
|
27 |
+
<?php if ( $fb_page_settings[ 'page_picture' ] ) : ?>
|
28 |
+
<img class="instant-articles-page-img" src="<?php echo esc_url( $fb_page_settings[ 'page_picture' ] ) ?>"/>
|
29 |
+
<?php endif; ?>
|
30 |
+
<a class="instant-articles-wizard-transition instant-articles-card-title-edit" href="#" data-new-state="<?php echo esc_attr( Instant_Articles_Wizard_State::STATE_PAGE_SELECTION ); ?>"></a>
|
31 |
+
</div>
|
32 |
+
</div>
|
33 |
+
</div>
|
34 |
+
|
35 |
+
<div class="instant-articles-card">
|
36 |
+
<div class="instant-articles-card-title">
|
37 |
+
<h3>Customize Your Style with Style Editor</h3>
|
38 |
+
</div>
|
39 |
+
<div class="instant-articles-card-content">
|
40 |
+
<div class="instant-articles-card-content-box instant-articles-card-content-full">
|
41 |
+
<p>
|
42 |
+
Customize the look and feel of your articles with one or more unique styles.
|
43 |
+
Try to make your Instant Articles look as much like your mobile web articles as possible
|
44 |
+
and be sure to upload your publication or blog's logo.
|
45 |
+
<a href="https://developers.facebook.com/docs/instant-articles/guides/design" target="_blank">Learn more in our design guidelines</a>.
|
46 |
+
</p>
|
47 |
+
<p>
|
48 |
+
Want to preview your style? Download Facebook Pages Manager on your
|
49 |
+
<a href="https://itunes.apple.com/us/app/facebook-pages-manager/id514643583?mt=8" target="_blank">iPhone</a>
|
50 |
+
or
|
51 |
+
<a href="https://play.google.com/store/apps/details?id=com.facebook.pages.app" target="_blank">Android</a>
|
52 |
+
phone.
|
53 |
+
</p>
|
54 |
+
<a
|
55 |
+
id="instant-articles-wizard-customize-style"
|
56 |
+
href="<?php echo esc_url( 'https://www.facebook.com/' . $fb_page_settings['page_id'] . '/publishing_tools/?section=INSTANT_ARTICLES_SETTINGS&initial_data[style]=' . $article_style ); ?>"
|
57 |
+
class="instant-articles-button instant-articles-button-highlight"
|
58 |
+
target="_blank">
|
59 |
+
Customize
|
60 |
+
</a>
|
61 |
+
<button id="instant-articles-wizard-customize-style-next" class="instant-articles-button instant-articles-wizard-transition" data-new-state="<?php echo esc_attr( Instant_Articles_Wizard_State::STATE_REVIEW_SUBMISSION ); ?>">
|
62 |
+
<label>Next</label>
|
63 |
+
</button>
|
64 |
+
</div>
|
65 |
+
</div>
|
66 |
+
</div>
|
wizard/templates/wizard-template.php
ADDED
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
<?php if ( ! $ajax ) : ?>
|
11 |
+
<h1>Facebook Instant Articles Settings</h1>
|
12 |
+
<div id="instant_articles_wizard_messages"><?php settings_errors(); ?></div>
|
13 |
+
<div id="instant_articles_wizard">
|
14 |
+
<?php endif; ?>
|
15 |
+
|
16 |
+
<?php if ( $current_state !== Instant_Articles_Wizard_State::STATE_OVERVIEW ): ?>
|
17 |
+
<?php
|
18 |
+
// Calculate classes for the timeline
|
19 |
+
$state_css_classes = array();
|
20 |
+
foreach ( Instant_Articles_Wizard_State::$timeline as $state => $order ) {
|
21 |
+
switch ( Instant_Articles_Wizard_State::get_timeline_position( $state ) ) {
|
22 |
+
case Instant_Articles_Wizard_State::TIMELINE_PAST:
|
23 |
+
$state_css_classes[ $state ] = 'instant-articles-card-bullet-step-completed';
|
24 |
+
break;
|
25 |
+
case Instant_Articles_Wizard_State::TIMELINE_CURRENT:
|
26 |
+
$state_css_classes[ $state ] = 'instant-articles-card-bullet-step-current';
|
27 |
+
break;
|
28 |
+
case Instant_Articles_Wizard_State::TIMELINE_FUTURE:
|
29 |
+
$state_css_classes[ $state ] = '';
|
30 |
+
break;
|
31 |
+
}
|
32 |
+
}
|
33 |
+
?>
|
34 |
+
|
35 |
+
<div class="instant-articles-card-bullet-bar">
|
36 |
+
<div class="instant-articles-card-bullet-step <?php echo esc_attr( $state_css_classes[ Instant_Articles_Wizard_State::STATE_APP_SETUP ] ); ?>">
|
37 |
+
<div class="instant-articles-card-bullet"></div>
|
38 |
+
<div class="instant-articles-card-bullet-path"></div>
|
39 |
+
<?php if ( Instant_Articles_Wizard_State::get_timeline_position( Instant_Articles_Wizard_State::STATE_APP_SETUP ) === Instant_Articles_Wizard_State::TIMELINE_PAST ) : ?>
|
40 |
+
<h4>Logged In</h4>
|
41 |
+
<?php else : ?>
|
42 |
+
<h4>Set Up and Log In</h4>
|
43 |
+
<?php endif; ?>
|
44 |
+
<p>If you don't have one already, set up your Facebook Developers App. This will allow you to log in and connect your plugin.</p>
|
45 |
+
</div>
|
46 |
+
<div class="instant-articles-card-bullet-step <?php echo esc_attr( $state_css_classes[ Instant_Articles_Wizard_State::STATE_PAGE_SELECTION ] ); ?>">
|
47 |
+
<div class="instant-articles-card-bullet"></div>
|
48 |
+
<div class="instant-articles-card-bullet-path"></div>
|
49 |
+
<?php if ( Instant_Articles_Wizard_State::get_timeline_position( Instant_Articles_Wizard_State::STATE_PAGE_SELECTION ) === Instant_Articles_Wizard_State::TIMELINE_PAST ) : ?>
|
50 |
+
<h4>Page Selected</h4>
|
51 |
+
<?php else : ?>
|
52 |
+
<h4>Select Your Page</h4>
|
53 |
+
<?php endif; ?>
|
54 |
+
<p>Select the Page you'll use to publish your Instant Articles.</p>
|
55 |
+
</div>
|
56 |
+
<div class="instant-articles-card-bullet-step <?php echo esc_attr( $state_css_classes[ Instant_Articles_Wizard_State::STATE_STYLE_SELECTION ] ); ?>">
|
57 |
+
<div class="instant-articles-card-bullet"></div>
|
58 |
+
<div class="instant-articles-card-bullet-path"></div>
|
59 |
+
<?php if ( Instant_Articles_Wizard_State::get_timeline_position( Instant_Articles_Wizard_State::STATE_STYLE_SELECTION ) === Instant_Articles_Wizard_State::TIMELINE_PAST ) : ?>
|
60 |
+
<h4>Style Customized</h4>
|
61 |
+
<?php else : ?>
|
62 |
+
<h4>Customize Your Style</h4>
|
63 |
+
<?php endif; ?>
|
64 |
+
<p>Use our Style Editor to make your Instant Articles look just how you want them to.</p>
|
65 |
+
</div>
|
66 |
+
<div class="instant-articles-card-bullet-step <?php echo esc_attr( $state_css_classes[ Instant_Articles_Wizard_State::STATE_REVIEW_SUBMISSION ] ); ?>">
|
67 |
+
<div class="instant-articles-card-bullet"></div>
|
68 |
+
<?php if ( Instant_Articles_Wizard_State::get_timeline_position( Instant_Articles_Wizard_State::STATE_REVIEW_SUBMISSION ) === Instant_Articles_Wizard_State::TIMELINE_PAST ) : ?>
|
69 |
+
<h4>Review Complete</h4>
|
70 |
+
<?php else : ?>
|
71 |
+
<h4>Submit for Review</h4>
|
72 |
+
<?php endif; ?>
|
73 |
+
<p>Submit your Instant Articles for review and start publishing.</p>
|
74 |
+
</div>
|
75 |
+
</div>
|
76 |
+
|
77 |
+
<?php endif; ?>
|
78 |
+
|
79 |
+
<?php
|
80 |
+
switch ( $current_state ) {
|
81 |
+
case Instant_Articles_Wizard_State::STATE_OVERVIEW:
|
82 |
+
include( dirname( __FILE__ ) . '/overview-template.php' );
|
83 |
+
break;
|
84 |
+
case Instant_Articles_Wizard_State::STATE_APP_SETUP:
|
85 |
+
include( dirname( __FILE__ ) . '/app-setup-template.php' );
|
86 |
+
break;
|
87 |
+
case Instant_Articles_Wizard_State::STATE_PAGE_SELECTION:
|
88 |
+
include( dirname( __FILE__ ) . '/page-selection-template.php' );
|
89 |
+
break;
|
90 |
+
case Instant_Articles_Wizard_State::STATE_STYLE_SELECTION:
|
91 |
+
include( dirname( __FILE__ ) . '/style-selection-template.php' );
|
92 |
+
break;
|
93 |
+
case Instant_Articles_Wizard_State::STATE_REVIEW_SUBMISSION:
|
94 |
+
include( dirname( __FILE__ ) . '/review-submission-template.php' );
|
95 |
+
break;
|
96 |
+
}
|
97 |
+
?>
|
98 |
+
|
99 |
+
<?php if ( ! $ajax ) : ?>
|
100 |
+
</div>
|
101 |
+
<?php if ( ! empty( get_settings_errors() ) ) : ?>
|
102 |
+
<a class="instant-articles-advanced-settings instant-articles-wizard-toggle" href="#">▼ Advanced Settings</a>
|
103 |
+
<div class="instant-articles-wizard-advanced-settings-box" style="display: block;">
|
104 |
+
<?php include( dirname( __FILE__ ) . '/advanced-template.php' ); ?>
|
105 |
+
</div>
|
106 |
+
<?php else: ?>
|
107 |
+
<a class="instant-articles-advanced-settings instant-articles-wizard-toggle" href="#">► Advanced Settings</a>
|
108 |
+
<div class="instant-articles-wizard-advanced-settings-box" style="display: none;">
|
109 |
+
<?php include( dirname( __FILE__ ) . '/advanced-template.php' ); ?>
|
110 |
+
</div>
|
111 |
+
<?php endif; ?>
|
112 |
+
<?php endif; ?>
|