Version Description
- Added: Make revisions accessible in the admin - now you can restore older versions of your ads.txt or view how it's changed over time (props @adamsilverstein, @helen)
- Added: Show a notice on the edit screen if an ads.txt file exists on the server (props @kkoppenhaver, @helen, @tomjn, @adamsilverstein)
-
Added: Add a custom
edit_ads_txt
capability for granular assignment, which is assigned to administrators by default (props @ethanclevenger91, @adamsilverstein) -
Added: Enable filtering of the output using
ads_txt_content
(props @ethanclevenger91) - Changed: Updated documentation, automation, and coding standards (props @jeffpaul, @adamsilverstein, @helen, @mmcachran)
- Fixed: Early escaping (props @tomjn)
- Fixed: PHPCS issues and added PHPCS scanning (props @adamsilverstein)
Download this release
Release Info
Developer | helen |
Plugin | Ads.txt Manager |
Version | 1.2.0 |
Comparing to | |
See all releases |
Code changes from version 1.0 to 1.2.0
- ads-txt.php +58 -5
- css/admin.css +3 -0
- inc/admin.php +273 -42
- inc/post-type.php +10 -4
- inc/save.php +39 -37
- js/admin.js +36 -5
- readme.txt +26 -4
ads-txt.php
CHANGED
@@ -2,17 +2,23 @@
|
|
2 |
/**
|
3 |
* Plugin Name: Ads.txt Manager
|
4 |
* Description: Create, manage, and validate your Ads.txt from within WordPress, just like any other content asset. Requires PHP 5.3+ and WordPress 4.9+.
|
5 |
-
* Version: 1.0
|
6 |
* Author: 10up
|
7 |
-
* Author URI:
|
8 |
* License: GPLv2 or later
|
9 |
* Text Domain: ads-txt
|
|
|
|
|
10 |
*/
|
11 |
|
12 |
if ( ! defined( 'ABSPATH' ) ) {
|
13 |
exit; // Exit if accessed directly.
|
14 |
}
|
15 |
|
|
|
|
|
|
|
|
|
16 |
require_once __DIR__ . '/inc/post-type.php';
|
17 |
require_once __DIR__ . '/inc/admin.php';
|
18 |
require_once __DIR__ . '/inc/save.php';
|
@@ -23,17 +29,64 @@ require_once __DIR__ . '/inc/save.php';
|
|
23 |
* @return void
|
24 |
*/
|
25 |
function tenup_display_ads_txt() {
|
26 |
-
$request = esc_url_raw( $_SERVER['REQUEST_URI'] );
|
27 |
if ( '/ads.txt' === $request ) {
|
28 |
-
$post_id = get_option(
|
29 |
|
30 |
// Will fall through if no option found, likely to a 404.
|
31 |
if ( ! empty( $post_id ) ) {
|
32 |
$post = get_post( $post_id );
|
33 |
header( 'Content-Type: text/plain' );
|
34 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
die();
|
36 |
}
|
37 |
}
|
38 |
}
|
39 |
add_action( 'init', 'tenup_display_ads_txt' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
/**
|
3 |
* Plugin Name: Ads.txt Manager
|
4 |
* Description: Create, manage, and validate your Ads.txt from within WordPress, just like any other content asset. Requires PHP 5.3+ and WordPress 4.9+.
|
5 |
+
* Version: 1.2.0
|
6 |
* Author: 10up
|
7 |
+
* Author URI: https://10up.com
|
8 |
* License: GPLv2 or later
|
9 |
* Text Domain: ads-txt
|
10 |
+
*
|
11 |
+
* @package Ads_Txt_Manager
|
12 |
*/
|
13 |
|
14 |
if ( ! defined( 'ABSPATH' ) ) {
|
15 |
exit; // Exit if accessed directly.
|
16 |
}
|
17 |
|
18 |
+
define( 'ADS_TXT_MANAGER_VERSION', '1.2.0' );
|
19 |
+
define( 'ADS_TXT_MANAGE_CAPABILITY', 'edit_ads_txt' );
|
20 |
+
define( 'ADS_TXT_MANAGER_POST_OPTION', 'adstxt_post' );
|
21 |
+
|
22 |
require_once __DIR__ . '/inc/post-type.php';
|
23 |
require_once __DIR__ . '/inc/admin.php';
|
24 |
require_once __DIR__ . '/inc/save.php';
|
29 |
* @return void
|
30 |
*/
|
31 |
function tenup_display_ads_txt() {
|
32 |
+
$request = isset( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : false;
|
33 |
if ( '/ads.txt' === $request ) {
|
34 |
+
$post_id = get_option( ADS_TXT_MANAGER_POST_OPTION );
|
35 |
|
36 |
// Will fall through if no option found, likely to a 404.
|
37 |
if ( ! empty( $post_id ) ) {
|
38 |
$post = get_post( $post_id );
|
39 |
header( 'Content-Type: text/plain' );
|
40 |
+
$adstxt = $post->post_content;
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Filter the ads.txt content.
|
44 |
+
*
|
45 |
+
* @since 1.2.0
|
46 |
+
*
|
47 |
+
* @param type $adstxt The existing ads.txt content.
|
48 |
+
*/
|
49 |
+
echo esc_html( apply_filters( 'ads_txt_content', $adstxt ) );
|
50 |
die();
|
51 |
}
|
52 |
}
|
53 |
}
|
54 |
add_action( 'init', 'tenup_display_ads_txt' );
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Add custom capabilities.
|
58 |
+
*
|
59 |
+
* @return void
|
60 |
+
*/
|
61 |
+
function add_adstxt_capabilities() {
|
62 |
+
$role = get_role( 'administrator' );
|
63 |
+
if ( ! $role->has_cap( ADS_TXT_MANAGE_CAPABILITY ) ) {
|
64 |
+
$role->add_cap( ADS_TXT_MANAGE_CAPABILITY );
|
65 |
+
}
|
66 |
+
}
|
67 |
+
add_action( 'admin_init', 'add_adstxt_capabilities' );
|
68 |
+
register_activation_hook( __FILE__, 'add_adstxt_capabilities' );
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Remove custom capabilities when deactivating the plugin.
|
72 |
+
*
|
73 |
+
* @return void
|
74 |
+
*/
|
75 |
+
function remove_adstxt_capabilities() {
|
76 |
+
$role = get_role( 'administrator' );
|
77 |
+
$role->remove_cap( ADS_TXT_MANAGE_CAPABILITY );
|
78 |
+
}
|
79 |
+
register_deactivation_hook( __FILE__, 'remove_adstxt_capabilities' );
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Add a query var to detect when ads.txt has been saved.
|
83 |
+
*
|
84 |
+
* @param array $qvars Array of query vars.
|
85 |
+
*
|
86 |
+
* @return array Array of query vars.
|
87 |
+
*/
|
88 |
+
function tenup_ads_txt_add_query_vars( $qvars ) {
|
89 |
+
$qvars[] = 'ads_txt_saved';
|
90 |
+
return $qvars;
|
91 |
+
}
|
92 |
+
add_filter( 'query_vars', 'tenup_ads_txt_add_query_vars' );
|
css/admin.css
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
.adstxt-revision-count {
|
2 |
+
font-weight: bold;
|
3 |
+
}
|
inc/admin.php
CHANGED
@@ -1,4 +1,9 @@
|
|
1 |
<?php
|
|
|
|
|
|
|
|
|
|
|
2 |
|
3 |
namespace AdsTxt;
|
4 |
|
@@ -14,13 +19,24 @@ function admin_enqueue_scripts( $hook ) {
|
|
14 |
return;
|
15 |
}
|
16 |
|
17 |
-
wp_enqueue_script(
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
wp_enqueue_style( 'code-editor' );
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
|
20 |
$strings = array(
|
21 |
-
'
|
22 |
-
'
|
23 |
-
'unknown_error' => __( 'An unknown error occurred.', 'ads-txt' ),
|
24 |
);
|
25 |
|
26 |
wp_localize_script( 'adstxt', 'adstxt', $strings );
|
@@ -35,7 +51,7 @@ add_action( 'admin_enqueue_scripts', __NAMESPACE__ . '\admin_enqueue_scripts' );
|
|
35 |
* @return void
|
36 |
*/
|
37 |
function admin_head_css() {
|
38 |
-
?>
|
39 |
<style>
|
40 |
.CodeMirror {
|
41 |
width: 100%;
|
@@ -43,19 +59,96 @@ function admin_head_css() {
|
|
43 |
height: calc( 100vh - 295px );
|
44 |
border: 1px solid #ddd;
|
45 |
box-sizing: border-box;
|
46 |
-
}
|
47 |
</style>
|
48 |
-
<?php
|
49 |
}
|
50 |
add_action( 'admin_head-settings_page_adstxt-settings', __NAMESPACE__ . '\admin_head_css' );
|
51 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
/**
|
53 |
* Add admin menu page.
|
54 |
*
|
55 |
* @return void
|
56 |
*/
|
57 |
function admin_menu() {
|
58 |
-
add_options_page(
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
}
|
60 |
add_action( 'admin_menu', __NAMESPACE__ . '\admin_menu' );
|
61 |
|
@@ -65,40 +158,113 @@ add_action( 'admin_menu', __NAMESPACE__ . '\admin_menu' );
|
|
65 |
* @return void
|
66 |
*/
|
67 |
function settings_screen() {
|
68 |
-
$post_id
|
69 |
-
$post
|
70 |
-
$content
|
|
|
|
|
|
|
71 |
|
72 |
if ( $post_id ) {
|
73 |
$post = get_post( $post_id );
|
74 |
-
$content = isset( $post->post_content ) ? $post->post_content : '';
|
75 |
-
$errors = get_post_meta( $post->ID, 'adstxt_errors', true );
|
76 |
}
|
77 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
<div class="wrap">
|
79 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
80 |
<div class="notice notice-error adstxt-notice">
|
81 |
-
<p><strong><?php echo
|
82 |
<ul>
|
83 |
<?php
|
84 |
foreach ( $errors as $error ) {
|
85 |
-
echo '<li
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
}
|
87 |
?>
|
88 |
</ul>
|
89 |
</div>
|
90 |
-
<?php endif; ?>
|
91 |
|
92 |
-
<h2><?php echo
|
93 |
|
94 |
<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" class="adstxt-settings-form">
|
95 |
-
<input type="hidden" name="post_id" value="<?php echo ( $
|
96 |
<input type="hidden" name="action" value="adstxt-save" />
|
97 |
<?php wp_nonce_field( 'adstxt_save' ); ?>
|
98 |
|
99 |
-
<label class="screen-reader-text" for="adstxt_content"><?php echo
|
100 |
<textarea class="widefat code" rows="25" name="adstxt" id="adstxt_content"><?php echo esc_textarea( $content ); ?></textarea>
|
101 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
102 |
<div id="adstxt-notification-area"></div>
|
103 |
|
104 |
<p class="submit">
|
@@ -109,19 +275,27 @@ function settings_screen() {
|
|
109 |
</form>
|
110 |
|
111 |
<script type="text/template" id="tmpl-adstext-notice">
|
112 |
-
<# if ( ! _.isUndefined( data.saved ) ) { #>
|
113 |
-
<div class="notice notice-success adstxt-notice adstxt-saved">
|
114 |
-
<p>{{ data.saved.saved_message }}</p>
|
115 |
-
</div>
|
116 |
-
<# } #>
|
117 |
-
|
118 |
<# if ( ! _.isUndefined( data.errors ) ) { #>
|
119 |
<div class="notice notice-error adstxt-notice adstxt-errors">
|
120 |
<p><strong>{{ data.errors.error_message }}</strong></p>
|
121 |
<# if ( ! _.isUndefined( data.errors.errors ) ) { #>
|
122 |
<ul class="adstxt-errors-items">
|
123 |
<# _.each( data.errors.errors, function( error ) { #>
|
124 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
125 |
<# } ); #>
|
126 |
</ul>
|
127 |
<# } #>
|
@@ -131,7 +305,7 @@ function settings_screen() {
|
|
131 |
<p class="adstxt-ays">
|
132 |
<input id="adstxt-ays-checkbox" name="adstxt_ays" type="checkbox" value="y" />
|
133 |
<label for="adstxt-ays-checkbox">
|
134 |
-
<?php
|
135 |
</label>
|
136 |
</p>
|
137 |
<# } #>
|
@@ -140,29 +314,86 @@ function settings_screen() {
|
|
140 |
</script>
|
141 |
</div>
|
142 |
|
143 |
-
<?php
|
144 |
}
|
145 |
|
146 |
/**
|
147 |
-
* Take an error array and
|
148 |
*
|
149 |
* @param array $error {
|
150 |
* Array of error message components.
|
151 |
*
|
152 |
-
* @type string $type Type of error. Typically 'warning' or 'error'.
|
153 |
* @type int $line Line number of the error.
|
154 |
-
* @type string $
|
|
|
155 |
* }
|
156 |
*
|
157 |
-
* @return string
|
158 |
*/
|
159 |
-
function
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
165 |
);
|
166 |
|
167 |
-
return $
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
168 |
}
|
|
1 |
<?php
|
2 |
+
/**
|
3 |
+
* Admin functionality for Ads.txt.
|
4 |
+
*
|
5 |
+
* @package Ads_Txt_Manager
|
6 |
+
*/
|
7 |
|
8 |
namespace AdsTxt;
|
9 |
|
19 |
return;
|
20 |
}
|
21 |
|
22 |
+
wp_enqueue_script(
|
23 |
+
'adstxt',
|
24 |
+
esc_url( plugins_url( '/js/admin.js', dirname( __FILE__ ) ) ),
|
25 |
+
array( 'jquery', 'wp-backbone', 'wp-codemirror' ),
|
26 |
+
ADS_TXT_MANAGER_VERSION,
|
27 |
+
true
|
28 |
+
);
|
29 |
wp_enqueue_style( 'code-editor' );
|
30 |
+
wp_enqueue_style(
|
31 |
+
'adstxt',
|
32 |
+
esc_url( plugins_url( '/css/admin.css', dirname( __FILE__ ) ) ),
|
33 |
+
array(),
|
34 |
+
ADS_TXT_MANAGER_VERSION
|
35 |
+
);
|
36 |
|
37 |
$strings = array(
|
38 |
+
'error_message' => esc_html__( 'Your Ads.txt contains the following issues:', 'ads-txt' ),
|
39 |
+
'unknown_error' => esc_html__( 'An unknown error occurred.', 'ads-txt' ),
|
|
|
40 |
);
|
41 |
|
42 |
wp_localize_script( 'adstxt', 'adstxt', $strings );
|
51 |
* @return void
|
52 |
*/
|
53 |
function admin_head_css() {
|
54 |
+
?>
|
55 |
<style>
|
56 |
.CodeMirror {
|
57 |
width: 100%;
|
59 |
height: calc( 100vh - 295px );
|
60 |
border: 1px solid #ddd;
|
61 |
box-sizing: border-box;
|
62 |
+
}
|
63 |
</style>
|
64 |
+
<?php
|
65 |
}
|
66 |
add_action( 'admin_head-settings_page_adstxt-settings', __NAMESPACE__ . '\admin_head_css' );
|
67 |
|
68 |
+
/**
|
69 |
+
* Appends a query argument to the edit url to make sure it is redirected to
|
70 |
+
* the ads.txt screen.
|
71 |
+
*
|
72 |
+
* @since 1.2.0
|
73 |
+
*
|
74 |
+
* @param string $url Edit url.
|
75 |
+
* @return string Edit url.
|
76 |
+
*/
|
77 |
+
function ads_txt_adjust_revisions_return_to_editor_link( $url ) {
|
78 |
+
global $pagenow;
|
79 |
+
|
80 |
+
if ( 'revision.php' !== $pagenow || ! isset( $_REQUEST['adstxt'] ) ) { // @codingStandardsIgnoreLine Nonce not required.
|
81 |
+
return $url;
|
82 |
+
}
|
83 |
+
|
84 |
+
return admin_url( 'options-general.php?page=adstxt-settings' );
|
85 |
+
}
|
86 |
+
add_filter( 'get_edit_post_link', __NAMESPACE__ . '\ads_txt_adjust_revisions_return_to_editor_link' );
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Modifies revisions data to preserve adstxt argument used in determining
|
90 |
+
* where to redirect user returning to editor.
|
91 |
+
*
|
92 |
+
* @since 1.9.0
|
93 |
+
*
|
94 |
+
* @param array $revisions_data The bootstrapped data for the revisions screen.
|
95 |
+
* @return array Modified bootstrapped data for the revisions screen.
|
96 |
+
*/
|
97 |
+
function adstxt_revisions_restore( $revisions_data ) {
|
98 |
+
if ( isset( $_REQUEST['adstxt'] ) ) { // @codingStandardsIgnoreLine Nonce not required.
|
99 |
+
$revisions_data['restoreUrl'] = add_query_arg(
|
100 |
+
'adstxt',
|
101 |
+
1,
|
102 |
+
$revisions_data['restoreUrl']
|
103 |
+
);
|
104 |
+
}
|
105 |
+
|
106 |
+
return $revisions_data;
|
107 |
+
}
|
108 |
+
add_filter( 'wp_prepare_revision_for_js', __NAMESPACE__ . '\adstxt_revisions_restore' );
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Hide the revisions title with CSS, since WordPress always shows the title
|
112 |
+
* field even if unchanged, and the title is not relevant for ads.txt.
|
113 |
+
*/
|
114 |
+
function admin_header_revisions_styles() {
|
115 |
+
$current_screen = get_current_screen();
|
116 |
+
|
117 |
+
if ( ! $current_screen || 'revision' !== $current_screen->id ) {
|
118 |
+
return;
|
119 |
+
}
|
120 |
+
|
121 |
+
if ( ! isset( $_REQUEST['adstxt'] ) ) { // @codingStandardsIgnoreLine Nonce not required.
|
122 |
+
return;
|
123 |
+
}
|
124 |
+
|
125 |
+
?>
|
126 |
+
<style>
|
127 |
+
.revisions-diff .diff h3 {
|
128 |
+
display: none;
|
129 |
+
}
|
130 |
+
.revisions-diff .diff table.diff:first-of-type {
|
131 |
+
display: none;
|
132 |
+
}
|
133 |
+
</style>
|
134 |
+
<?php
|
135 |
+
|
136 |
+
}
|
137 |
+
add_action( 'admin_head', __NAMESPACE__ . '\admin_header_revisions_styles' );
|
138 |
+
|
139 |
/**
|
140 |
* Add admin menu page.
|
141 |
*
|
142 |
* @return void
|
143 |
*/
|
144 |
function admin_menu() {
|
145 |
+
add_options_page(
|
146 |
+
esc_html__( 'Ads.txt', 'ads-txt' ),
|
147 |
+
esc_html__( 'Ads.txt', 'ads-txt' ),
|
148 |
+
ADS_TXT_MANAGE_CAPABILITY,
|
149 |
+
'adstxt-settings',
|
150 |
+
__NAMESPACE__ . '\settings_screen'
|
151 |
+
);
|
152 |
}
|
153 |
add_action( 'admin_menu', __NAMESPACE__ . '\admin_menu' );
|
154 |
|
158 |
* @return void
|
159 |
*/
|
160 |
function settings_screen() {
|
161 |
+
$post_id = get_option( ADS_TXT_MANAGER_POST_OPTION );
|
162 |
+
$post = false;
|
163 |
+
$content = false;
|
164 |
+
$errors = [];
|
165 |
+
$revision_count = 0;
|
166 |
+
$last_revision_id = false;
|
167 |
|
168 |
if ( $post_id ) {
|
169 |
$post = get_post( $post_id );
|
|
|
|
|
170 |
}
|
171 |
+
|
172 |
+
if ( is_a( $post, 'WP_Post' ) ) {
|
173 |
+
$content = $post->post_content;
|
174 |
+
$revisions = wp_get_post_revisions( $post->ID );
|
175 |
+
$revision_count = count( $revisions );
|
176 |
+
$last_revision = array_shift( $revisions );
|
177 |
+
$last_revision_id = $last_revision ? $last_revision->ID : false;
|
178 |
+
$errors = get_post_meta( $post->ID, 'adstxt_errors', true );
|
179 |
+
$revisions_link = $last_revision_id ? admin_url( 'revision.php?adstxt=1&revision=' . $last_revision_id ) : false;
|
180 |
+
|
181 |
+
} else {
|
182 |
+
|
183 |
+
// Create an initial post so the second save creates a comparable revision.
|
184 |
+
$postarr = array(
|
185 |
+
'post_title' => 'Ads.txt',
|
186 |
+
'post_content' => '',
|
187 |
+
'post_type' => 'adstxt',
|
188 |
+
'post_status' => 'publish',
|
189 |
+
);
|
190 |
+
|
191 |
+
$post_id = wp_insert_post( $postarr );
|
192 |
+
if ( $post_id ) {
|
193 |
+
update_option( ADS_TXT_MANAGER_POST_OPTION, $post_id );
|
194 |
+
}
|
195 |
+
}
|
196 |
+
?>
|
197 |
<div class="wrap">
|
198 |
+
<div class="notice notice-error adstxt-notice existing-adstxt" style="display: none;">
|
199 |
+
<p><strong><?php echo esc_html_e( 'Existing Ads.txt file found', 'ads-txt' ); ?></strong></p>
|
200 |
+
<p><?php echo esc_html_e( 'An ads.txt file on the server will take precedence over any content entered here. You will need to rename or remove the existing ads.txt file before you will be able to see any changes you make on this screen.', 'ads-txt' ); ?></p>
|
201 |
+
|
202 |
+
<p><?php echo esc_html_e( 'Removed the existing file but are still seeing this warning?', 'ads-txt' ); ?> <a class="ads-txt-rerun-check" href="#"><?php echo esc_html_e( 'Re-run the check now', 'ads-txt' ); ?></a> <span class="spinner" style="float:none;margin:-2px 5px 0"></span></p>
|
203 |
+
</div>
|
204 |
+
|
205 |
+
<?php if ( ! empty( $errors ) ) : ?>
|
206 |
<div class="notice notice-error adstxt-notice">
|
207 |
+
<p><strong><?php echo esc_html__( 'Your Ads.txt contains the following issues:', 'ads-txt' ); ?></strong></p>
|
208 |
<ul>
|
209 |
<?php
|
210 |
foreach ( $errors as $error ) {
|
211 |
+
echo '<li>';
|
212 |
+
|
213 |
+
// Errors were originally stored as an array.
|
214 |
+
// This old style only needs to be accounted for here at runtime display.
|
215 |
+
if ( isset( $error['message'] ) ) {
|
216 |
+
$message = sprintf(
|
217 |
+
/* translators: Error message output. 1: Line number, 2: Error message */
|
218 |
+
__( 'Line %1$s: %2$s', 'ads-txt' ),
|
219 |
+
$error['line'],
|
220 |
+
$error['message']
|
221 |
+
);
|
222 |
+
|
223 |
+
echo esc_html( $message );
|
224 |
+
} else {
|
225 |
+
display_formatted_error( $error ); // WPCS: XSS ok.
|
226 |
+
}
|
227 |
+
|
228 |
+
echo '</li>';
|
229 |
}
|
230 |
?>
|
231 |
</ul>
|
232 |
</div>
|
233 |
+
<?php endif; ?>
|
234 |
|
235 |
+
<h2><?php echo esc_html__( 'Manage Ads.txt', 'ads-txt' ); ?></h2>
|
236 |
|
237 |
<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" class="adstxt-settings-form">
|
238 |
+
<input type="hidden" name="post_id" value="<?php echo esc_attr( $post_id ) ? esc_attr( $post_id ) : ''; ?>" />
|
239 |
<input type="hidden" name="action" value="adstxt-save" />
|
240 |
<?php wp_nonce_field( 'adstxt_save' ); ?>
|
241 |
|
242 |
+
<label class="screen-reader-text" for="adstxt_content"><?php echo esc_html__( 'Ads.txt content', 'ads-txt' ); ?></label>
|
243 |
<textarea class="widefat code" rows="25" name="adstxt" id="adstxt_content"><?php echo esc_textarea( $content ); ?></textarea>
|
244 |
+
<?php
|
245 |
+
if ( $revision_count > 1 ) {
|
246 |
+
?>
|
247 |
+
<div class="misc-pub-section misc-pub-revisions">
|
248 |
+
<?php
|
249 |
+
echo wp_kses_post(
|
250 |
+
sprintf(
|
251 |
+
/* translators: Post revisions heading. 1: The number of available revisions */
|
252 |
+
__( 'Revisions: <span class="adstxt-revision-count">%s</span>', 'ads-txt' ),
|
253 |
+
number_format_i18n( $revision_count )
|
254 |
+
)
|
255 |
+
);
|
256 |
+
?>
|
257 |
+
<a class="hide-if-no-js" href="<?php echo esc_url( $revisions_link ); ?>">
|
258 |
+
<span aria-hidden="true">
|
259 |
+
<?php echo esc_html( __( 'Browse', 'ads-txt' ) ); ?>
|
260 |
+
</span> <span class="screen-reader-text">
|
261 |
+
<?php echo esc_html( __( 'Browse revisions', 'ads-txt' ) ); ?>
|
262 |
+
</span>
|
263 |
+
</a>
|
264 |
+
</div>
|
265 |
+
<?php
|
266 |
+
}
|
267 |
+
?>
|
268 |
<div id="adstxt-notification-area"></div>
|
269 |
|
270 |
<p class="submit">
|
275 |
</form>
|
276 |
|
277 |
<script type="text/template" id="tmpl-adstext-notice">
|
|
|
|
|
|
|
|
|
|
|
|
|
278 |
<# if ( ! _.isUndefined( data.errors ) ) { #>
|
279 |
<div class="notice notice-error adstxt-notice adstxt-errors">
|
280 |
<p><strong>{{ data.errors.error_message }}</strong></p>
|
281 |
<# if ( ! _.isUndefined( data.errors.errors ) ) { #>
|
282 |
<ul class="adstxt-errors-items">
|
283 |
<# _.each( data.errors.errors, function( error ) { #>
|
284 |
+
<?php foreach ( array_keys( get_error_messages() ) as $error_type ) : ?>
|
285 |
+
<# if ( "<?php echo esc_html( $error_type ); ?>" === error.type ) { #>
|
286 |
+
<li>
|
287 |
+
<?php
|
288 |
+
display_formatted_error(
|
289 |
+
array(
|
290 |
+
'line' => '{{error.line}}',
|
291 |
+
'type' => $error_type,
|
292 |
+
'value' => '{{error.value}}',
|
293 |
+
)
|
294 |
+
);
|
295 |
+
?>
|
296 |
+
</li>
|
297 |
+
<# } #>
|
298 |
+
<?php endforeach; ?>
|
299 |
<# } ); #>
|
300 |
</ul>
|
301 |
<# } #>
|
305 |
<p class="adstxt-ays">
|
306 |
<input id="adstxt-ays-checkbox" name="adstxt_ays" type="checkbox" value="y" />
|
307 |
<label for="adstxt-ays-checkbox">
|
308 |
+
<?php esc_html_e( 'Update anyway, even though it may adversely affect your ads?', 'ads-txt' ); ?>
|
309 |
</label>
|
310 |
</p>
|
311 |
<# } #>
|
314 |
</script>
|
315 |
</div>
|
316 |
|
317 |
+
<?php
|
318 |
}
|
319 |
|
320 |
/**
|
321 |
+
* Take an error array and output it as a message.
|
322 |
*
|
323 |
* @param array $error {
|
324 |
* Array of error message components.
|
325 |
*
|
|
|
326 |
* @type int $line Line number of the error.
|
327 |
+
* @type string $type Type of error.
|
328 |
+
* @type string $value Optional. Value in question.
|
329 |
* }
|
330 |
*
|
331 |
+
* @return string|void
|
332 |
*/
|
333 |
+
function display_formatted_error( $error ) {
|
334 |
+
$messages = get_error_messages();
|
335 |
+
|
336 |
+
if ( ! isset( $messages[ $error['type'] ] ) ) {
|
337 |
+
return __( 'Unknown error', 'adstxt' );
|
338 |
+
}
|
339 |
+
|
340 |
+
if ( ! isset( $error['value'] ) ) {
|
341 |
+
$error['value'] = '';
|
342 |
+
}
|
343 |
+
|
344 |
+
$message = sprintf( esc_html( $messages[ $error['type'] ] ), '<code>' . esc_html( $error['value'] ) . '</code>' );
|
345 |
+
|
346 |
+
printf(
|
347 |
+
/* translators: Error message output. 1: Line number, 2: Error message */
|
348 |
+
esc_html__( 'Line %1$s: %2$s', 'ads-txt' ),
|
349 |
+
esc_html( $error['line'] ),
|
350 |
+
wp_kses_post( $message )
|
351 |
+
);
|
352 |
+
}
|
353 |
+
|
354 |
+
/**
|
355 |
+
* Get all non-generic error messages, translated and with placeholders intact.
|
356 |
+
*
|
357 |
+
* @return array Associative array of error messages.
|
358 |
+
*/
|
359 |
+
function get_error_messages() {
|
360 |
+
$messages = array(
|
361 |
+
'invalid_variable' => __( 'Unrecognized variable' ),
|
362 |
+
'invalid_record' => __( 'Invalid record' ),
|
363 |
+
'invalid_account_type' => __( 'Third field should be RESELLER or DIRECT' ),
|
364 |
+
/* translators: %s: Subdomain */
|
365 |
+
'invalid_subdomain' => __( '%s does not appear to be a valid subdomain' ),
|
366 |
+
/* translators: %s: Exchange domain */
|
367 |
+
'invalid_exchange' => __( '%s does not appear to be a valid exchange domain' ),
|
368 |
+
/* translators: %s: Alphanumeric TAG-ID */
|
369 |
+
'invalid_tagid' => __( '%s does not appear to be a valid TAG-ID' ),
|
370 |
);
|
371 |
|
372 |
+
return $messages;
|
373 |
+
}
|
374 |
+
|
375 |
+
/**
|
376 |
+
* Maybe display admin notices on the Ads.txt settings page.
|
377 |
+
*
|
378 |
+
* @return void
|
379 |
+
*/
|
380 |
+
function admin_notices() {
|
381 |
+
if ( 'settings_page_adstxt-settings' !== get_current_screen()->base ) {
|
382 |
+
return;
|
383 |
+
}
|
384 |
+
|
385 |
+
if ( isset( $_GET['ads_txt_saved'] ) ) : // @codingStandardsIgnoreLine Nonce not required.
|
386 |
+
?>
|
387 |
+
<div class="notice notice-success adstxt-notice adstxt-saved">
|
388 |
+
<p><?php echo esc_html__( 'Ads.txt saved', 'ads-txt' ); ?></p>
|
389 |
+
</div>
|
390 |
+
<?php
|
391 |
+
elseif ( isset( $_GET['revision'] ) ) : // @codingStandardsIgnoreLine Nonce not required.
|
392 |
+
?>
|
393 |
+
<div class="notice notice-success adstxt-notice adstxt-saved">
|
394 |
+
<p><?php echo esc_html__( 'Revision restored', 'ads-txt' ); ?></p>
|
395 |
+
</div>
|
396 |
+
<?php
|
397 |
+
endif;
|
398 |
}
|
399 |
+
add_action( 'admin_notices', __NAMESPACE__ . '\admin_notices' );
|
inc/post-type.php
CHANGED
@@ -1,4 +1,9 @@
|
|
1 |
<?php
|
|
|
|
|
|
|
|
|
|
|
2 |
|
3 |
namespace Adstxt;
|
4 |
|
@@ -9,10 +14,11 @@ namespace Adstxt;
|
|
9 |
*/
|
10 |
function register() {
|
11 |
register_post_type(
|
12 |
-
'adstxt',
|
|
|
13 |
'labels' => array(
|
14 |
-
'name' =>
|
15 |
-
'singular_name' =>
|
16 |
),
|
17 |
'public' => false,
|
18 |
'hierarchical' => false,
|
@@ -32,7 +38,7 @@ function register() {
|
|
32 |
'edit_post' => 'customize',
|
33 |
'edit_posts' => 'customize',
|
34 |
'edit_private_posts' => 'customize',
|
35 |
-
'edit_published_posts' => '
|
36 |
'publish_posts' => 'customize',
|
37 |
'read' => 'read',
|
38 |
'read_post' => 'customize',
|
1 |
<?php
|
2 |
+
/**
|
3 |
+
* Post Type functionality for Ads.txt.
|
4 |
+
*
|
5 |
+
* @package Ads_Txt_Manager
|
6 |
+
*/
|
7 |
|
8 |
namespace Adstxt;
|
9 |
|
14 |
*/
|
15 |
function register() {
|
16 |
register_post_type(
|
17 |
+
'adstxt',
|
18 |
+
array(
|
19 |
'labels' => array(
|
20 |
+
'name' => esc_html_x( 'Ads.txt', 'post type general name', 'ads-txt' ),
|
21 |
+
'singular_name' => esc_html_x( 'Ads.txt', 'post type singular name', 'ads-txt' ),
|
22 |
),
|
23 |
'public' => false,
|
24 |
'hierarchical' => false,
|
38 |
'edit_post' => 'customize',
|
39 |
'edit_posts' => 'customize',
|
40 |
'edit_private_posts' => 'customize',
|
41 |
+
'edit_published_posts' => 'edit_published_posts',
|
42 |
'publish_posts' => 'customize',
|
43 |
'read' => 'read',
|
44 |
'read_post' => 'customize',
|
inc/save.php
CHANGED
@@ -1,4 +1,9 @@
|
|
1 |
<?php
|
|
|
|
|
|
|
|
|
|
|
2 |
|
3 |
namespace Adstxt;
|
4 |
|
@@ -16,12 +21,14 @@ function save() {
|
|
16 |
$_post = stripslashes_deep( $_POST );
|
17 |
$doing_ajax = defined( 'DOING_AJAX' ) && DOING_AJAX;
|
18 |
|
19 |
-
$post_id = $_post['post_id'];
|
20 |
$ays = isset( $_post['adstxt_ays'] ) ? $_post['adstxt_ays'] : null;
|
21 |
|
22 |
// Different browsers use different line endings.
|
23 |
$lines = preg_split( '/\r\n|\r|\n/', $_post['adstxt'] );
|
24 |
-
$sanitized =
|
|
|
|
|
25 |
|
26 |
foreach ( $lines as $i => $line ) {
|
27 |
$line_number = $i + 1;
|
@@ -50,7 +57,6 @@ function save() {
|
|
50 |
$post_id = wp_insert_post( $postarr );
|
51 |
|
52 |
if ( $post_id ) {
|
53 |
-
update_option( 'adstxt_post', $post_id );
|
54 |
$response['saved'] = true;
|
55 |
}
|
56 |
}
|
@@ -59,15 +65,14 @@ function save() {
|
|
59 |
$response['sanitized'] = $sanitized;
|
60 |
|
61 |
if ( ! empty( $errors ) ) {
|
62 |
-
|
63 |
-
$response['errors'] = array_map( __NAMESPACE__ . '\format_error', $errors );
|
64 |
}
|
65 |
|
66 |
echo wp_json_encode( $response );
|
67 |
die();
|
68 |
}
|
69 |
|
70 |
-
|
71 |
exit;
|
72 |
}
|
73 |
add_action( 'admin_post_adstxt-save', __NAMESPACE__ . '\save' );
|
@@ -96,9 +101,8 @@ function validate_line( $line, $line_number ) {
|
|
96 |
// The spec currently supports CONTACT and SUBDOMAIN.
|
97 |
if ( ! preg_match( '/^(CONTACT|SUBDOMAIN)=/i', $line ) ) {
|
98 |
$errors[] = array(
|
99 |
-
'line'
|
100 |
-
'type'
|
101 |
-
'message' => __( 'Unrecognized variable', 'ads-txt' ),
|
102 |
);
|
103 |
} elseif ( 0 === stripos( $line, 'subdomain=' ) ) { // Subdomains should be, well, subdomains.
|
104 |
// Disregard any comments.
|
@@ -111,14 +115,10 @@ function validate_line( $line, $line_number ) {
|
|
111 |
// If there's anything other than one piece left something's not right.
|
112 |
if ( 1 !== count( $subdomain ) || ! preg_match( $domain_regex, $subdomain[0] ) ) {
|
113 |
$subdomain = implode( '', $subdomain );
|
114 |
-
$errors[]
|
115 |
-
'line'
|
116 |
-
'type'
|
117 |
-
'
|
118 |
-
/* translators: %s: Subdomain */
|
119 |
-
__( '"%s" does not appear to be a valid subdomain', 'ads-txt' ),
|
120 |
-
esc_html( $subdomain )
|
121 |
-
),
|
122 |
);
|
123 |
}
|
124 |
}
|
@@ -141,21 +141,16 @@ function validate_line( $line, $line_number ) {
|
|
141 |
|
142 |
if ( ! preg_match( $domain_regex, $exchange ) ) {
|
143 |
$errors[] = array(
|
144 |
-
'line'
|
145 |
-
'type'
|
146 |
-
'
|
147 |
-
/* translators: %s: Exchange domain */
|
148 |
-
__( '"%s" does not appear to be a valid exchange domain', 'ads-txt' ),
|
149 |
-
esc_html( $exchange )
|
150 |
-
),
|
151 |
);
|
152 |
}
|
153 |
|
154 |
if ( ! preg_match( '/^(RESELLER|DIRECT)$/i', $account_type ) ) {
|
155 |
$errors[] = array(
|
156 |
-
'line'
|
157 |
-
'type'
|
158 |
-
'message' => __( 'Third field should be RESELLER or DIRECT', 'ads-txt' ),
|
159 |
);
|
160 |
}
|
161 |
|
@@ -166,13 +161,9 @@ function validate_line( $line, $line_number ) {
|
|
166 |
// TAG-IDs are meant to be checked against their DB - perhaps good for a service or the future.
|
167 |
if ( ! empty( $tag_id ) && ! preg_match( '/^[a-f0-9]{16}$/', $tag_id ) ) {
|
168 |
$errors[] = array(
|
169 |
-
'line'
|
170 |
-
'type'
|
171 |
-
'
|
172 |
-
/* translators: %s: TAG-ID */
|
173 |
-
__( '"%s" does not appear to be a valid TAG-ID', 'ads-txt' ),
|
174 |
-
esc_html( $fields[3] )
|
175 |
-
),
|
176 |
);
|
177 |
}
|
178 |
}
|
@@ -184,9 +175,8 @@ function validate_line( $line, $line_number ) {
|
|
184 |
$sanitized = wp_strip_all_tags( $line );
|
185 |
|
186 |
$errors[] = array(
|
187 |
-
'line'
|
188 |
-
'type'
|
189 |
-
'message' => __( 'Invalid record', 'ads-txt' ),
|
190 |
);
|
191 |
}
|
192 |
|
@@ -198,3 +188,15 @@ function validate_line( $line, $line_number ) {
|
|
198 |
'errors' => $errors,
|
199 |
);
|
200 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
<?php
|
2 |
+
/**
|
3 |
+
* Save functionality for Ads.txt.
|
4 |
+
*
|
5 |
+
* @package Ads_Txt_Manager
|
6 |
+
*/
|
7 |
|
8 |
namespace Adstxt;
|
9 |
|
21 |
$_post = stripslashes_deep( $_POST );
|
22 |
$doing_ajax = defined( 'DOING_AJAX' ) && DOING_AJAX;
|
23 |
|
24 |
+
$post_id = (int) $_post['post_id'];
|
25 |
$ays = isset( $_post['adstxt_ays'] ) ? $_post['adstxt_ays'] : null;
|
26 |
|
27 |
// Different browsers use different line endings.
|
28 |
$lines = preg_split( '/\r\n|\r|\n/', $_post['adstxt'] );
|
29 |
+
$sanitized = array();
|
30 |
+
$errors = array();
|
31 |
+
$response = array();
|
32 |
|
33 |
foreach ( $lines as $i => $line ) {
|
34 |
$line_number = $i + 1;
|
57 |
$post_id = wp_insert_post( $postarr );
|
58 |
|
59 |
if ( $post_id ) {
|
|
|
60 |
$response['saved'] = true;
|
61 |
}
|
62 |
}
|
65 |
$response['sanitized'] = $sanitized;
|
66 |
|
67 |
if ( ! empty( $errors ) ) {
|
68 |
+
$response['errors'] = $errors;
|
|
|
69 |
}
|
70 |
|
71 |
echo wp_json_encode( $response );
|
72 |
die();
|
73 |
}
|
74 |
|
75 |
+
wp_safe_redirect( esc_url_raw( $_post['_wp_http_referer'] ) . '&updated=true' );
|
76 |
exit;
|
77 |
}
|
78 |
add_action( 'admin_post_adstxt-save', __NAMESPACE__ . '\save' );
|
101 |
// The spec currently supports CONTACT and SUBDOMAIN.
|
102 |
if ( ! preg_match( '/^(CONTACT|SUBDOMAIN)=/i', $line ) ) {
|
103 |
$errors[] = array(
|
104 |
+
'line' => $line_number,
|
105 |
+
'type' => 'invalid_variable',
|
|
|
106 |
);
|
107 |
} elseif ( 0 === stripos( $line, 'subdomain=' ) ) { // Subdomains should be, well, subdomains.
|
108 |
// Disregard any comments.
|
115 |
// If there's anything other than one piece left something's not right.
|
116 |
if ( 1 !== count( $subdomain ) || ! preg_match( $domain_regex, $subdomain[0] ) ) {
|
117 |
$subdomain = implode( '', $subdomain );
|
118 |
+
$errors[] = array(
|
119 |
+
'line' => $line_number,
|
120 |
+
'type' => 'invalid_subdomain',
|
121 |
+
'value' => $subdomain,
|
|
|
|
|
|
|
|
|
122 |
);
|
123 |
}
|
124 |
}
|
141 |
|
142 |
if ( ! preg_match( $domain_regex, $exchange ) ) {
|
143 |
$errors[] = array(
|
144 |
+
'line' => $line_number,
|
145 |
+
'type' => 'invalid_exchange',
|
146 |
+
'value' => $exchange,
|
|
|
|
|
|
|
|
|
147 |
);
|
148 |
}
|
149 |
|
150 |
if ( ! preg_match( '/^(RESELLER|DIRECT)$/i', $account_type ) ) {
|
151 |
$errors[] = array(
|
152 |
+
'line' => $line_number,
|
153 |
+
'type' => 'invalid_account_type',
|
|
|
154 |
);
|
155 |
}
|
156 |
|
161 |
// TAG-IDs are meant to be checked against their DB - perhaps good for a service or the future.
|
162 |
if ( ! empty( $tag_id ) && ! preg_match( '/^[a-f0-9]{16}$/', $tag_id ) ) {
|
163 |
$errors[] = array(
|
164 |
+
'line' => $line_number,
|
165 |
+
'type' => 'invalid_tagid',
|
166 |
+
'value' => $fields[3],
|
|
|
|
|
|
|
|
|
167 |
);
|
168 |
}
|
169 |
}
|
175 |
$sanitized = wp_strip_all_tags( $line );
|
176 |
|
177 |
$errors[] = array(
|
178 |
+
'line' => $line_number,
|
179 |
+
'type' => 'invalid_record',
|
|
|
180 |
);
|
181 |
}
|
182 |
|
188 |
'errors' => $errors,
|
189 |
);
|
190 |
}
|
191 |
+
|
192 |
+
/**
|
193 |
+
* Delete `adstxt_errors` meta when restoring a revision.
|
194 |
+
*
|
195 |
+
* @param int $post_id Post ID, not revision ID.
|
196 |
+
*
|
197 |
+
* @return void
|
198 |
+
*/
|
199 |
+
function clear_error_meta( $post_id ) {
|
200 |
+
delete_post_meta( $post_id, 'adstxt_errors' );
|
201 |
+
}
|
202 |
+
add_action( 'wp_restore_post_revision', __NAMESPACE__ . '\clear_error_meta', 10, 1 );
|
js/admin.js
CHANGED
@@ -7,12 +7,38 @@
|
|
7 |
mode: 'shell'
|
8 |
} );
|
9 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
submit.on( 'click', function( e ){
|
11 |
e.preventDefault();
|
12 |
|
13 |
var textarea = $( document.getElementById( 'adstxt_content' ) ),
|
14 |
notices = $( '.adstxt-notice' ),
|
15 |
submit_wrap = $( 'p.submit' ),
|
|
|
16 |
spinner = submit_wrap.find( '.spinner' );
|
17 |
|
18 |
submit.attr( 'disabled', 'disabled' );
|
@@ -40,9 +66,7 @@
|
|
40 |
}
|
41 |
|
42 |
if ( 'undefined' !== typeof r.saved && r.saved ) {
|
43 |
-
|
44 |
-
'saved_message': adstxt.saved_message
|
45 |
-
};
|
46 |
} else {
|
47 |
templateData.errors = {
|
48 |
'error_message': adstxt.unknown_error
|
@@ -55,13 +79,20 @@
|
|
55 |
'errors': r.errors
|
56 |
}
|
57 |
}
|
58 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
}
|
60 |
})
|
61 |
});
|
62 |
|
63 |
$( '.wrap' ).on( 'click', '#adstxt-ays-checkbox', function( e ) {
|
64 |
-
if ( true === $( this ).prop('checked') ) {
|
65 |
submit.removeAttr( 'disabled' );
|
66 |
} else {
|
67 |
submit.attr( 'disabled', 'disabled' );
|
7 |
mode: 'shell'
|
8 |
} );
|
9 |
|
10 |
+
function checkForAdsFile( e ){
|
11 |
+
var currentTime = Date.now(),
|
12 |
+
adstxtUrl = '/ads.txt?currentTime=' + currentTime,
|
13 |
+
spinner = $( '.existing-adstxt .spinner' );
|
14 |
+
|
15 |
+
if ( false !== e ) {
|
16 |
+
e.preventDefault();
|
17 |
+
}
|
18 |
+
|
19 |
+
spinner.addClass( 'is-active' );
|
20 |
+
|
21 |
+
$.get( adstxtUrl, function( data, status ){
|
22 |
+
spinner.removeClass( 'is-active' );
|
23 |
+
$( '.existing-adstxt' ).show();
|
24 |
+
} ).fail( function() {
|
25 |
+
// Ads.txt not found
|
26 |
+
$( '.existing-adstxt' ).hide();
|
27 |
+
});
|
28 |
+
}
|
29 |
+
|
30 |
+
// Call our check when we first load the page
|
31 |
+
checkForAdsFile( false );
|
32 |
+
|
33 |
+
$( '.ads-txt-rerun-check' ).on( 'click', checkForAdsFile );
|
34 |
+
|
35 |
submit.on( 'click', function( e ){
|
36 |
e.preventDefault();
|
37 |
|
38 |
var textarea = $( document.getElementById( 'adstxt_content' ) ),
|
39 |
notices = $( '.adstxt-notice' ),
|
40 |
submit_wrap = $( 'p.submit' ),
|
41 |
+
saveSuccess = false,
|
42 |
spinner = submit_wrap.find( '.spinner' );
|
43 |
|
44 |
submit.attr( 'disabled', 'disabled' );
|
66 |
}
|
67 |
|
68 |
if ( 'undefined' !== typeof r.saved && r.saved ) {
|
69 |
+
saveSuccess = true;
|
|
|
|
|
70 |
} else {
|
71 |
templateData.errors = {
|
72 |
'error_message': adstxt.unknown_error
|
79 |
'errors': r.errors
|
80 |
}
|
81 |
}
|
82 |
+
|
83 |
+
// Refresh after a successful save, otherwise show the error message.
|
84 |
+
if ( saveSuccess ) {
|
85 |
+
document.location = document.location + '&ads_txt_saved=1';
|
86 |
+
} else {
|
87 |
+
notificationArea.html( notificationTemplate( templateData ) ).show();
|
88 |
+
}
|
89 |
+
|
90 |
}
|
91 |
})
|
92 |
});
|
93 |
|
94 |
$( '.wrap' ).on( 'click', '#adstxt-ays-checkbox', function( e ) {
|
95 |
+
if ( true === $( this ).prop( 'checked' ) ) {
|
96 |
submit.removeAttr( 'disabled' );
|
97 |
} else {
|
98 |
submit.attr( 'disabled', 'disabled' );
|
readme.txt
CHANGED
@@ -1,14 +1,14 @@
|
|
1 |
=== Ads.txt Manager ===
|
2 |
Contributors: 10up, helen, adamsilverstein, jakemgold
|
3 |
-
Author URI:
|
4 |
Plugin URI: https://github.com/10up/ads-txt
|
5 |
Tags: ads.txt, ads, ad manager, advertising, publishing, publishers
|
6 |
Requires at least: 4.9
|
7 |
-
Tested up to:
|
8 |
Requires PHP: 5.3
|
9 |
-
Stable tag:
|
10 |
License: GPLv2 or later
|
11 |
-
License URI:
|
12 |
Text Domain: ads-txt
|
13 |
|
14 |
Create, manage, and validate your ads.txt from within WordPress, just like any other content asset. Requires PHP 5.3+ and WordPress 4.9+.
|
@@ -25,6 +25,7 @@ Ads.txt is an initiative by the Interactive Advertising Bureau to enable publish
|
|
25 |
|
26 |
* Requires PHP 5.3+.
|
27 |
* Requires WordPress 4.9+. Older versions of WordPress will not display any syntax highlighting and may break JavaScript and/or be unable to localize the plugin.
|
|
|
28 |
* Rewrites need to be enabled. Without rewrites, WordPress cannot know to supply `/ads.txt` when requested.
|
29 |
* Your site URL must not contain a path (e.g. `https://example.com/site/` or path-based multisite installs). While the plugin will appear to function in the admin, it will not display the contents at `https://example.com/site/ads.txt`. This is because the plugin follows the IAB spec, which requires that the ads.txt file be located at the root of a domain or subdomain.
|
30 |
|
@@ -32,6 +33,10 @@ Ads.txt is an initiative by the Interactive Advertising Bureau to enable publish
|
|
32 |
|
33 |
We're closely monitoring continued developments in the ad fraud space, and see this plugin as not only a way to create and manage your ads.txt file but also be prepared for future changes and upgrades to specifications. Ads.cert is still in the extremely early stages so we don't see any immediate concerns with implementing ads.txt.
|
34 |
|
|
|
|
|
|
|
|
|
35 |
== Screenshots ==
|
36 |
|
37 |
1. Example of editing an ads.txt file with errors
|
@@ -42,7 +47,24 @@ We're closely monitoring continued developments in the ad fraud space, and see t
|
|
42 |
3. Head to Settings → Ads.txt and add the records you need.
|
43 |
4. Check it out at yoursite.com/ads.txt!
|
44 |
|
|
|
|
|
|
|
|
|
45 |
== Changelog ==
|
46 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
= 1.0 =
|
48 |
* Initial plugin release
|
1 |
=== Ads.txt Manager ===
|
2 |
Contributors: 10up, helen, adamsilverstein, jakemgold
|
3 |
+
Author URI: https://10up.com
|
4 |
Plugin URI: https://github.com/10up/ads-txt
|
5 |
Tags: ads.txt, ads, ad manager, advertising, publishing, publishers
|
6 |
Requires at least: 4.9
|
7 |
+
Tested up to: 5.3
|
8 |
Requires PHP: 5.3
|
9 |
+
Stable tag: 1.2.0
|
10 |
License: GPLv2 or later
|
11 |
+
License URI: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
12 |
Text Domain: ads-txt
|
13 |
|
14 |
Create, manage, and validate your ads.txt from within WordPress, just like any other content asset. Requires PHP 5.3+ and WordPress 4.9+.
|
25 |
|
26 |
* Requires PHP 5.3+.
|
27 |
* Requires WordPress 4.9+. Older versions of WordPress will not display any syntax highlighting and may break JavaScript and/or be unable to localize the plugin.
|
28 |
+
* Ad blockers may break syntax highlighting and pre-save error checking on the edit screen.
|
29 |
* Rewrites need to be enabled. Without rewrites, WordPress cannot know to supply `/ads.txt` when requested.
|
30 |
* Your site URL must not contain a path (e.g. `https://example.com/site/` or path-based multisite installs). While the plugin will appear to function in the admin, it will not display the contents at `https://example.com/site/ads.txt`. This is because the plugin follows the IAB spec, which requires that the ads.txt file be located at the root of a domain or subdomain.
|
31 |
|
33 |
|
34 |
We're closely monitoring continued developments in the ad fraud space, and see this plugin as not only a way to create and manage your ads.txt file but also be prepared for future changes and upgrades to specifications. Ads.cert is still in the extremely early stages so we don't see any immediate concerns with implementing ads.txt.
|
35 |
|
36 |
+
=== What about app-ads.txt? ===
|
37 |
+
|
38 |
+
We plan on adding support for this file in the future! If you'd like to follow along with development or even help us get it done, please see [this GitHub issue](https://github.com/10up/ads-txt/issues/40).
|
39 |
+
|
40 |
== Screenshots ==
|
41 |
|
42 |
1. Example of editing an ads.txt file with errors
|
47 |
3. Head to Settings → Ads.txt and add the records you need.
|
48 |
4. Check it out at yoursite.com/ads.txt!
|
49 |
|
50 |
+
Note: If you already have an existing ads.txt file in the web root, the plugin will not read in the contents of that file, and changes you make in WordPress admin will not overwrite contents of the physical file.
|
51 |
+
|
52 |
+
You will need to rename or remove the existing ads.txt file (keeping a copy of the records it contains to put into the new settings screen) before you will be able to see any changes you make to ads.txt inside the WordPress admin.
|
53 |
+
|
54 |
== Changelog ==
|
55 |
|
56 |
+
= 1.2.0 =
|
57 |
+
* **Added:** Make revisions accessible in the admin - now you can restore older versions of your ads.txt or view how it's changed over time (props [@adamsilverstein](https://github.com/adamsilverstein), [@helen](https://github.com/helen))
|
58 |
+
* **Added:** Show a notice on the edit screen if an ads.txt file exists on the server (props [@kkoppenhaver](https://github.com/kkoppenhaver), [@helen](https://github.com/helen), [@tomjn](https://github.com/tomjn), [@adamsilverstein](https://github.com/adamsilverstein))
|
59 |
+
* **Added:** Add a custom `edit_ads_txt` capability for granular assignment, which is assigned to administrators by default (props [@ethanclevenger91](https://github.com/ethanclevenger91), [@adamsilverstein](https://github.com/adamsilverstein))
|
60 |
+
* **Added:** Enable filtering of the output using `ads_txt_content` (props [@ethanclevenger91](https://github.com/ethanclevenger91))
|
61 |
+
* **Changed:** Updated documentation, automation, and coding standards (props [@jeffpaul](https://github.com/jeffpaul), [@adamsilverstein](https://github.com/adamsilverstein), [@helen](https://github.com/helen), [@mmcachran](https://github.com/mmcachran))
|
62 |
+
* **Fixed:** Early escaping (props [@tomjn](https://github.com/tomjn))
|
63 |
+
* **Fixed:** PHPCS issues and added PHPCS scanning (props [@adamsilverstein](https://github.com/adamsilverstein))
|
64 |
+
|
65 |
+
= 1.1 =
|
66 |
+
* Better error message formatting (wraps values in `<code>` tags for better readability)
|
67 |
+
* WordPress.com VIP-approved escaping
|
68 |
+
|
69 |
= 1.0 =
|
70 |
* Initial plugin release
|