| 1 |
<?php |
| 2 |
/** |
| 3 |
* Ebook Store - "Templates" settings tab. |
| 4 |
* |
| 5 |
* Pages the buyer is sent to, the delivery e-mail, and the HTML used for the |
| 6 |
* thank-you page and the checkout form. |
| 7 |
* |
| 8 |
* PHP 7.4 compatible. |
| 9 |
* |
| 10 |
* @package EbookStore |
| 11 |
*/ |
| 12 |
|
| 13 |
if ( ! defined( 'ABSPATH' ) ) { |
| 14 |
exit; |
| 15 |
} |
| 16 |
|
| 17 |
settings_fields( 'ebook-settings-group-templates' ); |
| 18 |
do_settings_sections( 'ebook-settings-group-templates' ); |
| 19 |
|
| 20 |
// $op holds the shipped defaults; it is created by ebook_settings_page(). Guard |
| 21 |
// so the tab still renders if this file is ever included on its own. |
| 22 |
if ( ! isset( $op ) || ! is_object( $op ) ) { |
| 23 |
$op = new QSWPOptions(); |
| 24 |
} |
| 25 |
|
| 26 |
$ebook_general_tab_url = function_exists( 'ebook_store_get_settings_tab_url' ) |
| 27 |
? ebook_store_get_settings_tab_url( 'General' ) |
| 28 |
: admin_url( 'options-general.php?page=ebook_options.php' ); |
| 29 |
|
| 30 |
$ebook_thankyou_page_id = (int) get_option( 'ebook_store_checkout_page', 0 ); |
| 31 |
$ebook_cancel_page_id = (int) get_option( 'ebook_store_cancel_page', 0 ); |
| 32 |
$ebook_thankyou_page = $ebook_thankyou_page_id > 0 ? get_post( $ebook_thankyou_page_id ) : null; |
| 33 |
$ebook_cancel_page = $ebook_cancel_page_id > 0 ? get_post( $ebook_cancel_page_id ) : null; |
| 34 |
$ebook_thankyou_has_code = false; |
| 35 |
|
| 36 |
if ( $ebook_thankyou_page instanceof WP_Post ) { |
| 37 |
$ebook_thankyou_has_code = has_shortcode( |
| 38 |
(string) get_post_field( 'post_content', $ebook_thankyou_page_id ), |
| 39 |
'ebook_thank_you' |
| 40 |
); |
| 41 |
} |
| 42 |
|
| 43 |
/** |
| 44 |
* Render one page picker with a real id, a real label and a description. |
| 45 |
* |
| 46 |
* A closure rather than a named function so re-including this file can never |
| 47 |
* trigger a "cannot redeclare" fatal. |
| 48 |
* |
| 49 |
* @param string $field_id HTML id and option name. |
| 50 |
* @param string $label Visible label. |
| 51 |
* @param int $selected Currently selected page id. |
| 52 |
* @param string $none_text Text for the "nothing chosen" entry. |
| 53 |
* @param string $help Description below the control. |
| 54 |
*/ |
| 55 |
$ebook_render_page_picker = function ( $field_id, $label, $selected, $none_text, $help ) { |
| 56 |
?> |
| 57 |
<div class="ebook-settings-field" data-ebook-search="<?php echo esc_attr( $label . ' ' . wp_strip_all_tags( $help ) . ' ' . $field_id ); ?>"> |
| 58 |
<label for="<?php echo esc_attr( $field_id ); ?>"><?php echo esc_html( $label ); ?></label> |
| 59 |
<?php |
| 60 |
wp_dropdown_pages( |
| 61 |
array( |
| 62 |
'depth' => 0, |
| 63 |
'child_of' => 0, |
| 64 |
'selected' => $selected, |
| 65 |
'echo' => 1, |
| 66 |
'name' => $field_id, |
| 67 |
'id' => $field_id, |
| 68 |
'show_option_none' => $none_text, |
| 69 |
'show_option_no_change' => null, |
| 70 |
'option_none_value' => '0', |
| 71 |
'post_type' => 'page', |
| 72 |
) |
| 73 |
); |
| 74 |
?> |
| 75 |
<p class="description"><?php echo wp_kses_post( $help ); ?></p> |
| 76 |
</div> |
| 77 |
<?php |
| 78 |
}; |
| 79 |
|
| 80 |
/** |
| 81 |
* Render the copyable placeholder reference. |
| 82 |
* |
| 83 |
* @param array $placeholders code => explanation. |
| 84 |
*/ |
| 85 |
$ebook_render_placeholders = function ( $placeholders ) { |
| 86 |
$index = 0; |
| 87 |
?> |
| 88 |
<dl class="ebook-settings-placeholders"> |
| 89 |
<?php |
| 90 |
foreach ( $placeholders as $code => $explanation ) { |
| 91 |
$index++; |
| 92 |
$input_id = 'ebook-placeholder-' . $index; |
| 93 |
?> |
| 94 |
<div class="ebook-settings-placeholders__row"> |
| 95 |
<dt> |
| 96 |
<span class="ebook-code__row"> |
| 97 |
<input |
| 98 |
id="<?php echo esc_attr( $input_id ); ?>" |
| 99 |
class="ebook-code__input ebook-settings-monospace-input" |
| 100 |
type="text" |
| 101 |
readonly="readonly" |
| 102 |
value="<?php echo esc_attr( $code ); ?>" |
| 103 |
aria-label="<?php |
| 104 |
/* translators: %s: a placeholder such as %%first_name%%. */ |
| 105 |
echo esc_attr( sprintf( __( 'Placeholder %s', 'ebook-store' ), $code ) ); |
| 106 |
?>" /> |
| 107 |
<button type="button" class="button ebook-code__copy" data-copy-target="#<?php echo esc_attr( $input_id ); ?>"> |
| 108 |
<?php echo esc_html__( 'Copy', 'ebook-store' ); ?> |
| 109 |
</button> |
| 110 |
<span class="ebook-code__status" role="status" aria-live="polite"></span> |
| 111 |
</span> |
| 112 |
</dt> |
| 113 |
<dd><?php echo esc_html( $explanation ); ?></dd> |
| 114 |
</div> |
| 115 |
<?php |
| 116 |
} |
| 117 |
?> |
| 118 |
</dl> |
| 119 |
<?php |
| 120 |
}; |
| 121 |
|
| 122 |
ebook_store_render_hero( |
| 123 |
array( |
| 124 |
'eyebrow' => __( 'Templates', 'ebook-store' ), |
| 125 |
'title' => __( 'Pages, e-mails and page content', 'ebook-store' ), |
| 126 |
'intro' => __( 'Everything a buyer reads after paying: the page they land on, the e-mail that carries their download link, and the wording of both. Change the text freely; keep the %%placeholders%% so the real order details are filled in automatically.', 'ebook-store' ), |
| 127 |
) |
| 128 |
); |
| 129 |
|
| 130 |
/* --------------------------------------------------------------------------- |
| 131 |
* 1. Pages |
| 132 |
* ------------------------------------------------------------------------ */ |
| 133 |
|
| 134 |
ebook_store_section_open( |
| 135 |
array( |
| 136 |
'id' => 'ebook-templates-pages', |
| 137 |
'eyebrow' => __( 'Step 1', 'ebook-store' ), |
| 138 |
'title' => __( 'Pages', 'ebook-store' ), |
| 139 |
'intro' => __( 'Which of your WordPress pages the buyer is sent to after paying, and where they land if they change their mind.', 'ebook-store' ), |
| 140 |
) |
| 141 |
); |
| 142 |
|
| 143 |
ebook_store_grid_open( 2 ); |
| 144 |
|
| 145 |
$ebook_render_page_picker( |
| 146 |
'ebook_store_checkout_page', |
| 147 |
__( 'Thank-you page (buyers land here after paying)', 'ebook-store' ), |
| 148 |
$ebook_thankyou_page_id, |
| 149 |
__( '-- Please select a page --', 'ebook-store' ), |
| 150 |
sprintf( |
| 151 |
/* translators: %s: the [ebook_thank_you] shortcode, shown literally. */ |
| 152 |
__( 'Pick the page that shows the download link. That page must contain the shortcode %s, otherwise the buyer sees an empty page and never gets their file.', 'ebook-store' ), |
| 153 |
'<code>[ebook_thank_you]</code>' |
| 154 |
) |
| 155 |
); |
| 156 |
|
| 157 |
$ebook_render_page_picker( |
| 158 |
'ebook_store_cancel_page', |
| 159 |
__( 'Cancelled-order page (optional)', 'ebook-store' ), |
| 160 |
$ebook_cancel_page_id, |
| 161 |
__( '-- Optional, none selected --', 'ebook-store' ), |
| 162 |
__( 'Shown when someone starts a payment and then cancels it at PayPal. Leave this empty and they are returned to your home page.', 'ebook-store' ) |
| 163 |
); |
| 164 |
|
| 165 |
ebook_store_grid_close(); |
| 166 |
|
| 167 |
// The single most common setup mistake: a thank-you page is chosen, but it does |
| 168 |
// not actually contain the shortcode. Say so plainly. |
| 169 |
?> |
| 170 |
<ul class="ebook-settings-status-list"> |
| 171 |
<?php |
| 172 |
if ( $ebook_thankyou_page_id < 1 ) { |
| 173 |
ebook_store_status_row( |
| 174 |
__( 'Thank-you page', 'ebook-store' ), |
| 175 |
'error', |
| 176 |
__( 'No page is selected yet, so buyers have nowhere to collect their download.', 'ebook-store' ), |
| 177 |
array( |
| 178 |
'label' => __( 'Create one for me', 'ebook-store' ), |
| 179 |
'url' => wp_nonce_url( admin_url( 'admin-post.php?action=ebook_store_fix_thankyou' ), 'ebook_store_fix_thankyou' ), |
| 180 |
) |
| 181 |
); |
| 182 |
} elseif ( ! ( $ebook_thankyou_page instanceof WP_Post ) ) { |
| 183 |
ebook_store_status_row( |
| 184 |
__( 'Thank-you page', 'ebook-store' ), |
| 185 |
'error', |
| 186 |
__( 'The page that was selected no longer exists. Choose another page above.', 'ebook-store' ), |
| 187 |
array( |
| 188 |
'label' => __( 'Create one for me', 'ebook-store' ), |
| 189 |
'url' => wp_nonce_url( admin_url( 'admin-post.php?action=ebook_store_fix_thankyou' ), 'ebook_store_fix_thankyou' ), |
| 190 |
) |
| 191 |
); |
| 192 |
} elseif ( ! $ebook_thankyou_has_code ) { |
| 193 |
ebook_store_status_row( |
| 194 |
__( 'Thank-you page', 'ebook-store' ), |
| 195 |
'error', |
| 196 |
sprintf( |
| 197 |
/* translators: 1: page title, 2: the [ebook_thank_you] shortcode. */ |
| 198 |
__( '"%1$s" does not contain %2$s. Buyers will see an empty page instead of their download link. Edit the page and add the shortcode.', 'ebook-store' ), |
| 199 |
$ebook_thankyou_page->post_title, |
| 200 |
'[ebook_thank_you]' |
| 201 |
), |
| 202 |
array( |
| 203 |
'label' => __( 'Edit the page', 'ebook-store' ), |
| 204 |
'url' => (string) get_edit_post_link( $ebook_thankyou_page_id, '' ), |
| 205 |
) |
| 206 |
); |
| 207 |
} else { |
| 208 |
ebook_store_status_row( |
| 209 |
__( 'Thank-you page', 'ebook-store' ), |
| 210 |
'ok', |
| 211 |
sprintf( |
| 212 |
/* translators: %s: page title. */ |
| 213 |
__( '"%s" is selected and contains the shortcode.', 'ebook-store' ), |
| 214 |
$ebook_thankyou_page->post_title |
| 215 |
), |
| 216 |
array( |
| 217 |
'label' => __( 'View the page', 'ebook-store' ), |
| 218 |
'url' => (string) get_permalink( $ebook_thankyou_page_id ), |
| 219 |
) |
| 220 |
); |
| 221 |
} |
| 222 |
|
| 223 |
if ( $ebook_cancel_page_id < 1 ) { |
| 224 |
ebook_store_status_row( |
| 225 |
__( 'Cancelled-order page', 'ebook-store' ), |
| 226 |
'muted', |
| 227 |
__( 'Not set. Buyers who cancel are returned to your home page, which is fine for most stores.', 'ebook-store' ) |
| 228 |
); |
| 229 |
} elseif ( ! ( $ebook_cancel_page instanceof WP_Post ) ) { |
| 230 |
ebook_store_status_row( |
| 231 |
__( 'Cancelled-order page', 'ebook-store' ), |
| 232 |
'warn', |
| 233 |
__( 'The page that was selected no longer exists. Choose another page or clear this setting.', 'ebook-store' ) |
| 234 |
); |
| 235 |
} else { |
| 236 |
ebook_store_status_row( |
| 237 |
__( 'Cancelled-order page', 'ebook-store' ), |
| 238 |
'ok', |
| 239 |
sprintf( |
| 240 |
/* translators: %s: page title. */ |
| 241 |
__( '"%s" is selected.', 'ebook-store' ), |
| 242 |
$ebook_cancel_page->post_title |
| 243 |
), |
| 244 |
array( |
| 245 |
'label' => __( 'View the page', 'ebook-store' ), |
| 246 |
'url' => (string) get_permalink( $ebook_cancel_page_id ), |
| 247 |
) |
| 248 |
); |
| 249 |
} |
| 250 |
?> |
| 251 |
</ul> |
| 252 |
<?php |
| 253 |
|
| 254 |
ebook_store_section_close(); |
| 255 |
|
| 256 |
/* --------------------------------------------------------------------------- |
| 257 |
* 2. Placeholder reference |
| 258 |
* ------------------------------------------------------------------------ */ |
| 259 |
|
| 260 |
ebook_store_section_open( |
| 261 |
array( |
| 262 |
'id' => 'ebook-templates-placeholders', |
| 263 |
'eyebrow' => __( 'Reference', 'ebook-store' ), |
| 264 |
'title' => __( 'Placeholders you can use', 'ebook-store' ), |
| 265 |
'intro' => __( 'Type any of these into the e-mail or the thank-you page below. When the message is sent, each one is swapped for the real detail from that order. Copy them exactly, including the two percent signs on each side.', 'ebook-store' ), |
| 266 |
) |
| 267 |
); |
| 268 |
|
| 269 |
$ebook_render_placeholders( |
| 270 |
array( |
| 271 |
'%%first_name%%' => __( "The buyer's first name.", 'ebook-store' ), |
| 272 |
'%%last_name%%' => __( "The buyer's surname.", 'ebook-store' ), |
| 273 |
'%%payer_email%%' => __( 'The e-mail address the buyer paid with.', 'ebook-store' ), |
| 274 |
'%%order_id%%' => __( 'Your order number, useful when a buyer writes in about a problem.', 'ebook-store' ), |
| 275 |
'%%txn_id%%' => __( 'The transaction number from the payment provider.', 'ebook-store' ), |
| 276 |
'%%downloadlink_html%%' => __( 'The ready-made download link (or links) for the book that was bought. Almost every store needs this one.', 'ebook-store' ), |
| 277 |
'%%ebook_bonus%%' => __( 'Download links for any bonus books attached to that title. Shows "None" if there are none.', 'ebook-store' ), |
| 278 |
'%%password%%' => __( 'The password that opens the PDF, when you protect your files with one.', 'ebook-store' ), |
| 279 |
'%%mc_gross%%' => __( 'The amount paid for the book, before tax.', 'ebook-store' ), |
| 280 |
'%%tax%%' => __( 'The tax or VAT charged on the order.', 'ebook-store' ), |
| 281 |
'%%total%%' => __( 'The full amount charged, tax included.', 'ebook-store' ), |
| 282 |
'%%mc_currency%%' => __( 'The currency code of the payment, for example USD or EUR.', 'ebook-store' ), |
| 283 |
'%%residence_country%%' => __( "The two-letter code of the buyer's country.", 'ebook-store' ), |
| 284 |
) |
| 285 |
); |
| 286 |
|
| 287 |
ebook_store_callout( |
| 288 |
sprintf( |
| 289 |
/* translators: 1: example placeholder, 2: example placeholder. */ |
| 290 |
__( 'Any other detail the payment provider sends with the order can be used the same way, for example %1$s or %2$s. If you type a name the order does not have, the placeholder is simply left on the page as you typed it, so always send yourself a test order after editing.', 'ebook-store' ), |
| 291 |
'<code>%%payment_date%%</code>', |
| 292 |
'<code>%%item_name%%</code>' |
| 293 |
), |
| 294 |
'soft', |
| 295 |
__( 'Anything else?', 'ebook-store' ) |
| 296 |
); |
| 297 |
|
| 298 |
ebook_store_section_close(); |
| 299 |
|
| 300 |
/* --------------------------------------------------------------------------- |
| 301 |
* 3. Order e-mail, thank-you content and checkout form. |
| 302 |
* |
| 303 |
* These are rich-text (TinyMCE) editors. They are the whole point of this tab, |
| 304 |
* and — importantly — a TinyMCE editor must be visible when it initialises, so |
| 305 |
* they are NOT placed inside a collapsed <details> (doing so left them with a |
| 306 |
* broken width and overlapping toolbar). The tab itself already lives behind the |
| 307 |
* "Pages & emails" group, so users only arrive here when they mean to. |
| 308 |
* ------------------------------------------------------------------------ */ |
| 309 |
|
| 310 |
ebook_store_section_open( |
| 311 |
array( |
| 312 |
'id' => 'ebook-templates-email', |
| 313 |
'eyebrow' => __( 'Step 2', 'ebook-store' ), |
| 314 |
'title' => __( 'Order e-mail', 'ebook-store' ), |
| 315 |
'intro' => __( 'The message sent to the buyer once payment clears. This is the copy most buyers keep, so make sure the download link is easy to find.', 'ebook-store' ), |
| 316 |
) |
| 317 |
); |
| 318 |
|
| 319 |
ebook_store_callout( |
| 320 |
sprintf( |
| 321 |
/* translators: %s: link to the General tab. */ |
| 322 |
__( 'This e-mail is only sent while <strong>Email delivery</strong> is switched on in the <a href="%s">General tab</a>. If it is off, buyers can only download from the thank-you page.', 'ebook-store' ), |
| 323 |
esc_url( $ebook_general_tab_url ) |
| 324 |
), |
| 325 |
'info' |
| 326 |
); |
| 327 |
|
| 328 |
ebook_store_field( |
| 329 |
array( |
| 330 |
'type' => 'text', |
| 331 |
'name' => 'email_delivery_subject', |
| 332 |
'id' => 'email_delivery_subject', |
| 333 |
'label' => __( 'Subject line', 'ebook-store' ), |
| 334 |
'value' => get_option( 'email_delivery_subject', $op->email_delivery_subject ), |
| 335 |
'placeholder' => $op->email_delivery_subject, |
| 336 |
'wide' => true, |
| 337 |
'help' => __( 'What the buyer sees in their inbox. Keep it short and mention your shop or the book title so it is not mistaken for spam.', 'ebook-store' ), |
| 338 |
) |
| 339 |
); |
| 340 |
?> |
| 341 |
|
| 342 |
<div class="ebook-settings-field ebook-settings-field--wide" data-ebook-search="<?php echo esc_attr( __( 'E-mail message', 'ebook-store' ) . ' email_delivery_text' ); ?>"> |
| 343 |
<label for="email_delivery_text"><?php echo esc_html__( 'E-mail message', 'ebook-store' ); ?></label> |
| 344 |
<?php |
| 345 |
wp_editor( |
| 346 |
get_option( 'email_delivery_text', $op->email_delivery_text ), |
| 347 |
'email_delivery_text', |
| 348 |
array( |
| 349 |
'textarea_name' => 'email_delivery_text', |
| 350 |
'textarea_rows' => 14, |
| 351 |
) |
| 352 |
); |
| 353 |
?> |
| 354 |
<p class="description"> |
| 355 |
<?php |
| 356 |
echo wp_kses_post( |
| 357 |
sprintf( |
| 358 |
/* translators: %s: the %%downloadlink_html%% placeholder. */ |
| 359 |
__( 'Always keep %s somewhere in this message. Without it the e-mail arrives with no way to download the book.', 'ebook-store' ), |
| 360 |
'<code>%%downloadlink_html%%</code>' |
| 361 |
) |
| 362 |
); |
| 363 |
?> |
| 364 |
</p> |
| 365 |
</div> |
| 366 |
|
| 367 |
<?php |
| 368 |
ebook_store_section_close(); |
| 369 |
|
| 370 |
/* --------------------------------------------------------------------------- |
| 371 |
* 4. Thank-you page content |
| 372 |
* ------------------------------------------------------------------------ */ |
| 373 |
|
| 374 |
ebook_store_section_open( |
| 375 |
array( |
| 376 |
'id' => 'ebook-templates-thankyou', |
| 377 |
'eyebrow' => __( 'Step 3', 'ebook-store' ), |
| 378 |
'title' => __( 'Thank-you page content', 'ebook-store' ), |
| 379 |
'intro' => __( 'What appears on the page the buyer lands on after paying. This text replaces the [ebook_thank_you] shortcode on the page you picked above.', 'ebook-store' ), |
| 380 |
) |
| 381 |
); |
| 382 |
?> |
| 383 |
|
| 384 |
<div class="ebook-settings-field ebook-settings-field--wide" data-ebook-search="<?php echo esc_attr( __( 'Thank-you page content', 'ebook-store' ) . ' thankyou_page' ); ?>"> |
| 385 |
<label for="thankyou_page"><?php echo esc_html__( 'Page content', 'ebook-store' ); ?></label> |
| 386 |
<?php |
| 387 |
wp_editor( |
| 388 |
get_option( 'thankyou_page', $op->thankyou_page ), |
| 389 |
'thankyou_page', |
| 390 |
array( |
| 391 |
'textarea_name' => 'thankyou_page', |
| 392 |
'textarea_rows' => 16, |
| 393 |
) |
| 394 |
); |
| 395 |
?> |
| 396 |
<p class="description"> |
| 397 |
<?php |
| 398 |
echo wp_kses_post( |
| 399 |
sprintf( |
| 400 |
/* translators: 1: the %%downloadlink_html%% placeholder, 2: the [ebook_thank_you] shortcode. */ |
| 401 |
__( 'Keep %1$s here too, and remember this text only shows up if the selected page contains %2$s.', 'ebook-store' ), |
| 402 |
'<code>%%downloadlink_html%%</code>', |
| 403 |
'<code>[ebook_thank_you]</code>' |
| 404 |
) |
| 405 |
); |
| 406 |
?> |
| 407 |
</p> |
| 408 |
</div> |
| 409 |
|
| 410 |
<?php |
| 411 |
ebook_store_section_close(); |
| 412 |
|
| 413 |
/* --------------------------------------------------------------------------- |
| 414 |
* 5. Checkout form markup |
| 415 |
* ------------------------------------------------------------------------ */ |
| 416 |
|
| 417 |
ebook_store_section_open( |
| 418 |
array( |
| 419 |
'id' => 'ebook-templates-form', |
| 420 |
'eyebrow' => __( 'Advanced', 'ebook-store' ), |
| 421 |
'title' => __( 'Checkout form markup', 'ebook-store' ), |
| 422 |
'intro' => __( 'The short form that asks the buyer for their name and e-mail address before payment starts. Most stores never need to touch this.', 'ebook-store' ), |
| 423 |
) |
| 424 |
); |
| 425 |
|
| 426 |
ebook_store_callout( |
| 427 |
sprintf( |
| 428 |
/* translators: 1: first_name field name, 2: last_name field name, 3: payer_email field name, 4: the CSS class "required". */ |
| 429 |
__( 'This box holds raw HTML. The fields named %1$s, %2$s and %3$s are the ones the plugin reads, so do not rename or remove them, and keep the class %4$s on any field a buyer must fill in. If you break the form, clear the box and save to fall back to the built-in version.', 'ebook-store' ), |
| 430 |
'<code>first_name</code>', |
| 431 |
'<code>last_name</code>', |
| 432 |
'<code>payer_email</code>', |
| 433 |
'<code>required</code>' |
| 434 |
), |
| 435 |
'warning', |
| 436 |
__( 'Editing this can stop checkout working.', 'ebook-store' ) |
| 437 |
); |
| 438 |
?> |
| 439 |
|
| 440 |
<div class="ebook-settings-field ebook-settings-field--wide" data-ebook-search="<?php echo esc_attr( __( 'Checkout form markup', 'ebook-store' ) . ' formContent' ); ?>"> |
| 441 |
<label for="formContent"><?php echo esc_html__( 'Form HTML', 'ebook-store' ); ?></label> |
| 442 |
<?php |
| 443 |
wp_editor( |
| 444 |
get_option( 'formContent', $op->formContent ), |
| 445 |
'formContent', |
| 446 |
array( |
| 447 |
'textarea_name' => 'formContent', |
| 448 |
'textarea_rows' => 12, |
| 449 |
) |
| 450 |
); |
| 451 |
?> |
| 452 |
<p class="description"><?php echo esc_html__( 'Use the "Text" tab of the editor when you edit this, so the HTML is not reformatted.', 'ebook-store' ); ?></p> |
| 453 |
</div> |
| 454 |
|
| 455 |
<?php |
| 456 |
ebook_store_section_close(); |
| 457 |
|
| 458 |
do_action( 'ebook_settings_page_extend' ); |
| 459 |
|