Changeset 3627752
- Timestamp:
- 07/29/2026 11:20:46 PM (3 months ago)
- Location:
- sell-ads
- Files:
-
- 1 deleted
- 18 edited
- 13 copied
-
tags/1.9.6 (copied) (copied from sell-ads/trunk )
-
tags/1.9.6/css/style.css (copied) (copied from sell-ads/trunk/css/style.css ) (1 diff)
-
tags/1.9.6/inc/ajax.php (modified) (1 diff)
-
tags/1.9.6/inc/campaign_fields.php (copied) (copied from sell-ads/trunk/inc/campaign_fields.php ) (16 diffs)
-
tags/1.9.6/inc/checkout.php (copied) (copied from sell-ads/trunk/inc/checkout.php ) (3 diffs)
-
tags/1.9.6/inc/connect.php (copied) (copied from sell-ads/trunk/inc/connect.php ) (2 diffs)
-
tags/1.9.6/inc/helper.php (modified) (4 diffs)
-
tags/1.9.6/inc/hooks.php (modified) (2 diffs)
-
tags/1.9.6/inc/notify.php (copied) (copied from sell-ads/trunk/inc/notify.php )
-
tags/1.9.6/inc/page/confirm.php (copied) (copied from sell-ads/trunk/inc/page/confirm.php ) (3 diffs)
-
tags/1.9.6/inc/page/img (deleted)
-
tags/1.9.6/inc/page/style.css (copied) (copied from sell-ads/trunk/inc/page/style.css ) (7 diffs)
-
tags/1.9.6/inc/page/wp-sap.js (copied) (copied from sell-ads/trunk/inc/page/wp-sap.js )
-
tags/1.9.6/inc/settings.php (copied) (copied from sell-ads/trunk/inc/settings.php ) (11 diffs)
-
tags/1.9.6/inc/shortcode.php (copied) (copied from sell-ads/trunk/inc/shortcode.php ) (3 diffs)
-
tags/1.9.6/inc/stripe.php (modified) (2 diffs)
-
tags/1.9.6/readme.txt (copied) (copied from sell-ads/trunk/readme.txt ) (4 diffs)
-
tags/1.9.6/wp-sap.php (copied) (copied from sell-ads/trunk/wp-sap.php ) (4 diffs)
-
trunk/css/style.css (modified) (1 diff)
-
trunk/inc/ajax.php (modified) (1 diff)
-
trunk/inc/campaign_fields.php (modified) (16 diffs)
-
trunk/inc/checkout.php (modified) (3 diffs)
-
trunk/inc/connect.php (modified) (2 diffs)
-
trunk/inc/helper.php (modified) (4 diffs)
-
trunk/inc/hooks.php (modified) (2 diffs)
-
trunk/inc/page/confirm.php (modified) (3 diffs)
-
trunk/inc/page/style.css (modified) (7 diffs)
-
trunk/inc/settings.php (modified) (11 diffs)
-
trunk/inc/shortcode.php (modified) (3 diffs)
-
trunk/inc/stripe.php (modified) (2 diffs)
-
trunk/readme.txt (modified) (4 diffs)
-
trunk/wp-sap.php (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
sell-ads/tags/1.9.6/css/style.css
r3626502 r3627752 26 26 } 27 27 28 /* Freistehende, abgerundete Karte auf hellem Grund (SS1) statt des frueheren 29 kantigen Vollbreiten-Bandes. Der Radius stand bis 1.8.2 per !important auf 0 30 und musste hier aktiv ueberschrieben werden - jetzt traegt die Box Ecken und 31 einen weichen Schatten selbst. width:100% bleibt: die Karte fuellt die Breite 32 ihres Widgets/Containers, hebt sich aber durch Radius und Schatten ab. */ 28 33 .wpsap_ads_plugin_ads_box { 29 34 width: 100%; 30 35 box-sizing: border-box; 31 background-color: var(--wpsap-canvas, #f0f1f2); 32 border-radius: 0 !important; 36 background-color: #F2F3F5; 37 /* border-radius: 14px; */ 38 /* box-shadow: var(--wpsap-shadow, 0 1px 3px rgba(0, 0, 0, .08)); */ 33 39 text-align: center; 34 40 display: flex; -
sell-ads/tags/1.9.6/inc/ajax.php
r3626067 r3627752 84 84 update_post_meta($order_id,'order_image',$data['url']); 85 85 update_post_meta($order_id,'order_url',$site_url); 86 // Attachment-ID mitfuehren, damit das Motiv beim Ablehnen/Kuendigen/ 87 // Ablaufen restlos aus der Mediathek entfernt werden kann 88 // (wpsap_delete_order_media() in inc/helper.php). 89 update_post_meta($order_id,'wpsap_order_image_id',$image); 86 90 } 87 91 else { -
sell-ads/tags/1.9.6/inc/campaign_fields.php
r3626502 r3627752 16 16 function wpsap_campaign_metaboxes_html(){ 17 17 global $post; 18 // Keine Prefill-Defaults: leere Felder bleiben leer, damit im Frontend nur 19 // erscheint, was der Betreiber aktiv eingetragen hat. 18 20 $campaign_title = get_post_meta($post->ID, "wpsap_campaign_title",true); 19 if(empty($campaign_title)){20 $campaign_title = 'This Advertising space is for sale';21 }22 21 23 22 $campaign_name = get_the_title($post->ID); … … 27 26 28 27 $button_text = get_post_meta($post->ID, "wpsap_button_text",true); 29 if(empty($button_text)){30 $button_text = 'Buy';31 }32 28 33 29 // Ohne dieses Feld schlug die Nonce-Pruefung beim Speichern immer fehl … … 53 49 <span class="tooltiptext">This title is used to advertise your ad space.</span> 54 50 </div> 55 <input type="text" name="wpsap_campaign_title" class="regular-text" value="<?php echo esc_attr($campaign_title); ?>" required>51 <input type="text" name="wpsap_campaign_title" class="regular-text" value="<?php echo esc_attr($campaign_title); ?>"> 56 52 </td> 57 53 </tr> … … 68 64 </tr> 69 65 66 <?php $currency = strtoupper(wpsap_stripe_currency()); ?> 70 67 <tr> 71 <td><h4>Monthly Price ( $)</h4></td>68 <td><h4>Monthly Price (<?php echo esc_html($currency); ?>)</h4></td> 72 69 <td> 73 70 <div class="tooltip"><span class="dashicons dashicons-info"></span> 74 <span class="tooltiptext">This is the monthly price in US dollarsfor which you want to rent out your ad space.</span>71 <span class="tooltiptext">This is the monthly price in <?php echo esc_html($currency); ?> for which you want to rent out your ad space.</span> 75 72 </div> 76 73 <input type="number" step="0.01" min="0" name="wpsap_campaign_price" class="regular-text" value="<?php echo esc_attr(get_post_meta($post->ID, "wpsap_campaign_price",true)); ?>" required> … … 194 191 $columns['title'] = __( 'Campaign', "wpsap"); 195 192 $columns['price'] = __( 'Price', "wpsap"); 196 193 // Info-Icon mit CSS-Tooltip: erklaert die zwei gezaehlten Ereignisse. Der 194 // native title-Tooltip erschien nicht zuverlaessig, deshalb dieselbe 195 // .tooltiptext-Mechanik wie in der Metabox. Das noetige CSS steht - auf die 196 // Liste gescoped - im admin_footer (wpsap_campaign_copy_field()). WordPress 197 // gibt das Spalten-Label als HTML aus, daher ohne eigenes Enqueue. 198 // Icon und Text stehen in getrennten Spans: nur das Icon traegt die 199 // dashicons-Klasse, sonst wuerde der Tooltip-Text in der Icon-Schrift 200 // gerendert. 201 $columns['clicks'] = __( 'Clicks', "wpsap") 202 . ' <span class="wpsap-th-tip" tabindex="0">' 203 . '<span class="dashicons dashicons-info"></span>' 204 . '<span class="wpsap-th-tiptext">' 205 . esc_html__('Total clicks for this ad slot: clicks on the “Buy” button (before the slot is sold) plus outbound clicks on the published ad.','wpsap_ads_plugin') 206 . '</span></span>'; 197 207 $columns['pdate'] = __( 'Date', "wpsap"); 198 208 $columns['php'] = __( 'PHP', "wpsap"); … … 211 221 echo esc_html(get_post_meta($post_id, "wpsap_campaign_price",true).' '.strtoupper(wpsap_stripe_currency())." per month"); 212 222 break; 223 case 'clicks' : 224 // Zaehler wird an zwei Stellen hochgezaehlt: beim /goto-Redirect 225 // (inc/hooks.php) und beim Buy-Button-Klick (wpsap_start_checkout, 226 // inc/checkout.php). 227 // Als Link auf die Kampagne ausgegeben, damit die Zahl - wie in der 228 // Vorlage - klickbar ist und in WP-Blau erscheint. 229 $clicks = (int) get_post_meta($post_id, "wpsap_click_count",true); 230 $edit_link = get_edit_post_link($post_id); 231 if($edit_link){ 232 echo '<a href="'.esc_url($edit_link).'">'.esc_html($clicks).'</a>'; 233 } else { 234 echo esc_html($clicks); 235 } 236 break; 213 237 case 'php' : 214 echo esc_html(wpsap_plugin_php_function($post_id)); 238 // Bewusst ohne esc_html(): wpsap_plugin_php_function() liefert das 239 // fertige Kopier-Feld und escapt seinen dynamischen Wert selbst. 240 echo wpsap_plugin_php_function($post_id); 215 241 break; 216 242 case 'shortcode' : 217 echo esc_html(wpsap_shortcode_input($post_id));243 echo wpsap_shortcode_input($post_id); 218 244 break; 219 245 … … 230 256 $columns['order'] = __( 'Order', "wpsap"); 231 257 $columns['campaign'] = __( 'Campaign', "wpsap"); 232 $columns['pdate'] = __( ' Date', "wpsap");258 $columns['pdate'] = __( 'Order Date', "wpsap"); 233 259 $columns['status'] = __( 'Status', "wpsap"); 234 $columns['billing'] = __( 'Billing', "wpsap");235 260 $columns['resources'] = __( 'Resources', "wpsap"); 236 261 $columns['link'] = __( 'Link', "wpsap"); … … 251 276 // entstanden sind - die Spalte Total zeigt trotzdem einen Betrag. 252 277 if(get_post_meta($post_id,'wpsap_test_order',true) === 'yes'){ 253 echo '<br/><small><span style="color:#996800;">'.esc_html__('Test order — not paid','wpsap_ads_plugin').'</span></small>';278 echo '<br/><small><span style="color:#996800;">'.esc_html__('Test order','wpsap_ads_plugin').'</span></small>'; 254 279 } 255 280 break; … … 268 293 $final_dates = wpsap_order_days_left($post_id); 269 294 if($final_dates > 0){ 295 // Ablaufdatum = Bestelldatum + 14 Tage, dieselbe Frist wie 296 // in wpsap_order_days_left(). 297 $placed = get_post_time('U',true,$post_id); 298 $expires = $placed ? $placed + 14 * DAY_IN_SECONDS : time() + $final_dates * DAY_IN_SECONDS; 270 299 echo '<strong>Pending</strong>'; 271 echo '<br/><small><span>( '.esc_html($final_dates).' days until expiration)</span></small>';300 echo '<br/><small><span>(Request expires on '.esc_html(wp_date(get_option('date_format'),$expires)).')</span></small>'; 272 301 } 273 302 else { … … 291 320 echo "<span style='color:#ff0000;'>Rejected</span>"; 292 321 } 322 else if($current_status == 'expired'){ 323 $on = (int) get_post_meta($post_id, "wpsap_expired_on",true); 324 if(!$on){ 325 $placed = get_post_time('U',true,$post_id); 326 $on = $placed ? $placed + 14 * DAY_IN_SECONDS : 0; 327 } 328 echo "<span style='color:#ff0000;'>Expired</span>"; 329 if($on){ 330 echo "<br/><small>(on ".esc_html(wp_date(get_option('date_format'),$on)).")</small>"; 331 } 332 } 293 333 else { 294 334 echo esc_html($current_status); … … 297 337 } 298 338 break; 299 case 'billing' :300 echo esc_html(get_post_meta($post_id, "order_email",true));301 break;302 339 case 'resources' : 303 $url = get_post_meta($post_id, "order_url",true); 304 echo '<a target="_blank" href="'.esc_url(get_post_meta($post_id, "order_image",true)).'"><img style="max-width:120px;" src="'.esc_url(get_post_meta($post_id, "order_image",true)).'"></a>'; 340 // Nach Reject/Cancel/Expired ist das Motiv geloescht (order_image 341 // leer) - dann kein kaputtes <img> ausgeben. 342 $image = get_post_meta($post_id, "order_image",true); 343 if($image){ 344 echo '<a target="_blank" href="'.esc_url($image).'"><img style="max-width:120px;" src="'.esc_url($image).'"></a>'; 345 } else { 346 echo '—'; 347 } 305 348 break; 306 349 case 'link' : 307 350 $url = get_post_meta($post_id, "order_url",true); 308 echo '<a href="'.esc_url($url).'">'.esc_url($url).'</a>'; 351 if($url){ 352 echo '<a href="'.esc_url($url).'">'.esc_url($url).'</a>'; 353 } else { 354 echo '—'; 355 } 309 356 break; 310 357 case 'total' : 311 358 $status = get_post_meta($post_id, "wpsap_order_status",true); 312 359 if($status == "accepted"){ 313 echo "<small>You have confirmed the advertising partnership . Now you need to publish the advertisement. Make sure that the ad is displayed correctly and that the product link works. If there are any errors, you should contact the buyer immediately. If the buyer does not cancel within the next 14 days, the first transaction will be executed. The monthly payment will remain until someone cancels.</small>";360 echo "<small>You have confirmed the advertising partnership, and the first payment was charged when you accepted. Please publish the advertisement now: make sure it displays correctly and that the product link works, and contact the buyer right away if anything is wrong. The monthly payment continues until the subscription is cancelled — either by you here, or by the buyer from their own Stripe billing portal, which they can reach through the link on their order confirmation page.</small>"; 314 361 } 315 362 else { … … 320 367 $currency = wpsap_stripe_currency(); 321 368 } 322 echo esc_html(number_format_i18n($total,2).' '.strtoupper($currency) );369 echo esc_html(number_format_i18n($total,2).' '.strtoupper($currency).' per month'); 323 370 } 324 371 break; … … 334 381 echo 'This subscription was cancelled by the buyer.'; 335 382 } 383 elseif($status == 'expired'){ 384 // Nach 14 Tagen ohne Annahme ueber wpsap_expire_ads() beendet - 385 // das Abo stand noch im Trial, es wurde also nichts berechnet. 386 echo 'This request expired unanswered. No payment was charged.'; 387 } 336 388 elseif($status != "accepted" && $status != "published"){ 337 echo '<a href="'.esc_url(wpsap_order_action_url(' reject',$post_id)).'" class="button reject_ads">Reject</a> | <a href="'.esc_url(wpsap_order_action_url('accept',$post_id)).'" class="button accept_ads">Accept</a>';389 echo '<a href="'.esc_url(wpsap_order_action_url('accept',$post_id)).'" class="button button-primary accept_ads">Accept</a> | <a href="'.esc_url(wpsap_order_action_url('reject',$post_id)).'" class="button reject_ads">Reject</a>'; 338 390 } 339 391 … … 343 395 } 344 396 else { 345 echo '<a href="'.esc_url(wpsap_order_action_url('accept',$post_id)).'" class="button button-primaryaccept_ads">Unpublish</a> | <a href="'.esc_url(wpsap_order_action_url('reject',$post_id)).'" class="button reject_ads">Cancel</a>';397 echo '<a href="'.esc_url(wpsap_order_action_url('accept',$post_id)).'" class="button accept_ads">Unpublish</a> | <a href="'.esc_url(wpsap_order_action_url('reject',$post_id)).'" class="button reject_ads">Cancel</a>'; 346 398 } 347 399 } … … 356 408 if(isset($_GET['post_type'])){ 357 409 if(sanitize_text_field($_GET['post_type']) == 'ads_order'){ 358 ?> 410 ?> 359 411 <style> 360 412 .tablenav.top { … … 363 415 </style> 364 416 365 <?php 366 } 367 } 417 <?php 418 } 419 } 420 } 421 422 423 // Kopier-Verhalten und Optik der PHP-/Shortcode-Felder in der Kampagnenliste. 424 add_action('admin_footer','wpsap_campaign_copy_field'); 425 function wpsap_campaign_copy_field(){ 426 if(!isset($_GET['post_type']) || sanitize_text_field(wp_unslash($_GET['post_type'])) !== 'ads_campaign'){ 427 return; 428 } 429 ?> 430 <style> 431 .wpsap-copy { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; } 432 /* Weisses, schreibgeschuetztes Feld mit dezentem Rahmen - wie in der Vorlage 433 (kein grauer Fuellton). Erhoehte Spezifitaet (span + input.klasse), weil WP 434 readonly-Felder sonst grau einfaerbt (input[readonly]). */ 435 .wpsap-copy input.wpsap-copy__input { width: 150px; max-width: 100%; background: #fff; color: #3c434a; } 436 /* Randloses Kopier-Icon statt umrandetem Button: die Vorlage zeigt nur das 437 schlichte Dokument-Symbol ohne Button-Rahmen (die WP-.button-Klasse ist im 438 Markup deshalb entfernt). */ 439 .wpsap-copy__btn { display: inline-flex; align-items: center; justify-content: center; background: none; border: none; box-shadow: none; outline: none; padding: 0 2px; min-height: 0; color: #50575e; cursor: pointer; } 440 .wpsap-copy__btn:hover { color: #2271b1; background: none; box-shadow: none; } 441 .wpsap-copy__btn:focus { background: none; box-shadow: none; outline: none; } 442 .wpsap-copy__btn .dashicons { width: 18px; height: 18px; font-size: 18px; } 443 .wpsap-copy__btn.is-copied { color: #46b450; } 444 445 /* Info-Tooltip im Spaltenkopf "Clicks". Aufbau wie die Metabox-Tooltips, aber 446 eigene Klassen, damit nichts mit anderen Admin-Styles kollidiert. */ 447 .wpsap-th-tip { position: relative; display: inline-flex; align-items: center; vertical-align: middle; margin-top: -2px; cursor: help; color: #787c82; } 448 .wpsap-th-tip .dashicons-info { font-size: 16px; width: 16px; height: 16px; line-height: 16px; } 449 .wpsap-th-tip .wpsap-th-tiptext { 450 visibility: hidden; opacity: 0; transition: opacity .1s ease; 451 position: absolute; z-index: 100; top: 150%; left: 50%; transform: translateX(-50%); 452 width: 240px; padding: 8px 10px; border-radius: 4px; 453 background: #1d2327; color: #fff; 454 font: 400 12px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; 455 text-align: left; white-space: normal; font-weight: 400; text-transform: none; 456 } 457 .wpsap-th-tip:hover .wpsap-th-tiptext, 458 .wpsap-th-tip:focus .wpsap-th-tiptext, 459 .wpsap-th-tip:focus-within .wpsap-th-tiptext { visibility: visible; opacity: 1; } 460 </style> 461 <script> 462 jQuery(function($){ 463 $(document).on('click','.wpsap-copy__btn',function(){ 464 var $btn = $(this); 465 var $input = $btn.closest('.wpsap-copy').find('.wpsap-copy__input'); 466 var text = $input.val(); 467 468 var done = function(){ 469 $btn.addClass('is-copied'); 470 setTimeout(function(){ $btn.removeClass('is-copied'); },1200); 471 }; 472 473 if(navigator.clipboard && navigator.clipboard.writeText){ 474 navigator.clipboard.writeText(text).then(done, function(){ 475 $input.trigger('select'); document.execCommand('copy'); done(); 476 }); 477 } else { 478 $input.trigger('select'); document.execCommand('copy'); done(); 479 } 480 }); 481 }); 482 </script> 483 <?php 484 } 485 486 487 // Doppelte Bestaetigung fuer Reject/Cancel: beide Buttons loesen dieselbe 488 // irreversible Aktion aus (Stripe-Abo kuendigen). Ein eigenes Modal faengt den 489 // Klick ab und verlangt, dass der Betreiber das Aktionswort tippt, bevor der 490 // bereits nonce-gesicherte Link geoeffnet wird. Reiner Frontend-Schutz - der 491 // Serverpfad in wpsap_job_status() bleibt unveraendert. 492 add_action('admin_footer','wpsap_order_reject_confirm'); 493 function wpsap_order_reject_confirm(){ 494 if(!isset($_GET['post_type']) || sanitize_text_field(wp_unslash($_GET['post_type'])) !== 'ads_order'){ 495 return; 496 } 497 ?> 498 <style> 499 #wpsap-reject-modal { position: fixed; inset: 0; z-index: 100000; display: none; } 500 #wpsap-reject-modal.is-open { display: block; } 501 #wpsap-reject-modal .wpsap-reject-backdrop { position: absolute; inset: 0; background: rgba(0,0,0,0.5); } 502 #wpsap-reject-modal .wpsap-reject-box { position: relative; max-width: 420px; margin: 12vh auto 0; background: #fff; border-radius: 4px; box-shadow: 0 6px 30px rgba(0,0,0,0.3); padding: 24px; } 503 #wpsap-reject-modal .wpsap-reject-title { display: flex; align-items: center; gap: 8px; margin: 0 0 12px; font-size: 18px; font-weight: 600; color: #b32d2e; } 504 #wpsap-reject-modal .wpsap-reject-text { margin: 0 0 16px; color: #3c434a; line-height: 1.5; } 505 #wpsap-reject-modal .wpsap-reject-label { display: block; margin: 0 0 6px; font-weight: 600; color: #3c434a; } 506 #wpsap-reject-modal .wpsap-reject-input { width: 100%; box-sizing: border-box; margin: 0 0 16px; } 507 #wpsap-reject-modal .wpsap-reject-actions { display: flex; justify-content: flex-end; gap: 8px; } 508 #wpsap-reject-modal .wpsap-reject-confirm { background: #b32d2e; border-color: #b32d2e; color: #fff; } 509 #wpsap-reject-modal .wpsap-reject-confirm:hover:not(:disabled) { background: #9e2423; border-color: #9e2423; color: #fff; } 510 #wpsap-reject-modal .wpsap-reject-confirm:disabled { opacity: 0.5; cursor: not-allowed; } 511 </style> 512 <div id="wpsap-reject-modal" role="dialog" aria-modal="true" aria-labelledby="wpsap-reject-title"> 513 <div class="wpsap-reject-backdrop"></div> 514 <div class="wpsap-reject-box"> 515 <h2 id="wpsap-reject-title" class="wpsap-reject-title"><span class="dashicons dashicons-warning"></span><span class="wpsap-reject-heading">Reject this ad?</span></h2> 516 <p class="wpsap-reject-text">This permanently cancels the buyer’s active Stripe subscription. This action cannot be undone.</p> 517 <label class="wpsap-reject-label" for="wpsap-reject-word">Type <strong class="wpsap-reject-word">REJECT</strong> to confirm:</label> 518 <input type="text" id="wpsap-reject-word" class="wpsap-reject-input regular-text" autocomplete="off" autocapitalize="characters" spellcheck="false"> 519 <div class="wpsap-reject-actions"> 520 <button type="button" class="button wpsap-reject-cancel">Close</button> 521 <button type="button" class="button wpsap-reject-confirm" disabled>Confirm</button> 522 </div> 523 </div> 524 </div> 525 <script> 526 jQuery(function($){ 527 var $modal = $('#wpsap-reject-modal'); 528 var $input = $('#wpsap-reject-word'); 529 var $confirm = $modal.find('.wpsap-reject-confirm'); 530 var targetHref = ''; 531 var expectedWord = 'REJECT'; 532 533 function closeModal(){ 534 $modal.removeClass('is-open'); 535 targetHref = ''; 536 $input.val(''); 537 $confirm.prop('disabled', true); 538 } 539 540 // Reject und Cancel teilen die Klasse .reject_ads; der Wortlaut folgt dem 541 // Text des tatsaechlich geklickten Links (Reject oder Cancel). 542 $(document).on('click','.reject_ads',function(e){ 543 e.preventDefault(); 544 targetHref = $(this).attr('href'); 545 var label = $.trim($(this).text()) || 'Reject'; 546 expectedWord = label.toUpperCase(); 547 $modal.find('.wpsap-reject-heading').text(label + ' this ad?'); 548 $modal.find('.wpsap-reject-word').text(expectedWord); 549 $input.val(''); 550 $confirm.prop('disabled', true); 551 $modal.addClass('is-open'); 552 $input.trigger('focus'); 553 }); 554 555 $input.on('input',function(){ 556 $confirm.prop('disabled', $.trim($input.val()).toUpperCase() !== expectedWord); 557 }); 558 559 $confirm.on('click',function(){ 560 if($confirm.prop('disabled') || !targetHref){ return; } 561 window.location.href = targetHref; 562 }); 563 564 $modal.find('.wpsap-reject-cancel, .wpsap-reject-backdrop').on('click', closeModal); 565 566 $(document).on('keydown',function(e){ 567 if(e.key === 'Escape' && $modal.hasClass('is-open')){ closeModal(); } 568 }); 569 }); 570 </script> 571 <?php 368 572 } 369 573 -
sell-ads/tags/1.9.6/inc/checkout.php
r3626502 r3627752 183 183 } 184 184 185 // Buy-Button-Klick zaehlen - derselbe Zaehler wie der /goto-Redirect 186 // (inc/hooks.php), damit die Spalte "Clicks" beide Ereignisse summiert. 187 // Selbst-Klicks eingeloggter Redakteure verfaelschen die Statistik nicht. 188 if(get_post_type($campaign_id) === 'ads_campaign' 189 && !(is_user_logged_in() && current_user_can('edit_posts'))){ 190 $count = (int) get_post_meta($campaign_id,'wpsap_click_count',true); 191 update_post_meta($campaign_id,'wpsap_click_count',$count + 1); 192 } 193 185 194 // Testmodus: die Zahlungsseite entfaellt ersatzlos. Die Bestellung 186 195 // entsteht hier statt aus einer bezahlten Stripe-Session, danach geht es … … 326 335 327 336 /** 328 * Taeglicher Lauf: Bestellungen, die 14 Tage unbeantwortet blieben, 329 * werden abgelehnt und das Abo beendet. Frueher passierte das mitten330 * im Rendern der Bestellliste.337 * Taeglicher Lauf: Bestellungen, die 14 Tage unbeantwortet blieben, laufen ab 338 * (Status "expired") und das Abo wird beendet - weil es noch im Trial steht, 339 * ohne Belastung. Frueher passierte das mitten im Rendern der Bestellliste. 331 340 */ 332 341 add_action('wpsap_expire_pending_orders','wpsap_expire_pending_orders'); … … 348 357 foreach($orders as $order_id){ 349 358 if(wpsap_order_days_left($order_id) <= 0){ 350 wpsap_ reject_ads($order_id);359 wpsap_expire_ads($order_id); 351 360 } 352 361 } -
sell-ads/tags/1.9.6/inc/connect.php
r3626502 r3627752 20 20 21 21 function wpsap_payment_mode(){ 22 $mode = get_option('wpsap_payment_mode',' own_key');23 return in_array($mode,array('own_key','connect'),true) ? $mode : ' own_key';22 $mode = get_option('wpsap_payment_mode','connect'); 23 return in_array($mode,array('own_key','connect'),true) ? $mode : 'connect'; 24 24 } 25 25 … … 326 326 } 327 327 328 function wpsap_connect_end_trial($subscription_id){ 329 return wpsap_connect_request('POST','v1/subscription/end-trial',array('subscription_id' => $subscription_id)); 330 } 331 328 332 function wpsap_connect_portal_url($customer_id,$return_url){ 329 333 $session = wpsap_connect_request('POST','v1/portal',array( -
sell-ads/tags/1.9.6/inc/helper.php
r3626067 r3627752 2 2 if ( ! defined( 'ABSPATH' ) ) exit; 3 3 4 /** 5 * Baut das kopierbare Feld fuer die PHP-Einbindung einer Kampagne. 6 * 7 * Rueckgabe ist fertiges HTML und wird in der Spalte direkt ausgegeben - 8 * frueher lag ein esc_html() darum, das aus dem <input> sichtbaren Rohtext 9 * machte. Escapt wird deshalb nur noch der dynamische Wert selbst. 10 */ 4 11 function wpsap_plugin_php_function($content){ 5 6 $html = '<input type="text" readonly value="<?php echo wpsap_show('.esc_attr($content).'); ?>">'; 7 return $html; 8 12 $id = absint($content); 13 $value = '<?php echo wpsap_show('.$id.'); ?>'; 14 return wpsap_copy_field($value); 9 15 } 10 16 17 /** 18 * Baut das kopierbare Feld fuer die Shortcode-Einbindung einer Kampagne. 19 */ 11 20 function wpsap_shortcode_input($content){ 12 $html = '<input type="text" readonly value="[wpsap_ads id='.esc_attr($content).']">'; 13 return $html; 21 $id = absint($content); 22 $value = '[wpsap_ads id='.$id.']'; 23 return wpsap_copy_field($value); 24 } 25 26 /** 27 * Gemeinsames Markup fuer die Kopier-Felder der Kampagnenliste: ein 28 * schreibgeschuetztes Eingabefeld mit Betrag daneben ein Kopier-Button. 29 * Der zugehoerige Klick-Handler liegt im admin_footer der Liste 30 * (inc/campaign_fields.php). 31 */ 32 function wpsap_copy_field($value){ 33 return '<span class="wpsap-copy">' 34 .'<input type="text" class="wpsap-copy__input" readonly value="'.esc_attr($value).'">' 35 .'<button type="button" class="wpsap-copy__btn" title="'.esc_attr__('Copy','wpsap_ads_plugin').'">' 36 .'<span class="dashicons dashicons-admin-page"></span>' 37 .'</button>' 38 .'</span>'; 14 39 } 15 40 … … 43 68 44 69 /** 70 * Entfernt Motiv und Ziellink einer endgueltig toten Bestellung restlos: 71 * das Attachment aus der Mediathek (Datei inkl. resized Varianten, ohne 72 * Papierkorb) sowie die Meta order_image/order_url. Jedes Motiv gehoert zu 73 * genau einer Bestellung, deshalb ist das harte Loeschen unbedenklich. 74 * 75 * Die Attachment-ID steht seit dem Upload in wpsap_order_image_id; fuer 76 * Bestandsbestellungen ohne dieses Meta wird sie aus der gespeicherten URL 77 * aufgeloest. 78 */ 79 function wpsap_delete_order_media($order_id){ 80 $attachment_id = (int) get_post_meta($order_id,'wpsap_order_image_id',true); 81 if(!$attachment_id){ 82 $image_url = get_post_meta($order_id,'order_image',true); 83 if($image_url){ 84 $attachment_id = attachment_url_to_postid($image_url); 85 } 86 } 87 88 if($attachment_id && get_post_type($attachment_id) === 'attachment'){ 89 wp_delete_attachment($attachment_id,true); 90 } 91 92 delete_post_meta($order_id,'order_image'); 93 delete_post_meta($order_id,'order_url'); 94 delete_post_meta($order_id,'wpsap_order_image_id'); 95 } 96 97 /** 45 98 * Ablehnen heisst: das Abo bei Stripe beenden. Der lokale Status wird erst 46 99 * danach gesetzt - frueher lief es umgekehrt, wodurch Plugin und Stripe … … 62 115 ) ); 63 116 117 // Erst nach dem gesicherten Statuswechsel: Motiv und Link sind jetzt tot. 118 wpsap_delete_order_media($order_id); 119 120 return true; 121 } 122 123 /** 124 * Ablauf einer unbeantworteten Bestellung nach 14 Tagen. Wie das Ablehnen 125 * beendet es das Abo bei Stripe - weil das noch im Trial steht, entsteht dabei 126 * keine Rechnung, der Kaeufer wird also nicht belastet. Getrennt von 127 * wpsap_reject_ads(), damit der Zustand in der Liste als "Expired" (statt 128 * "Rejected") erkennbar bleibt und das Ablaufdatum festgehalten wird. 129 */ 130 function wpsap_expire_ads($order_id){ 131 $subscription_id = get_post_meta($order_id,'wpsap_subscription_id',true); 132 if($subscription_id){ 133 $result = wpsap_stripe_cancel_subscription($subscription_id); 134 if(is_wp_error($result)){ 135 return $result; 136 } 137 } 138 139 // Ablaufdatum = Bestelldatum + 14 Tage, dieselbe Frist wie in 140 // wpsap_order_days_left(). Festgehalten, damit die Liste "Expired on <Tag>" 141 // zeigen kann, ohne es jedes Mal neu herzuleiten. 142 $placed = get_post_time('U',true,$order_id); 143 $expires = $placed ? $placed + 14 * DAY_IN_SECONDS : time(); 144 update_post_meta($order_id,'wpsap_expired_on',$expires); 145 146 update_post_meta($order_id,"wpsap_order_status",'expired'); 147 wp_update_post( array( 148 'ID' => $order_id, 149 'post_status' => 'rejected', 150 ) ); 151 152 // Wie beim Ablehnen: Motiv und Link sind mit dem Ablauf tot. 153 wpsap_delete_order_media($order_id); 154 64 155 return true; 65 156 } … … 80 171 return new WP_Error('wpsap_subscription_gone',__('This subscription is no longer active at Stripe.','wpsap_ads_plugin')); 81 172 } 173 174 // Erst mit der Annahme wird belastet: das Abo lief bis hierher im Trial 175 // (siehe wpsap_stripe_build_checkout). Das Beenden des Trials stellt die 176 // erste Rechnung sofort aus. 177 $charged = wpsap_stripe_end_trial($subscription_id); 178 if(is_wp_error($charged)){ 179 return $charged; 180 } 82 181 } 83 182 -
sell-ads/tags/1.9.6/inc/hooks.php
r3626067 r3627752 144 144 } 145 145 146 $order_date = get_the_date( 'l F j, Y',$order_id); 147 $expected_date = date('l F j, Y',strtotime($order_date."+ 7days")); 148 146 // Die Datumsangaben der Bestaetigungstabelle berechnet confirm.php 147 // selbst aus dem Bestellzeitpunkt - hier ist nichts vorzubereiten. 149 148 require WPSAP_Plugin_Path.'inc/page/confirm.php'; 150 149 die(); … … 229 228 // neu registriert - die alte Registrierung ueberschrieb ihn global fuer 230 229 // alle Post-Types. 230 231 232 /* -------------------------------------------------------------------------- 233 * Klick-Tracking ueber /goto/<slug> 234 * 235 * Die veroeffentlichte Anzeige verlinkt nicht mehr direkt auf die Zielseite, 236 * sondern ueber diesen Endpoint (inc/shortcode.php). Er zaehlt den Klick auf 237 * der Kampagne (wpsap_click_count) und leitet dann zur Zielseite weiter. Der 238 * Zaehler erscheint in der Spalte "Clicks" der Kampagnenliste. 239 * ------------------------------------------------------------------------- */ 240 241 add_filter('query_vars','wpsap_goto_query_var'); 242 function wpsap_goto_query_var($vars){ 243 $vars[] = 'wpsap_goto'; 244 return $vars; 245 } 246 247 add_action('init','wpsap_goto_rewrite'); 248 function wpsap_goto_rewrite(){ 249 add_rewrite_rule('^goto/([^/]+)/?$','index.php?wpsap_goto=$matches[1]','top'); 250 251 // Beim reinen Plugin-Update laeuft der Aktivierungshook nicht - ohne 252 // diesen Guard griffe die Rewrite-Rule auf cybie.de erst nach manuellem 253 // Neu-Speichern der Permalinks. Der Flush erfolgt genau einmal je Version. 254 if(get_option('wpsap_rewrite_version') !== WPSAP_Version){ 255 flush_rewrite_rules(false); 256 update_option('wpsap_rewrite_version',WPSAP_Version); 257 } 258 } 259 260 add_action('template_redirect','wpsap_handle_goto'); 261 function wpsap_handle_goto(){ 262 $slug = get_query_var('wpsap_goto'); 263 if($slug === '' || $slug === null){ 264 return; 265 } 266 267 $home = home_url('/'); 268 269 // Slug -> Kampagne. Numerischer Wert wird als ID behandelt, sonst ueber 270 // den post_name aufgeloest. Der CPT ist nicht oeffentlich, get_page_by_path 271 // findet ihn trotzdem, weil der Post-Type explizit uebergeben wird. 272 $campaign = null; 273 if(ctype_digit((string) $slug)){ 274 $maybe = get_post(absint($slug)); 275 if($maybe && $maybe->post_type === 'ads_campaign'){ 276 $campaign = $maybe; 277 } 278 } 279 if(!$campaign){ 280 $campaign = get_page_by_path(sanitize_title($slug),OBJECT,'ads_campaign'); 281 } 282 283 if(!$campaign){ 284 nocache_headers(); 285 wp_redirect($home,302); 286 exit; 287 } 288 289 // Zielseite = URL der aktuell veroeffentlichten Anzeige dieses Slots. 290 $target = ''; 291 foreach(wpsap_get_active_ads($campaign->ID) as $ad){ 292 $url = get_post_meta($ad->ID,'order_url',true); 293 if(!empty($url)){ 294 $target = $url; 295 break; 296 } 297 } 298 299 if(empty($target)){ 300 nocache_headers(); 301 wp_redirect($home,302); 302 exit; 303 } 304 305 // Selbst-Klicks von Redakteuren verfaelschen die Statistik nicht. 306 if(!(is_user_logged_in() && current_user_can('edit_posts'))){ 307 $count = (int) get_post_meta($campaign->ID,'wpsap_click_count',true); 308 update_post_meta($campaign->ID,'wpsap_click_count',$count + 1); 309 } 310 311 nocache_headers(); 312 // Ziel ist eine fremde Domain - wp_safe_redirect() wuerde das blocken. 313 wp_redirect(esc_url_raw($target),302); 314 exit; 315 } -
sell-ads/tags/1.9.6/inc/page/confirm.php
r3626502 r3627752 43 43 // Fuer die Seitenspalte: beide Zahlungswege legen diese Felder an - 44 44 // wpsap_sync_order_from_session() ebenso wie wpsap_create_test_order(). 45 $wpsap_place_id = (int) get_post_meta($order_id,'wpsap_place_id',true);46 $wpsap_campaign_label = '';47 if($wpsap_place_id){48 $wpsap_campaign_label = (string) get_post_meta($wpsap_place_id,'wpsap_campaign_title',true);49 if($wpsap_campaign_label === ''){50 $wpsap_campaign_label = (string) get_the_title($wpsap_place_id);51 }52 }53 54 45 $wpsap_price_label = ''; 55 46 $wpsap_order_total = (int) get_post_meta($order_id,'order_total',true); … … 58 49 $wpsap_price_label = number_format_i18n($wpsap_order_total / 100,2).' '.strtoupper((string) get_post_meta($order_id,'wpsap_currency',true)); 59 50 } 51 52 // Datumsangaben der Bestaetigungstabelle. Bezugspunkt ist der Zeitpunkt der 53 // Bestellung; wp_date() wendet die WP-Zeitzone an. Der Kaeufer-Flow ist 54 // durchgaengig englisch, deshalb erzwingt switch_to_locale('en_US') englische 55 // Monatsnamen auch auf einer de_DE-Site. Das Billing-Datum ist eine 56 // Anzeige-Schaetzung fuer den Kaeufer (Prueffrist bis 14 Tage + ein Abo-Monat) - 57 // Stripe bucht im Abo technisch bereits beim Checkout. 58 $wpsap_order_ts = get_post_timestamp($order_id); 59 $wpsap_switched_locale = switch_to_locale('en_US'); 60 $wpsap_submitted_date = $wpsap_order_ts ? wp_date('F j, Y',$wpsap_order_ts) : ''; 61 $wpsap_billing_date = $wpsap_order_ts ? wp_date('F j, Y',strtotime('+14 days +1 month',$wpsap_order_ts)) : ''; 62 if($wpsap_switched_locale){ restore_previous_locale(); } 60 63 61 64 // Solange Bild oder Link fehlen, steht der Kaeufer noch im Upload-Schritt. … … 85 88 <?php } ?> 86 89 87 <div class="wpsap-flow__grid"> 88 89 <aside class="wpsap-flow__aside"> 90 <div class="wpsap-flow__site"><?php echo esc_html(get_bloginfo('name')); ?></div> 91 92 <?php if($wpsap_campaign_label !== '' || $wpsap_price_label !== ''){ ?> 93 <div class="wpsap-flow__facts"> 94 <?php if($wpsap_campaign_label !== ''){ ?> 95 <div class="wpsap-flow__fact"> 96 <span class="wpsap-flow__fact-label"><?php esc_html_e('Ad space','wpsap_ads_plugin'); ?></span> 97 <span class="wpsap-flow__fact-value"><?php echo esc_html($wpsap_campaign_label); ?></span> 98 </div> 99 <?php } ?> 100 <?php if($wpsap_price_label !== ''){ ?> 101 <div class="wpsap-flow__fact"> 102 <span class="wpsap-flow__fact-label"><?php esc_html_e('Per month','wpsap_ads_plugin'); ?></span> 103 <span class="wpsap-flow__fact-value"><?php echo esc_html($wpsap_price_label); ?></span> 104 </div> 105 <?php } ?> 106 </div> 90 <?php /* Schritt 1: Upload - einspaltig zentriert. Bewusst NICHT im 91 Zwei-Spalten-Grid: die Aside gehoert erst auf die Bestaetigung. 92 Sichtbar bzw. verborgen nur ueber display:none - der gezeigte 93 Zustand kommt aus dem Stylesheet, damit wp-sap.js ihn per 94 .hide()/.show() korrekt umschalten kann. */ ?> 95 <section class="upload_ads_area" <?php if($wpsap_step_done){ echo 'style="display:none"'; } ?>> 96 <div class="wpsap-single"> 97 98 <h1 class="wpsap-step__title">Upload your Ad</h1> 99 100 <p class="wpsap-step__lead">Attention: Make sure that you upload your desired advertising image (JPG, PNG, GIF) in the preferred resolution (up to max. 10 MB) and add the correct link to your offer.</p> 101 102 <?php if(trim($note_on_upload_page) !== ''){ ?> 103 <div class="wpsap-note"><?php echo esc_html($note_on_upload_page); ?></div> 107 104 <?php } ?> 108 105 109 <?php if(trim($note_on_thanks_page) !== ''){ ?> 110 <div class="wpsap-flow__aside-note"><?php echo esc_html($note_on_thanks_page); ?></div> 111 <?php } ?> 112 113 <p class="wpsap-flow__copyright">Copyright <?php echo esc_html(get_bloginfo('name')); ?></p> 114 </aside> 115 116 <div class="wpsap-flow__main"> 117 118 <section class="upload_ads_area" style="<?php echo $wpsap_step_done ? 'display:none' : 'display:block'; ?>"> 119 120 <h1 class="wpsap-step__title">Upload your Ad</h1> 121 <p class="wpsap-step__lead">Attention: Make sure that you upload your desired advertising image (JPG, PNG, GIF) in the preferred resolution (up to max. 10 MB) and add the correct link to your offer.</p> 122 123 <?php if(trim($note_on_upload_page) !== ''){ ?> 124 <div class="wpsap-note"><?php echo esc_html($note_on_upload_page); ?></div> 125 <?php } ?> 126 127 <?php /* Nimmt die Meldungen auf, fuer die wp-sap.js bis 1.8.0 128 alert() aufrief. */ ?> 129 <div class="wpsap-alert" id="wpsap_form_error" role="alert"></div> 130 131 <form action="" id="wp_sap_form" method="post" enctype="multipart/form-data" class="wpsap-card"> 132 <div class="file-area"> 133 <input type="hidden" name="action" value="wpsap_upload_image"> 134 <input type="hidden" name="security" id="wpsap_security" value=""> 135 <?php /* Die Bestellung wird serverseitig ueber die Session-ID 136 aufgeloest. Eine mitgeschickte order_id waere im Browser 137 frei aenderbar. */ ?> 138 <input type="hidden" name="session" value="<?php echo esc_attr($session_id); ?>"> 139 <input type="file" name="image" id="images" accept="image/*" required="required"> 140 <div class="file-dummy"> 141 <?php if($image_uploaded){ ?> 142 <div class="default"> 143 <img src="<?php echo esc_url($image_uploaded); ?>" alt=""> 144 <h6>Click on the image to change it</h6> 145 </div> 146 <?php } else { ?> 147 <div class="default"> 148 <span class="wpsap-drop__icon" aria-hidden="true"> 149 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" focusable="false"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><path d="M21 15l-5-5L5 21"/></svg> 150 </span> 151 <h6>Drop image here or click to upload</h6> 152 </div> 153 <?php } ?> 154 <div class="success" id="image_uploaded_area"> 155 <h5>Image Uploading....</h5> 156 </div> 106 <?php /* Nimmt die Meldungen auf, fuer die wp-sap.js bis 1.8.0 107 alert() aufrief. */ ?> 108 <div class="wpsap-alert" id="wpsap_form_error" role="alert"></div> 109 110 <form action="" id="wp_sap_form" method="post" enctype="multipart/form-data" class="wpsap-card"> 111 <div class="file-area"> 112 <input type="hidden" name="action" value="wpsap_upload_image"> 113 <input type="hidden" name="security" id="wpsap_security" value=""> 114 <?php /* Die Bestellung wird serverseitig ueber die Session-ID 115 aufgeloest. Eine mitgeschickte order_id waere im Browser 116 frei aenderbar. */ ?> 117 <input type="hidden" name="session" value="<?php echo esc_attr($session_id); ?>"> 118 <input type="file" name="image" id="images" accept="image/*" required="required"> 119 <div class="file-dummy"> 120 <?php if($image_uploaded){ ?> 121 <div class="default"> 122 <img src="<?php echo esc_url($image_uploaded); ?>" alt=""> 123 <h6>Click on the image to change it</h6> 124 </div> 125 <?php } else { ?> 126 <div class="default"> 127 <span class="wpsap-drop__icon" aria-hidden="true"> 128 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" focusable="false"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><path d="M21 15l-5-5L5 21"/></svg> 129 </span> 130 <h6>Drop image here or click to upload</h6> 131 </div> 132 <?php } ?> 133 <div class="success" id="image_uploaded_area"> 134 <h5>Image Uploading....</h5> 157 135 </div> 158 136 </div> 159 160 <div class="wpsap-field"> 161 <input type="submit" value="Upload image" id="hidden_upload_image_btn" style="display:none;"> 162 <button type="button" id="upload_image_btn" class="wpsap-btn wpsap-btn--secondary">Upload image</button> 163 </div> 164 165 <div class="wpsap-field"> 166 <label class="wpsap-field__label" for="site_url">Link to your offer</label> 167 <input type="text" id="site_url" name="site_url" value="<?php echo esc_url($link_added); ?>" placeholder="Paste your product link here..."> 168 </div> 169 </form> 170 137 </div> 138 139 <div class="wpsap-field"> 140 <input type="submit" value="Upload image" id="hidden_upload_image_btn" style="display:none;"> 141 <?php /* Der Upload-Button ist bewusst blau (SS3) und damit von 142 der schwarzen Primaeraktion "Next" unterscheidbar. */ ?> 143 <button type="button" id="upload_image_btn" class="wpsap-btn wpsap-btn--upload">Upload image</button> 144 </div> 145 146 <div class="wpsap-field"> 147 <label class="wpsap-field__label" for="site_url">Link to your offer</label> 148 <input type="text" id="site_url" name="site_url" value="<?php echo esc_url($link_added); ?>" placeholder="Paste your product link here..."> 149 </div> 150 </form> 151 152 <?php if($terms || $cencel || $cencel_policy){ ?> 153 <ul class="wpsap-links"> 154 <?php if($terms){ ?> 155 <li><a href="<?php echo esc_url(get_the_permalink($terms)); ?>" target="_blank" rel="noopener noreferrer"><?php echo esc_html(get_the_title($terms)); ?></a></li> 156 <?php } ?> 171 157 <?php if($cencel){ ?> 172 <ul class="wpsap-links"> 173 <li><a href="<?php echo esc_url(get_the_permalink($cencel)); ?>"><?php echo esc_html(get_the_title($cencel)); ?></a></li> 174 </ul> 158 <li><a href="<?php echo esc_url(get_the_permalink($cencel)); ?>" target="_blank" rel="noopener noreferrer"><?php echo esc_html(get_the_title($cencel)); ?></a></li> 175 159 <?php } ?> 176 177 <div class="wpsap-actions"> 178 <input type="hidden" id="ads_image" value="<?php echo esc_url($image_uploaded); ?>"> 179 <button type="button" class="btn next wpsap-btn wpsap-btn--primary">Next</button> 180 </div> 181 182 </section> 183 184 <section class="purchased_area" style="<?php echo $wpsap_step_done ? 'display:block' : 'display:none'; ?>"> 185 186 <h1 class="wpsap-step__title">Your order has been placed</h1> 187 <?php /* Kein Erstattungsversprechen: wpsap_reject_ads() kuendigt 188 das Abo bei Stripe, mehr nicht. Bis 1.8.1 stand hier 189 "you will automatically get your money back" - das 190 loeste der Code nie ein. */ ?> 191 <p class="wpsap-step__lead">The advertisement has been successfully sent to the website owner. It may take up to 14 days for the ad to be reviewed and accepted. If your request is rejected or stays unanswered, your subscription is cancelled automatically and you will not be charged again. If your ad has been accepted, your advertising partnership will remain active until you or the website owner cancel it.</p> 192 193 <table> 194 <tbody> 195 <tr> 196 <th scope="row">Start date</th> 197 <td>After the website owner accept your ads.</td> 198 </tr> 199 <tr> 200 <th scope="row">End date</th> 201 <td>Until someone quits</td> 202 </tr> 203 </tbody> 204 </table> 205 206 <div class="link_input_desc_area"> 207 <div class="input-group"> 208 <?php /* Fuehrt in das Billing Portal von Stripe - dort kann der Kaeufer 209 selbst kuendigen und seine Rechnungen einsehen. */ ?> 210 <input id="foo" type="text" class="link_copied_button" readonly value="<?php echo esc_url(add_query_arg(array('action' => 'wpsap_billing_portal','session' => $session_id),admin_url('admin-post.php'))); ?>"> 211 <span class="input-group-button"> 212 <button class="wpsap_ads_copy_btn" type="button" data-clipboard-target="#foo" title="Copy to clipboard" aria-label="Copy to clipboard"> 213 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg> 214 </button> 215 </span> 216 </div> 217 218 <div class="wpsap-copy-hint"> 219 <span class="wpsap-copy-hint__icon" aria-hidden="true"> 220 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" focusable="false"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg> 221 </span> 222 <p>Save this link. With this link you can cancel your monthly advertising space rental in the future. If you want to cancel, you can use this link or simply ask the website owner directly.</p> 223 </div> 224 </div> 225 226 <?php if($cencel_policy || $terms){ ?> 227 <ul class="wpsap-links"> 228 <?php if($cencel_policy){ ?> 229 <li><a href="<?php echo esc_url(get_the_permalink($cencel_policy)); ?>"><?php echo esc_html(get_the_title($cencel_policy)); ?></a></li> 230 <?php } ?> 231 <?php if($terms){ ?> 232 <li><a href="<?php echo esc_url(get_the_permalink($terms)); ?>"><?php echo esc_html(get_the_title($terms)); ?></a></li> 233 <?php } ?> 234 </ul> 160 <?php if($cencel_policy){ ?> 161 <li><a href="<?php echo esc_url(get_the_permalink($cencel_policy)); ?>" target="_blank" rel="noopener noreferrer"><?php echo esc_html(get_the_title($cencel_policy)); ?></a></li> 235 162 <?php } ?> 236 237 <div class="wpsap-actions">238 <button type="button" class="btn_back wpsap-btn wpsap-btn--quiet">Back</button> 239 <button type="button" class="btn_finish wpsap-btn wpsap-btn--primary" data-link="<?php echo esc_url(get_site_url()); ?>">Finish</button>240 < /div>241 242 </ section>163 </ul> 164 <?php } ?> 165 166 <div class="wpsap-actions"> 167 <input type="hidden" id="ads_image" value="<?php echo esc_url($image_uploaded); ?>"> 168 <button type="button" class="btn next wpsap-btn wpsap-btn--primary">Next</button> 169 </div> 243 170 244 171 </div> 245 </div> 172 </section> 173 174 <?php /* Schritt 2: Bestaetigung - einspaltig, zentriert wie der 175 Upload-Schritt. Die frueher linke Aside (Logo, Fakten, Copyright) 176 wurde bewusst entfernt; nur .wpsap-flow__main traegt den Inhalt. */ ?> 177 <section class="purchased_area" <?php if(!$wpsap_step_done){ echo 'style="display:none"'; } ?>> 178 179 <div class="wpsap-flow__main"> 180 181 <span class="wpsap-badge" aria-hidden="true"> 182 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round" focusable="false"><path d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"/><path d="m9 12 2 2 4-4"/></svg> 183 </span> 184 185 <h1 class="wpsap-step__title">Your order has been placed</h1> 186 <?php /* Kein Erstattungsversprechen: wpsap_reject_ads() kuendigt 187 das Abo bei Stripe, mehr nicht. Bis 1.8.1 stand hier 188 "you will automatically get your money back" - das 189 loeste der Code nie ein. */ ?> 190 <p class="wpsap-step__lead">The advertisement has been successfully sent to the website owner. It may take up to 14 days for the ad to be reviewed and approved. If your request is rejected or remains unanswered, your subscription will be cancelled automatically, and you will not be charged. If your ad is approved, your advertising partnership will remain active until you or the website owner cancels it.</p> 191 192 <?php /* Stand bis 1.8.3 in der linken Aside. Die Notiz ist optional 193 konfigurierbar und darf mit der entfernten Spalte nicht 194 verschwinden - sie sitzt jetzt hier im Hauptbereich. */ ?> 195 <?php if(trim($note_on_thanks_page) !== ''){ ?> 196 <div class="wpsap-note"><?php echo esc_html($note_on_thanks_page); ?></div> 197 <?php } ?> 198 199 <table> 200 <tbody> 201 <tr> 202 <th scope="row">Offer Submitted</th> 203 <td><?php echo esc_html($wpsap_submitted_date); ?></td> 204 </tr> 205 <tr> 206 <th scope="row">Expected start date</th> 207 <td>Waiting for website owner to review (Maximum 14 days)</td> 208 </tr> 209 <tr> 210 <th scope="row">End date</th> 211 <td>Until you or website owner cancels</td> 212 </tr> 213 <tr> 214 <th scope="row">Billing date</th> 215 <td><?php echo esc_html($wpsap_billing_date); ?></td> 216 </tr> 217 </tbody> 218 </table> 219 220 <div class="link_input_desc_area"> 221 <div class="input-group"> 222 <?php /* Fuehrt in das Billing Portal von Stripe - dort kann der Kaeufer 223 selbst kuendigen und seine Rechnungen einsehen. */ ?> 224 <input id="foo" type="text" class="link_copied_button" readonly value="<?php echo esc_url(add_query_arg(array('action' => 'wpsap_billing_portal','session' => $session_id),admin_url('admin-post.php'))); ?>"> 225 <span class="input-group-button"> 226 <button class="wpsap_ads_copy_btn" type="button" data-clipboard-target="#foo" title="Copy to clipboard" aria-label="Copy to clipboard"> 227 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg> 228 </button> 229 </span> 230 </div> 231 232 <div class="wpsap-copy-hint"> 233 <span class="wpsap-copy-hint__icon" aria-hidden="true"> 234 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" focusable="false"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg> 235 </span> 236 <p>Please save this link. You can use it at any time to manage your subscription or cancel your monthly advertising space rental. If you wish to cancel, simply use this link or contact the website owner directly.</p> 237 </div> 238 </div> 239 240 <div class="wpsap-actions"> 241 <button type="button" class="btn_back wpsap-btn wpsap-btn--quiet">Back</button> 242 <button type="button" class="btn_finish wpsap-btn wpsap-btn--primary" data-link="<?php echo esc_url(get_site_url()); ?>">Finish</button> 243 </div> 244 245 </div> 246 </section> 247 246 248 </div> 247 249 -
sell-ads/tags/1.9.6/inc/page/style.css
r3626502 r3627752 107 107 108 108 /* ========================================================================== 109 Zweispaltiger Rahmen109 Rahmen: Upload einspaltig (SS3), Bestaetigung zweispaltig (SS4) 110 110 ========================================================================== */ 111 111 … … 120 120 } 121 121 122 .wpsap-flow__grid { 122 /* Die Bestaetigung ist einspaltig (die frueher linke Aside mit Logo, Fakten 123 und Copyright ist entfernt). flex:1 1 auto fuellt die Resthoehe unter dem 124 Flex-#wpsap-flow - das tat vorher .wpsap-flow__grid. */ 125 .purchased_area { 123 126 flex: 1 1 auto; 124 display: grid; 125 grid-template-columns: minmax(240px, 320px) 1fr; 126 align-items: stretch; 127 } 128 129 .wpsap-flow__aside { 130 background-color: var(--wpsap-canvas-soft, #fafafa); 131 border-right: 1px solid var(--wpsap-line, #dcdfe3); 132 padding: 2.5rem 1.75rem; 133 display: flex; 134 flex-direction: column; 135 gap: 1.5rem; 136 } 137 127 } 128 129 /* Bleibt fuer den Upload-Schritt (Marken-Text als Logo-Fallback). */ 138 130 #wpsap-flow .wpsap-flow__site { 139 131 font-size: 22px; … … 144 136 } 145 137 146 .wpsap-flow__facts { 138 /* Bestaetigung: Inhalt zentriert mit fester Maximalbreite (SS4). Die 139 Blanket-Regel gibt jedem direkten Kind dieselbe Breite, damit Badge, Titel, 140 Tabelle und Aktionszeile buendig uebereinanderstehen. */ 141 .wpsap-flow__main { 142 padding: 3rem 1.75rem; 147 143 display: flex; 148 144 flex-direction: column; 149 gap: .75rem; 150 } 151 152 .wpsap-flow__fact { 153 display: flex; 154 flex-direction: column; 155 gap: .15rem; 156 } 157 158 #wpsap-flow .wpsap-flow__fact-label { 159 font-size: 12px; 145 align-items: center; 146 text-align: center; 147 } 148 149 .wpsap-flow__main > * { 150 width: 100%; 151 max-width: 520px; 152 } 153 154 /* Schritt 1 ist einspaltig und ohne Aside. wp-sap.js schaltet die Sichtbarkeit 155 per .hide()/.show(); der gezeigte Zustand kommt aus dem Stylesheet, das 156 Markup setzt inline nur display:none fuer den verborgenen Schritt - so 157 ueberschreibt keine Inline-Regel das Grid der Bestaetigung. */ 158 .upload_ads_area { 159 flex: 1 1 auto; 160 padding: 3rem 1.25rem; 161 } 162 163 .wpsap-single { 164 width: 100%; 165 max-width: 560px; 166 margin: 0 auto; 167 } 168 169 /* Nur der Kopfbereich des Upload-Schritts ist zentriert; Karte und Felder 170 darunter bleiben linksbuendig. */ 171 .wpsap-single > .wpsap-flow__brand, 172 .wpsap-single > .wpsap-step__title, 173 .wpsap-single > .wpsap-step__subtitle, 174 .wpsap-single > .wpsap-step__lead { 175 text-align: center; 176 } 177 178 .wpsap-single > .wpsap-flow__brand { 179 margin-bottom: 1.5rem; 180 } 181 182 .upload_ads_area .wpsap-links { 183 justify-content: center; 184 } 185 186 187 /* ========================================================================== 188 Logo, Untertitel und Erfolgs-Badge 189 ========================================================================== */ 190 191 /* Logo (get_custom_logo) oben im Upload-Schritt bzw. in der Aside. In der 192 Aside bleibt es linksbuendig wie die uebrigen Angaben. */ 193 #wpsap-flow .wpsap-flow__brand img, 194 #wpsap-flow .custom-logo { 195 display: inline-block; 196 width: auto; 197 height: auto; 198 max-height: 52px; 199 } 200 201 #wpsap-flow .wpsap-step__subtitle { 202 font-size: 16px; 160 203 font-weight: 600; 161 letter-spacing: .04em; 162 text-transform: uppercase; 163 color: var(--wpsap-muted, #6b7280); 164 } 165 166 #wpsap-flow .wpsap-flow__fact-value { 167 font-size: 16px; 168 font-weight: 500; 169 color: var(--wpsap-ink, #161616); 170 overflow-wrap: anywhere; 171 } 172 173 #wpsap-flow .wpsap-flow__aside-note { 174 font-size: 14px; 175 line-height: 1.55; 204 line-height: 1.35; 176 205 color: var(--wpsap-ink-soft, #4a4a4a); 177 white-space: pre-line; 178 } 179 180 /* Schiebt das Copyright ans untere Ende, ohne es dort festzunageln - 181 bei viel Inhalt rutscht es einfach mit. */ 182 #wpsap-flow .wpsap-flow__copyright { 183 margin-top: auto; 184 padding-top: 1.5rem; 185 font-size: 13px; 186 color: var(--wpsap-muted, #6b7280); 187 } 188 189 .wpsap-flow__main { 190 padding: 2.5rem 1.75rem 3rem; 206 margin: 0 0 1rem 0; 207 } 208 209 /* Siegel mit Haken ueber dem Titel der Bestaetigung (SS4). */ 210 .wpsap-badge { 191 211 display: flex; 192 212 justify-content: center; 193 } 194 195 /* Die beiden Schritte behalten ihre Bestandsklassen: inc/page/wp-sap.js 196 blendet sie ueber .hide()/.show() um und setzt dabei display:block. */ 197 .upload_ads_area, 198 .purchased_area { 199 width: 100%;200 max-width: 640px;213 color: var(--wpsap-ink, #161616); 214 margin-bottom: 1rem; 215 } 216 217 #wpsap-flow .wpsap-badge svg { 218 display: block; 219 width: 64px; 220 height: 64px; 201 221 } 202 222 … … 331 351 } 332 352 353 /* Blauer Upload-Button (SS3) - hebt das Hochladen von der schwarzen 354 Primaeraktion "Next" ab. Fuellt die Breite der Karte. */ 355 #wpsap-flow .wpsap-btn--upload { 356 width: 100%; 357 background-color: #337ab6; 358 border-color: #337ab6; 359 color: #fff; 360 } 361 362 #wpsap-flow .wpsap-btn--upload:hover { 363 background-color: #2b6698; 364 border-color: #2b6698; 365 } 366 333 367 #wpsap-flow .wpsap-btn[disabled] { 334 368 opacity: .6; … … 507 541 text-align: left; 508 542 vertical-align: top; 543 /* Beide Spalten identisch: schwarze Schrift auf weissem Grund. Explizit 544 gesetzt, damit kein Theme-CSS auf der Bestaetigungsseite durchschlaegt. */ 545 color: #000; 546 background-color: #fff; 509 547 } 510 548 511 549 #wpsap-flow .purchased_area th { 512 550 width: 40%; 513 font-weight: 600;514 color: var(--wpsap-ink, #161616);515 background-color: var(--wpsap-canvas-soft, #fafafa);516 551 } 517 552 … … 521 556 border-radius: var(--wpsap-radius-sm, 5px); 522 557 padding: 1rem; 558 /* Der Hauptbereich zentriert seinen Inhalt (SS4); Feld und Hinweis bleiben 559 darin aber linksbuendig. */ 560 text-align: left; 523 561 } 524 562 … … 604 642 } 605 643 606 .wpsap-flow__grid {607 grid-template-columns: 1fr;608 }609 610 .wpsap-flow__aside {611 border-right: 0;612 border-bottom: 1px solid var(--wpsap-line, #dcdfe3);613 padding: 1.75rem 1.25rem;614 gap: 1.25rem;615 }616 617 /* Gestapelt gehoert das Copyright unter den Inhalt der Spalte,618 nicht ans Ende eines nicht mehr vorhandenen Streifens. */619 #wpsap-flow .wpsap-flow__copyright {620 margin-top: 0;621 padding-top: 0;622 }623 624 644 .wpsap-flow__main { 625 645 padding: 1.75rem 1.25rem 2.5rem; -
sell-ads/tags/1.9.6/inc/settings.php
r3626502 r3627752 94 94 <?php $this->wpsap_notify_callback(); ?> 95 95 96 <details class="wpsap-more"> 97 <summary><?php esc_html_e( 'Pages and texts','wpsap_ads_plugin' ); ?></summary> 96 <h2 class="wpsap-step"><?php esc_html_e( 'Pages and texts','wpsap_ads_plugin' ); ?></h2> 98 97 <table class="form-table" role="presentation"> 99 98 <tr> 100 <th scope="row"><label for="terms_condtions_0"><?php esc_html_e( 'Terms of Service ','wpsap_ads_plugin' ); ?></label></th>99 <th scope="row"><label for="terms_condtions_0"><?php esc_html_e( 'Terms of Service (Displayed on the upload page)','wpsap_ads_plugin' ); ?></label></th> 101 100 <td><?php $this->wpsap_terms_condtions_0_callback(); ?></td> 102 101 </tr> 103 102 <tr> 104 <th scope="row"><label for="template_cencel_subscription_1"><?php esc_html_e( 'Uploading Policy ','wpsap_ads_plugin' ); ?></label></th>103 <th scope="row"><label for="template_cencel_subscription_1"><?php esc_html_e( 'Uploading Policy (Displayed on the upload page)','wpsap_ads_plugin' ); ?></label></th> 105 104 <td><?php $this->wpsap_template_cencel_subscription_1_callback(); ?></td> 106 105 </tr> 107 106 <tr> 108 <th scope="row"><label for="template_cencel_policy_1"><?php esc_html_e( 'Cancel Policy ','wpsap_ads_plugin' ); ?></label></th>107 <th scope="row"><label for="template_cencel_policy_1"><?php esc_html_e( 'Cancel Policy (Displayed on the upload page)','wpsap_ads_plugin' ); ?></label></th> 109 108 <td><?php $this->wpsap_template_cencel_policy_1_callback(); ?></td> 110 109 </tr> 111 110 <tr> 112 <th scope="row"><label for="notification_2"><?php esc_html_e( 'Note for the buyer ','wpsap_ads_plugin' ); ?></label></th>111 <th scope="row"><label for="notification_2"><?php esc_html_e( 'Note for the buyer (Shown on the Stripe payment page)','wpsap_ads_plugin' ); ?></label></th> 113 112 <td><?php $this->wpsap_notification_2_callback(); ?></td> 114 113 </tr> … … 122 121 </tr> 123 122 </table> 124 </details>125 123 126 124 <?php submit_button(); ?> … … 142 140 border: 1px solid #dcdcde; 143 141 border-left: 4px solid #2271b1; 144 }145 .wpsap-settings .wpsap-more {146 margin-top: 32px;147 padding-top: 8px;148 border-top: 1px solid #dcdcde;149 }150 .wpsap-settings .wpsap-more > summary {151 cursor: pointer;152 font-size: 1.15em;153 font-weight: 600;154 padding: 8px 0;155 142 } 156 143 </style> … … 241 228 $status = wpsap_connect_account_status(); 242 229 ?> 243 <p>Payments run through the Sell Ads platform at <code>sellads.cybie.de</code>.230 <p>Payments run through our SellAds platform. 244 231 Your advertisers pay into your own Stripe account. No API key and no webhook setup needed.</p> 245 232 … … 330 317 </p> 331 318 <p class="description">Stripe cannot change this later, so please pick the country your business is registered in.</p> 332 <p class="description">333 <a href="https://sellads.cybie.de/terms.html" target="_blank" rel="noopener noreferrer">Terms of service</a>334 ·335 <a href="https://sellads.cybie.de/privacy.html" target="_blank" rel="noopener noreferrer">Privacy policy</a>336 </p>337 319 <?php 338 320 } … … 505 487 <label class="wpsap-choice"> 506 488 <input type="radio" name="wpsap_test_mode" value="live" <?php checked( 'live', $mode ); ?>> 507 Live — buyers pay through Stripe489 Live 508 490 </label> 509 491 <label class="wpsap-choice"> 510 492 <input type="radio" name="wpsap_test_mode" value="test" <?php checked( 'test', $mode ); ?>> 511 Test mode — walk through the plugin without setting up Stripe493 Test mode 512 494 </label> 513 495 <p class="description"> … … 519 501 if ( wpsap_test_mode() ) { 520 502 echo '<p class="notice notice-warning inline" style="padding:8px 12px;margin:8px 0 0;">' 521 . '<strong>Test mode is on.</strong> Visitors can place orders without paying , and the ad space says so.'503 . '<strong>Test mode is on.</strong> Visitors can place orders without paying.' 522 504 . '</p>'; 523 505 } … … 529 511 <label class="wpsap-choice"> 530 512 <input type="radio" name="wpsap_payment_mode" value="connect" <?php checked( 'connect', $mode ); ?>> 531 Connect with Stripe — one click, nothing to set up513 Connect with Stripe Express — Suggestion for Beginners 532 514 </label> 533 515 <label class="wpsap-choice"> 534 516 <input type="radio" name="wpsap_payment_mode" value="own_key" <?php checked( 'own_key', $mode ); ?>> 535 Use my own Stripe key — you add the key and the webhook yourself517 Use my own Stripe key — Suggestion for Advanced Users 536 518 </label> 537 519 <?php … … 627 609 public function wpsap_terms_condtions_0_callback() { 628 610 ?> <select name="wpsap_option_name[terms_condtions_0]" id="terms_condtions_0"> 629 <?php foreach($this->wpsap_get_pages() as $page){ ?> 611 <option value="" <?php echo empty( $this->wpsap_options['terms_condtions_0'] ) ? 'selected' : ''; ?>><?php esc_html_e( '— None —', 'wpsap_ads_plugin' ); ?></option> 612 <?php foreach($this->wpsap_get_pages() as $page){ ?> 630 613 <?php $selected = (isset( $this->wpsap_options['terms_condtions_0'] ) && $this->wpsap_options['terms_condtions_0'] == $page->ID) ? 'selected' : '' ; ?> 631 614 <option value="<?php echo esc_attr($page->ID); ?>" <?php echo esc_attr($selected); ?>><?php echo esc_html(get_the_title($page->ID)); ?></option> … … 637 620 public function wpsap_template_cencel_subscription_1_callback() { 638 621 ?> <select name="wpsap_option_name[template_cencel_subscription_1]" id="template_cencel_subscription_1"> 639 640 <?php foreach($this->wpsap_get_pages() as $page){ ?> 622 <option value="" <?php echo empty( $this->wpsap_options['template_cencel_subscription_1'] ) ? 'selected' : ''; ?>><?php esc_html_e( '— None —', 'wpsap_ads_plugin' ); ?></option> 623 <?php foreach($this->wpsap_get_pages() as $page){ ?> 641 624 <?php $selected = (isset( $this->wpsap_options['template_cencel_subscription_1'] ) && $this->wpsap_options['template_cencel_subscription_1'] == $page->ID) ? 'selected' : '' ; ?> 642 625 <option value="<?php echo esc_attr($page->ID); ?>" <?php echo esc_attr($selected); ?>><?php echo esc_html(get_the_title($page->ID)); ?></option> … … 647 630 public function wpsap_template_cencel_policy_1_callback() { 648 631 ?> <select name="wpsap_option_name[template_cencel_policy_1]" id="template_cencel_policy_1"> 649 650 <?php foreach($this->wpsap_get_pages() as $page){ ?> 632 <option value="" <?php echo empty( $this->wpsap_options['template_cencel_policy_1'] ) ? 'selected' : ''; ?>><?php esc_html_e( '— None —', 'wpsap_ads_plugin' ); ?></option> 633 <?php foreach($this->wpsap_get_pages() as $page){ ?> 651 634 <?php $selected = (isset( $this->wpsap_options['template_cencel_policy_1'] ) && $this->wpsap_options['template_cencel_policy_1'] == $page->ID) ? 'selected' : '' ; ?> 652 635 <option value="<?php echo esc_attr($page->ID); ?>" <?php echo esc_attr($selected); ?>><?php echo esc_html(get_the_title($page->ID)); ?></option> -
sell-ads/tags/1.9.6/inc/shortcode.php
r3626502 r3627752 8 8 $price = get_post_meta($id,"wpsap_campaign_price",true); 9 9 $button_text = get_post_meta($id, "wpsap_button_text",true); 10 if(empty($title)){ 11 $title = __('This Ad Space is for Sale','wpsap_ads_plugin'); 12 } 10 // Kein Default-Titel: der Platz zeigt einen Titel nur, wenn der Betreiber 11 // ihn aktiv gesetzt hat (Ausgabe unten bedingt). 13 12 if(empty($button_text)){ 14 13 $button_text = __('Buy','wpsap_ads_plugin'); … … 27 26 <div class="wpsap_ads_plugin_ads_box"> 28 27 <div class="wpsap_ads_plugin_ads_box_container"> 28 <?php if((string) $title !== ''){ ?> 29 29 <div class="wpsap_ads_plugin_ads_box_title"><?php echo esc_html($title); ?></div> 30 <?php } ?> 30 31 <form class="wpsap_ads_plugin_ads_box_form" method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>"> 31 32 <input type="hidden" name="action" value="wpsap_start_checkout"> … … 48 49 } 49 50 else { 51 // Klicks auf die veroeffentlichte Anzeige laufen ueber /goto/<slug>, 52 // damit der Zaehler der Kampagne hochlaeuft (inc/hooks.php) - derselbe 53 // Zaehler, den auch der Buy-Button-Klick erhoeht (inc/checkout.php). 54 // Fallback auf die ID, falls der Slug (post_name) leer ist. 55 $slug = get_post_field('post_name',$id); 56 if(empty($slug)){ 57 $slug = $id; 58 } 59 // user_trailingslashit() richtet sich nach der Permalink-Struktur der 60 // Seite. Ohne das haengt WordPress bei Trailing-Slash-Permalinks erst 61 // einen 301 an, bevor der Redirect greift - ein unnoetiger Hop auf 62 // jedem Anzeigenklick. 63 $goto_url = home_url(user_trailingslashit('goto/'.$slug)); 50 64 foreach($activer_orders as $ad){ 51 $url = get_post_meta($ad->ID, "order_url",true); 52 ?> 65 ?> 53 66 <div class="wpsap_ads_plugin_ads_box"> 54 67 <div class="wpsap_ads_plugin_ads_box_container"> 55 <a href="<?php echo esc_ attr($url); ?>" target="_blank" rel="noopener noreferrer nofollow"><img style="max-width:100%;" src="<?php echo esc_attr(get_post_meta($ad->ID, "order_image",true)); ?>"></a>68 <a href="<?php echo esc_url($goto_url); ?>" target="_blank" rel="noopener noreferrer nofollow"><img style="max-width:100%;" src="<?php echo esc_attr(get_post_meta($ad->ID, "order_image",true)); ?>"></a> 56 69 </div> 57 70 </div> -
sell-ads/tags/1.9.6/inc/stripe.php
r3626067 r3627752 157 157 ), 158 158 'subscription_data' => array( 159 // Waehrend der Pruefungsfrist wird nicht belastet: das Abo startet 160 // im Trial, die erste Rechnung entsteht erst, wenn der Betreiber die 161 // Bestellung annimmt (wpsap_stripe_end_trial) - oder gar nicht, wenn 162 // sie nach 14 Tagen ablaeuft und das Abo vorher gekuendigt wird. 163 // 16 statt 14 Tage: der Ablauf-Cron laeuft nur taeglich, der Puffer 164 // stellt sicher, dass die Kuendigung immer vor dem Trial-Ende greift. 165 'trial_period_days' => 16, 159 166 'metadata' => array( 160 167 'wpsap_place_id' => (string) $campaign_id, … … 210 217 } 211 218 return wpsap_stripe_request('DELETE','subscriptions/'.rawurlencode($subscription_id)); 219 } 220 221 /** 222 * Beendet den Trial eines Abos sofort. Dadurch stellt Stripe die erste 223 * Rechnung unmittelbar aus. Aufgerufen beim Annehmen einer Bestellung: erst 224 * dann - nicht schon beim Checkout - soll der Kaeufer belastet werden. 225 */ 226 function wpsap_stripe_end_trial($subscription_id){ 227 $subscription_id = sanitize_text_field($subscription_id); 228 if(empty($subscription_id)){ 229 return new WP_Error('wpsap_no_subscription',__('No subscription stored for this order.','wpsap_ads_plugin')); 230 } 231 if(wpsap_connect_is_active()){ 232 return wpsap_connect_end_trial($subscription_id); 233 } 234 return wpsap_stripe_request('POST','subscriptions/'.rawurlencode($subscription_id),array('trial_end' => 'now')); 212 235 } 213 236 -
sell-ads/tags/1.9.6/readme.txt
r3626505 r3627752 5 5 Tested up to: 7.0 6 6 Requires PHP: 7.0 7 Stable tag: 1. 8.27 Stable tag: 1.9.6 8 8 License: GPLv2 or later 9 9 License URI: http://www.gnu.org/licenses/gpl.html … … 241 241 If you want to fill unsold inventory automatically, you want an ad network, not this. This plugin 242 242 does nothing until a real advertiser buys a real space from you. If you need impression counting, 243 click tracking, geo-targeting or A/B rotation, this plugin has none of it on purpose: an ad here is 244 an image and a link, and that is the entire point. And if you would rather never speak to an 243 geo-targeting or A/B rotation, this plugin has none of it on purpose: an ad here is an image and a 244 link, and that is the entire point. It does count clicks — first-party, on your own server, with no 245 cookies and no third-party script — but that is as far as the measuring goes. And if you would rather never speak to an 245 246 advertiser, be aware that even though the purchase itself is automatic, you are the one who decides 246 247 what runs on your site. … … 402 403 403 404 == Changelog == 405 406 = 1.9.0 = 407 * New: the campaign list shows a "Clicks" column again, counting how often each ad space was clicked. Published ads now link through a first-party /goto/<slug> redirect on your own domain that counts the click and forwards the visitor to the advertiser — no cookies and no third-party script are involved, and clicks from logged-in editors are not counted. 408 * Fixed: the "PHP" and "Shortcode" columns showed their raw HTML instead of a usable field. They are copyable input fields again, each with a copy button. 409 410 = 1.8.4 = 411 * The confirmation step is now a single centred column, matching the upload step. The left column that repeated your site name, the ad space and the monthly price has been removed; the confirmation badge, the summary table and the cancellation link stay. 412 413 = 1.8.3 = 414 * The buyer flow was reworked to match the intended design. The ad space now shows as a rounded card instead of a square band. 415 * The upload step is a single centred column again, with your site logo on top, the ad space name below the heading, and a clearly separated blue upload button. Your terms and refund pages are linked right there. 416 * The confirmation step keeps its two columns and now opens with a confirmation badge and a four-row summary: when the request was submitted, the expected review window, that the partnership runs until either side cancels, and the expected first billing date. 417 * Uses your WordPress site logo (Appearance → Customize) on both pages when one is set, otherwise your site name. 404 418 405 419 = 1.8.2 = … … 456 470 == Upgrade Notice == 457 471 472 = 1.9.0 = 473 The campaign list has a Clicks column again and published ads are counted through a first-party /goto redirect on your own domain. The PHP and Shortcode columns are copyable fields again. No reconfiguration needed; the redirect rule is registered automatically on update. 474 475 = 1.8.4 = 476 The confirmation page after upload is now a single centred column; the left sidebar with the site name and price has been removed. No reconfiguration needed. 477 478 = 1.8.3 = 479 Visual update to the pages buyers see. The ad space is a rounded card, the upload step is a single centred column with your site logo, and the confirmation shows a badge and a clear date summary. No reconfiguration needed. 480 458 481 = 1.8.2 = 459 482 Documentation only — the plugin code is identical to 1.8.1. The description now covers pricing, placement and finding your first advertiser. -
sell-ads/tags/1.9.6/wp-sap.php
r3626505 r3627752 5 5 * Plugin URI: https://cybie.de 6 6 * Description: The easiest way to sell adspace on your WordPress Website 7 * Version: 1. 8.27 * Version: 1.9.6 8 8 * Requires at least: 6.0 9 9 * Requires PHP: 7.0 … … 17 17 18 18 19 define("WPSAP_Version",'1. 8.2');19 define("WPSAP_Version",'1.9.6'); 20 20 define('WPSAP_Plugin_Path',plugin_dir_path( __FILE__ )); 21 21 define('WPSAP_Plugin_Dir',plugin_dir_url( __FILE__ )); … … 81 81 wp_schedule_event(time() + HOUR_IN_SECONDS,'daily','wpsap_expire_pending_orders'); 82 82 } 83 84 // Damit /goto/<slug> sofort nach der Aktivierung greift, muss die 85 // Rewrite-Rule bekannt sein und einmal geflusht werden. Die laufende 86 // Absicherung uebernimmt der Versions-Guard in wpsap_goto_rewrite(). 87 wpsap_goto_rewrite(); 88 flush_rewrite_rules(); 83 89 } 84 90 … … 86 92 function wpsap_deactivate(){ 87 93 wp_clear_scheduled_hook('wpsap_expire_pending_orders'); 94 95 // Die /goto-Rewrite-Rule wird ohne aktives Plugin nicht mehr registriert - 96 // der Flush raeumt sie aus den gespeicherten Regeln. Beim naechsten 97 // Aktivieren sorgt der Versions-Guard fuer die Neuanlage. 98 delete_option('wpsap_rewrite_version'); 99 flush_rewrite_rules(); 88 100 } 89 101 -
sell-ads/trunk/css/style.css
r3626502 r3627752 26 26 } 27 27 28 /* Freistehende, abgerundete Karte auf hellem Grund (SS1) statt des frueheren 29 kantigen Vollbreiten-Bandes. Der Radius stand bis 1.8.2 per !important auf 0 30 und musste hier aktiv ueberschrieben werden - jetzt traegt die Box Ecken und 31 einen weichen Schatten selbst. width:100% bleibt: die Karte fuellt die Breite 32 ihres Widgets/Containers, hebt sich aber durch Radius und Schatten ab. */ 28 33 .wpsap_ads_plugin_ads_box { 29 34 width: 100%; 30 35 box-sizing: border-box; 31 background-color: var(--wpsap-canvas, #f0f1f2); 32 border-radius: 0 !important; 36 background-color: #F2F3F5; 37 /* border-radius: 14px; */ 38 /* box-shadow: var(--wpsap-shadow, 0 1px 3px rgba(0, 0, 0, .08)); */ 33 39 text-align: center; 34 40 display: flex; -
sell-ads/trunk/inc/ajax.php
r3626067 r3627752 84 84 update_post_meta($order_id,'order_image',$data['url']); 85 85 update_post_meta($order_id,'order_url',$site_url); 86 // Attachment-ID mitfuehren, damit das Motiv beim Ablehnen/Kuendigen/ 87 // Ablaufen restlos aus der Mediathek entfernt werden kann 88 // (wpsap_delete_order_media() in inc/helper.php). 89 update_post_meta($order_id,'wpsap_order_image_id',$image); 86 90 } 87 91 else { -
sell-ads/trunk/inc/campaign_fields.php
r3626502 r3627752 16 16 function wpsap_campaign_metaboxes_html(){ 17 17 global $post; 18 // Keine Prefill-Defaults: leere Felder bleiben leer, damit im Frontend nur 19 // erscheint, was der Betreiber aktiv eingetragen hat. 18 20 $campaign_title = get_post_meta($post->ID, "wpsap_campaign_title",true); 19 if(empty($campaign_title)){20 $campaign_title = 'This Advertising space is for sale';21 }22 21 23 22 $campaign_name = get_the_title($post->ID); … … 27 26 28 27 $button_text = get_post_meta($post->ID, "wpsap_button_text",true); 29 if(empty($button_text)){30 $button_text = 'Buy';31 }32 28 33 29 // Ohne dieses Feld schlug die Nonce-Pruefung beim Speichern immer fehl … … 53 49 <span class="tooltiptext">This title is used to advertise your ad space.</span> 54 50 </div> 55 <input type="text" name="wpsap_campaign_title" class="regular-text" value="<?php echo esc_attr($campaign_title); ?>" required>51 <input type="text" name="wpsap_campaign_title" class="regular-text" value="<?php echo esc_attr($campaign_title); ?>"> 56 52 </td> 57 53 </tr> … … 68 64 </tr> 69 65 66 <?php $currency = strtoupper(wpsap_stripe_currency()); ?> 70 67 <tr> 71 <td><h4>Monthly Price ( $)</h4></td>68 <td><h4>Monthly Price (<?php echo esc_html($currency); ?>)</h4></td> 72 69 <td> 73 70 <div class="tooltip"><span class="dashicons dashicons-info"></span> 74 <span class="tooltiptext">This is the monthly price in US dollarsfor which you want to rent out your ad space.</span>71 <span class="tooltiptext">This is the monthly price in <?php echo esc_html($currency); ?> for which you want to rent out your ad space.</span> 75 72 </div> 76 73 <input type="number" step="0.01" min="0" name="wpsap_campaign_price" class="regular-text" value="<?php echo esc_attr(get_post_meta($post->ID, "wpsap_campaign_price",true)); ?>" required> … … 194 191 $columns['title'] = __( 'Campaign', "wpsap"); 195 192 $columns['price'] = __( 'Price', "wpsap"); 196 193 // Info-Icon mit CSS-Tooltip: erklaert die zwei gezaehlten Ereignisse. Der 194 // native title-Tooltip erschien nicht zuverlaessig, deshalb dieselbe 195 // .tooltiptext-Mechanik wie in der Metabox. Das noetige CSS steht - auf die 196 // Liste gescoped - im admin_footer (wpsap_campaign_copy_field()). WordPress 197 // gibt das Spalten-Label als HTML aus, daher ohne eigenes Enqueue. 198 // Icon und Text stehen in getrennten Spans: nur das Icon traegt die 199 // dashicons-Klasse, sonst wuerde der Tooltip-Text in der Icon-Schrift 200 // gerendert. 201 $columns['clicks'] = __( 'Clicks', "wpsap") 202 . ' <span class="wpsap-th-tip" tabindex="0">' 203 . '<span class="dashicons dashicons-info"></span>' 204 . '<span class="wpsap-th-tiptext">' 205 . esc_html__('Total clicks for this ad slot: clicks on the “Buy” button (before the slot is sold) plus outbound clicks on the published ad.','wpsap_ads_plugin') 206 . '</span></span>'; 197 207 $columns['pdate'] = __( 'Date', "wpsap"); 198 208 $columns['php'] = __( 'PHP', "wpsap"); … … 211 221 echo esc_html(get_post_meta($post_id, "wpsap_campaign_price",true).' '.strtoupper(wpsap_stripe_currency())." per month"); 212 222 break; 223 case 'clicks' : 224 // Zaehler wird an zwei Stellen hochgezaehlt: beim /goto-Redirect 225 // (inc/hooks.php) und beim Buy-Button-Klick (wpsap_start_checkout, 226 // inc/checkout.php). 227 // Als Link auf die Kampagne ausgegeben, damit die Zahl - wie in der 228 // Vorlage - klickbar ist und in WP-Blau erscheint. 229 $clicks = (int) get_post_meta($post_id, "wpsap_click_count",true); 230 $edit_link = get_edit_post_link($post_id); 231 if($edit_link){ 232 echo '<a href="'.esc_url($edit_link).'">'.esc_html($clicks).'</a>'; 233 } else { 234 echo esc_html($clicks); 235 } 236 break; 213 237 case 'php' : 214 echo esc_html(wpsap_plugin_php_function($post_id)); 238 // Bewusst ohne esc_html(): wpsap_plugin_php_function() liefert das 239 // fertige Kopier-Feld und escapt seinen dynamischen Wert selbst. 240 echo wpsap_plugin_php_function($post_id); 215 241 break; 216 242 case 'shortcode' : 217 echo esc_html(wpsap_shortcode_input($post_id));243 echo wpsap_shortcode_input($post_id); 218 244 break; 219 245 … … 230 256 $columns['order'] = __( 'Order', "wpsap"); 231 257 $columns['campaign'] = __( 'Campaign', "wpsap"); 232 $columns['pdate'] = __( ' Date', "wpsap");258 $columns['pdate'] = __( 'Order Date', "wpsap"); 233 259 $columns['status'] = __( 'Status', "wpsap"); 234 $columns['billing'] = __( 'Billing', "wpsap");235 260 $columns['resources'] = __( 'Resources', "wpsap"); 236 261 $columns['link'] = __( 'Link', "wpsap"); … … 251 276 // entstanden sind - die Spalte Total zeigt trotzdem einen Betrag. 252 277 if(get_post_meta($post_id,'wpsap_test_order',true) === 'yes'){ 253 echo '<br/><small><span style="color:#996800;">'.esc_html__('Test order — not paid','wpsap_ads_plugin').'</span></small>';278 echo '<br/><small><span style="color:#996800;">'.esc_html__('Test order','wpsap_ads_plugin').'</span></small>'; 254 279 } 255 280 break; … … 268 293 $final_dates = wpsap_order_days_left($post_id); 269 294 if($final_dates > 0){ 295 // Ablaufdatum = Bestelldatum + 14 Tage, dieselbe Frist wie 296 // in wpsap_order_days_left(). 297 $placed = get_post_time('U',true,$post_id); 298 $expires = $placed ? $placed + 14 * DAY_IN_SECONDS : time() + $final_dates * DAY_IN_SECONDS; 270 299 echo '<strong>Pending</strong>'; 271 echo '<br/><small><span>( '.esc_html($final_dates).' days until expiration)</span></small>';300 echo '<br/><small><span>(Request expires on '.esc_html(wp_date(get_option('date_format'),$expires)).')</span></small>'; 272 301 } 273 302 else { … … 291 320 echo "<span style='color:#ff0000;'>Rejected</span>"; 292 321 } 322 else if($current_status == 'expired'){ 323 $on = (int) get_post_meta($post_id, "wpsap_expired_on",true); 324 if(!$on){ 325 $placed = get_post_time('U',true,$post_id); 326 $on = $placed ? $placed + 14 * DAY_IN_SECONDS : 0; 327 } 328 echo "<span style='color:#ff0000;'>Expired</span>"; 329 if($on){ 330 echo "<br/><small>(on ".esc_html(wp_date(get_option('date_format'),$on)).")</small>"; 331 } 332 } 293 333 else { 294 334 echo esc_html($current_status); … … 297 337 } 298 338 break; 299 case 'billing' :300 echo esc_html(get_post_meta($post_id, "order_email",true));301 break;302 339 case 'resources' : 303 $url = get_post_meta($post_id, "order_url",true); 304 echo '<a target="_blank" href="'.esc_url(get_post_meta($post_id, "order_image",true)).'"><img style="max-width:120px;" src="'.esc_url(get_post_meta($post_id, "order_image",true)).'"></a>'; 340 // Nach Reject/Cancel/Expired ist das Motiv geloescht (order_image 341 // leer) - dann kein kaputtes <img> ausgeben. 342 $image = get_post_meta($post_id, "order_image",true); 343 if($image){ 344 echo '<a target="_blank" href="'.esc_url($image).'"><img style="max-width:120px;" src="'.esc_url($image).'"></a>'; 345 } else { 346 echo '—'; 347 } 305 348 break; 306 349 case 'link' : 307 350 $url = get_post_meta($post_id, "order_url",true); 308 echo '<a href="'.esc_url($url).'">'.esc_url($url).'</a>'; 351 if($url){ 352 echo '<a href="'.esc_url($url).'">'.esc_url($url).'</a>'; 353 } else { 354 echo '—'; 355 } 309 356 break; 310 357 case 'total' : 311 358 $status = get_post_meta($post_id, "wpsap_order_status",true); 312 359 if($status == "accepted"){ 313 echo "<small>You have confirmed the advertising partnership . Now you need to publish the advertisement. Make sure that the ad is displayed correctly and that the product link works. If there are any errors, you should contact the buyer immediately. If the buyer does not cancel within the next 14 days, the first transaction will be executed. The monthly payment will remain until someone cancels.</small>";360 echo "<small>You have confirmed the advertising partnership, and the first payment was charged when you accepted. Please publish the advertisement now: make sure it displays correctly and that the product link works, and contact the buyer right away if anything is wrong. The monthly payment continues until the subscription is cancelled — either by you here, or by the buyer from their own Stripe billing portal, which they can reach through the link on their order confirmation page.</small>"; 314 361 } 315 362 else { … … 320 367 $currency = wpsap_stripe_currency(); 321 368 } 322 echo esc_html(number_format_i18n($total,2).' '.strtoupper($currency) );369 echo esc_html(number_format_i18n($total,2).' '.strtoupper($currency).' per month'); 323 370 } 324 371 break; … … 334 381 echo 'This subscription was cancelled by the buyer.'; 335 382 } 383 elseif($status == 'expired'){ 384 // Nach 14 Tagen ohne Annahme ueber wpsap_expire_ads() beendet - 385 // das Abo stand noch im Trial, es wurde also nichts berechnet. 386 echo 'This request expired unanswered. No payment was charged.'; 387 } 336 388 elseif($status != "accepted" && $status != "published"){ 337 echo '<a href="'.esc_url(wpsap_order_action_url(' reject',$post_id)).'" class="button reject_ads">Reject</a> | <a href="'.esc_url(wpsap_order_action_url('accept',$post_id)).'" class="button accept_ads">Accept</a>';389 echo '<a href="'.esc_url(wpsap_order_action_url('accept',$post_id)).'" class="button button-primary accept_ads">Accept</a> | <a href="'.esc_url(wpsap_order_action_url('reject',$post_id)).'" class="button reject_ads">Reject</a>'; 338 390 } 339 391 … … 343 395 } 344 396 else { 345 echo '<a href="'.esc_url(wpsap_order_action_url('accept',$post_id)).'" class="button button-primaryaccept_ads">Unpublish</a> | <a href="'.esc_url(wpsap_order_action_url('reject',$post_id)).'" class="button reject_ads">Cancel</a>';397 echo '<a href="'.esc_url(wpsap_order_action_url('accept',$post_id)).'" class="button accept_ads">Unpublish</a> | <a href="'.esc_url(wpsap_order_action_url('reject',$post_id)).'" class="button reject_ads">Cancel</a>'; 346 398 } 347 399 } … … 356 408 if(isset($_GET['post_type'])){ 357 409 if(sanitize_text_field($_GET['post_type']) == 'ads_order'){ 358 ?> 410 ?> 359 411 <style> 360 412 .tablenav.top { … … 363 415 </style> 364 416 365 <?php 366 } 367 } 417 <?php 418 } 419 } 420 } 421 422 423 // Kopier-Verhalten und Optik der PHP-/Shortcode-Felder in der Kampagnenliste. 424 add_action('admin_footer','wpsap_campaign_copy_field'); 425 function wpsap_campaign_copy_field(){ 426 if(!isset($_GET['post_type']) || sanitize_text_field(wp_unslash($_GET['post_type'])) !== 'ads_campaign'){ 427 return; 428 } 429 ?> 430 <style> 431 .wpsap-copy { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; } 432 /* Weisses, schreibgeschuetztes Feld mit dezentem Rahmen - wie in der Vorlage 433 (kein grauer Fuellton). Erhoehte Spezifitaet (span + input.klasse), weil WP 434 readonly-Felder sonst grau einfaerbt (input[readonly]). */ 435 .wpsap-copy input.wpsap-copy__input { width: 150px; max-width: 100%; background: #fff; color: #3c434a; } 436 /* Randloses Kopier-Icon statt umrandetem Button: die Vorlage zeigt nur das 437 schlichte Dokument-Symbol ohne Button-Rahmen (die WP-.button-Klasse ist im 438 Markup deshalb entfernt). */ 439 .wpsap-copy__btn { display: inline-flex; align-items: center; justify-content: center; background: none; border: none; box-shadow: none; outline: none; padding: 0 2px; min-height: 0; color: #50575e; cursor: pointer; } 440 .wpsap-copy__btn:hover { color: #2271b1; background: none; box-shadow: none; } 441 .wpsap-copy__btn:focus { background: none; box-shadow: none; outline: none; } 442 .wpsap-copy__btn .dashicons { width: 18px; height: 18px; font-size: 18px; } 443 .wpsap-copy__btn.is-copied { color: #46b450; } 444 445 /* Info-Tooltip im Spaltenkopf "Clicks". Aufbau wie die Metabox-Tooltips, aber 446 eigene Klassen, damit nichts mit anderen Admin-Styles kollidiert. */ 447 .wpsap-th-tip { position: relative; display: inline-flex; align-items: center; vertical-align: middle; margin-top: -2px; cursor: help; color: #787c82; } 448 .wpsap-th-tip .dashicons-info { font-size: 16px; width: 16px; height: 16px; line-height: 16px; } 449 .wpsap-th-tip .wpsap-th-tiptext { 450 visibility: hidden; opacity: 0; transition: opacity .1s ease; 451 position: absolute; z-index: 100; top: 150%; left: 50%; transform: translateX(-50%); 452 width: 240px; padding: 8px 10px; border-radius: 4px; 453 background: #1d2327; color: #fff; 454 font: 400 12px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; 455 text-align: left; white-space: normal; font-weight: 400; text-transform: none; 456 } 457 .wpsap-th-tip:hover .wpsap-th-tiptext, 458 .wpsap-th-tip:focus .wpsap-th-tiptext, 459 .wpsap-th-tip:focus-within .wpsap-th-tiptext { visibility: visible; opacity: 1; } 460 </style> 461 <script> 462 jQuery(function($){ 463 $(document).on('click','.wpsap-copy__btn',function(){ 464 var $btn = $(this); 465 var $input = $btn.closest('.wpsap-copy').find('.wpsap-copy__input'); 466 var text = $input.val(); 467 468 var done = function(){ 469 $btn.addClass('is-copied'); 470 setTimeout(function(){ $btn.removeClass('is-copied'); },1200); 471 }; 472 473 if(navigator.clipboard && navigator.clipboard.writeText){ 474 navigator.clipboard.writeText(text).then(done, function(){ 475 $input.trigger('select'); document.execCommand('copy'); done(); 476 }); 477 } else { 478 $input.trigger('select'); document.execCommand('copy'); done(); 479 } 480 }); 481 }); 482 </script> 483 <?php 484 } 485 486 487 // Doppelte Bestaetigung fuer Reject/Cancel: beide Buttons loesen dieselbe 488 // irreversible Aktion aus (Stripe-Abo kuendigen). Ein eigenes Modal faengt den 489 // Klick ab und verlangt, dass der Betreiber das Aktionswort tippt, bevor der 490 // bereits nonce-gesicherte Link geoeffnet wird. Reiner Frontend-Schutz - der 491 // Serverpfad in wpsap_job_status() bleibt unveraendert. 492 add_action('admin_footer','wpsap_order_reject_confirm'); 493 function wpsap_order_reject_confirm(){ 494 if(!isset($_GET['post_type']) || sanitize_text_field(wp_unslash($_GET['post_type'])) !== 'ads_order'){ 495 return; 496 } 497 ?> 498 <style> 499 #wpsap-reject-modal { position: fixed; inset: 0; z-index: 100000; display: none; } 500 #wpsap-reject-modal.is-open { display: block; } 501 #wpsap-reject-modal .wpsap-reject-backdrop { position: absolute; inset: 0; background: rgba(0,0,0,0.5); } 502 #wpsap-reject-modal .wpsap-reject-box { position: relative; max-width: 420px; margin: 12vh auto 0; background: #fff; border-radius: 4px; box-shadow: 0 6px 30px rgba(0,0,0,0.3); padding: 24px; } 503 #wpsap-reject-modal .wpsap-reject-title { display: flex; align-items: center; gap: 8px; margin: 0 0 12px; font-size: 18px; font-weight: 600; color: #b32d2e; } 504 #wpsap-reject-modal .wpsap-reject-text { margin: 0 0 16px; color: #3c434a; line-height: 1.5; } 505 #wpsap-reject-modal .wpsap-reject-label { display: block; margin: 0 0 6px; font-weight: 600; color: #3c434a; } 506 #wpsap-reject-modal .wpsap-reject-input { width: 100%; box-sizing: border-box; margin: 0 0 16px; } 507 #wpsap-reject-modal .wpsap-reject-actions { display: flex; justify-content: flex-end; gap: 8px; } 508 #wpsap-reject-modal .wpsap-reject-confirm { background: #b32d2e; border-color: #b32d2e; color: #fff; } 509 #wpsap-reject-modal .wpsap-reject-confirm:hover:not(:disabled) { background: #9e2423; border-color: #9e2423; color: #fff; } 510 #wpsap-reject-modal .wpsap-reject-confirm:disabled { opacity: 0.5; cursor: not-allowed; } 511 </style> 512 <div id="wpsap-reject-modal" role="dialog" aria-modal="true" aria-labelledby="wpsap-reject-title"> 513 <div class="wpsap-reject-backdrop"></div> 514 <div class="wpsap-reject-box"> 515 <h2 id="wpsap-reject-title" class="wpsap-reject-title"><span class="dashicons dashicons-warning"></span><span class="wpsap-reject-heading">Reject this ad?</span></h2> 516 <p class="wpsap-reject-text">This permanently cancels the buyer’s active Stripe subscription. This action cannot be undone.</p> 517 <label class="wpsap-reject-label" for="wpsap-reject-word">Type <strong class="wpsap-reject-word">REJECT</strong> to confirm:</label> 518 <input type="text" id="wpsap-reject-word" class="wpsap-reject-input regular-text" autocomplete="off" autocapitalize="characters" spellcheck="false"> 519 <div class="wpsap-reject-actions"> 520 <button type="button" class="button wpsap-reject-cancel">Close</button> 521 <button type="button" class="button wpsap-reject-confirm" disabled>Confirm</button> 522 </div> 523 </div> 524 </div> 525 <script> 526 jQuery(function($){ 527 var $modal = $('#wpsap-reject-modal'); 528 var $input = $('#wpsap-reject-word'); 529 var $confirm = $modal.find('.wpsap-reject-confirm'); 530 var targetHref = ''; 531 var expectedWord = 'REJECT'; 532 533 function closeModal(){ 534 $modal.removeClass('is-open'); 535 targetHref = ''; 536 $input.val(''); 537 $confirm.prop('disabled', true); 538 } 539 540 // Reject und Cancel teilen die Klasse .reject_ads; der Wortlaut folgt dem 541 // Text des tatsaechlich geklickten Links (Reject oder Cancel). 542 $(document).on('click','.reject_ads',function(e){ 543 e.preventDefault(); 544 targetHref = $(this).attr('href'); 545 var label = $.trim($(this).text()) || 'Reject'; 546 expectedWord = label.toUpperCase(); 547 $modal.find('.wpsap-reject-heading').text(label + ' this ad?'); 548 $modal.find('.wpsap-reject-word').text(expectedWord); 549 $input.val(''); 550 $confirm.prop('disabled', true); 551 $modal.addClass('is-open'); 552 $input.trigger('focus'); 553 }); 554 555 $input.on('input',function(){ 556 $confirm.prop('disabled', $.trim($input.val()).toUpperCase() !== expectedWord); 557 }); 558 559 $confirm.on('click',function(){ 560 if($confirm.prop('disabled') || !targetHref){ return; } 561 window.location.href = targetHref; 562 }); 563 564 $modal.find('.wpsap-reject-cancel, .wpsap-reject-backdrop').on('click', closeModal); 565 566 $(document).on('keydown',function(e){ 567 if(e.key === 'Escape' && $modal.hasClass('is-open')){ closeModal(); } 568 }); 569 }); 570 </script> 571 <?php 368 572 } 369 573 -
sell-ads/trunk/inc/checkout.php
r3626502 r3627752 183 183 } 184 184 185 // Buy-Button-Klick zaehlen - derselbe Zaehler wie der /goto-Redirect 186 // (inc/hooks.php), damit die Spalte "Clicks" beide Ereignisse summiert. 187 // Selbst-Klicks eingeloggter Redakteure verfaelschen die Statistik nicht. 188 if(get_post_type($campaign_id) === 'ads_campaign' 189 && !(is_user_logged_in() && current_user_can('edit_posts'))){ 190 $count = (int) get_post_meta($campaign_id,'wpsap_click_count',true); 191 update_post_meta($campaign_id,'wpsap_click_count',$count + 1); 192 } 193 185 194 // Testmodus: die Zahlungsseite entfaellt ersatzlos. Die Bestellung 186 195 // entsteht hier statt aus einer bezahlten Stripe-Session, danach geht es … … 326 335 327 336 /** 328 * Taeglicher Lauf: Bestellungen, die 14 Tage unbeantwortet blieben, 329 * werden abgelehnt und das Abo beendet. Frueher passierte das mitten330 * im Rendern der Bestellliste.337 * Taeglicher Lauf: Bestellungen, die 14 Tage unbeantwortet blieben, laufen ab 338 * (Status "expired") und das Abo wird beendet - weil es noch im Trial steht, 339 * ohne Belastung. Frueher passierte das mitten im Rendern der Bestellliste. 331 340 */ 332 341 add_action('wpsap_expire_pending_orders','wpsap_expire_pending_orders'); … … 348 357 foreach($orders as $order_id){ 349 358 if(wpsap_order_days_left($order_id) <= 0){ 350 wpsap_ reject_ads($order_id);359 wpsap_expire_ads($order_id); 351 360 } 352 361 } -
sell-ads/trunk/inc/connect.php
r3626502 r3627752 20 20 21 21 function wpsap_payment_mode(){ 22 $mode = get_option('wpsap_payment_mode',' own_key');23 return in_array($mode,array('own_key','connect'),true) ? $mode : ' own_key';22 $mode = get_option('wpsap_payment_mode','connect'); 23 return in_array($mode,array('own_key','connect'),true) ? $mode : 'connect'; 24 24 } 25 25 … … 326 326 } 327 327 328 function wpsap_connect_end_trial($subscription_id){ 329 return wpsap_connect_request('POST','v1/subscription/end-trial',array('subscription_id' => $subscription_id)); 330 } 331 328 332 function wpsap_connect_portal_url($customer_id,$return_url){ 329 333 $session = wpsap_connect_request('POST','v1/portal',array( -
sell-ads/trunk/inc/helper.php
r3626067 r3627752 2 2 if ( ! defined( 'ABSPATH' ) ) exit; 3 3 4 /** 5 * Baut das kopierbare Feld fuer die PHP-Einbindung einer Kampagne. 6 * 7 * Rueckgabe ist fertiges HTML und wird in der Spalte direkt ausgegeben - 8 * frueher lag ein esc_html() darum, das aus dem <input> sichtbaren Rohtext 9 * machte. Escapt wird deshalb nur noch der dynamische Wert selbst. 10 */ 4 11 function wpsap_plugin_php_function($content){ 5 6 $html = '<input type="text" readonly value="<?php echo wpsap_show('.esc_attr($content).'); ?>">'; 7 return $html; 8 12 $id = absint($content); 13 $value = '<?php echo wpsap_show('.$id.'); ?>'; 14 return wpsap_copy_field($value); 9 15 } 10 16 17 /** 18 * Baut das kopierbare Feld fuer die Shortcode-Einbindung einer Kampagne. 19 */ 11 20 function wpsap_shortcode_input($content){ 12 $html = '<input type="text" readonly value="[wpsap_ads id='.esc_attr($content).']">'; 13 return $html; 21 $id = absint($content); 22 $value = '[wpsap_ads id='.$id.']'; 23 return wpsap_copy_field($value); 24 } 25 26 /** 27 * Gemeinsames Markup fuer die Kopier-Felder der Kampagnenliste: ein 28 * schreibgeschuetztes Eingabefeld mit Betrag daneben ein Kopier-Button. 29 * Der zugehoerige Klick-Handler liegt im admin_footer der Liste 30 * (inc/campaign_fields.php). 31 */ 32 function wpsap_copy_field($value){ 33 return '<span class="wpsap-copy">' 34 .'<input type="text" class="wpsap-copy__input" readonly value="'.esc_attr($value).'">' 35 .'<button type="button" class="wpsap-copy__btn" title="'.esc_attr__('Copy','wpsap_ads_plugin').'">' 36 .'<span class="dashicons dashicons-admin-page"></span>' 37 .'</button>' 38 .'</span>'; 14 39 } 15 40 … … 43 68 44 69 /** 70 * Entfernt Motiv und Ziellink einer endgueltig toten Bestellung restlos: 71 * das Attachment aus der Mediathek (Datei inkl. resized Varianten, ohne 72 * Papierkorb) sowie die Meta order_image/order_url. Jedes Motiv gehoert zu 73 * genau einer Bestellung, deshalb ist das harte Loeschen unbedenklich. 74 * 75 * Die Attachment-ID steht seit dem Upload in wpsap_order_image_id; fuer 76 * Bestandsbestellungen ohne dieses Meta wird sie aus der gespeicherten URL 77 * aufgeloest. 78 */ 79 function wpsap_delete_order_media($order_id){ 80 $attachment_id = (int) get_post_meta($order_id,'wpsap_order_image_id',true); 81 if(!$attachment_id){ 82 $image_url = get_post_meta($order_id,'order_image',true); 83 if($image_url){ 84 $attachment_id = attachment_url_to_postid($image_url); 85 } 86 } 87 88 if($attachment_id && get_post_type($attachment_id) === 'attachment'){ 89 wp_delete_attachment($attachment_id,true); 90 } 91 92 delete_post_meta($order_id,'order_image'); 93 delete_post_meta($order_id,'order_url'); 94 delete_post_meta($order_id,'wpsap_order_image_id'); 95 } 96 97 /** 45 98 * Ablehnen heisst: das Abo bei Stripe beenden. Der lokale Status wird erst 46 99 * danach gesetzt - frueher lief es umgekehrt, wodurch Plugin und Stripe … … 62 115 ) ); 63 116 117 // Erst nach dem gesicherten Statuswechsel: Motiv und Link sind jetzt tot. 118 wpsap_delete_order_media($order_id); 119 120 return true; 121 } 122 123 /** 124 * Ablauf einer unbeantworteten Bestellung nach 14 Tagen. Wie das Ablehnen 125 * beendet es das Abo bei Stripe - weil das noch im Trial steht, entsteht dabei 126 * keine Rechnung, der Kaeufer wird also nicht belastet. Getrennt von 127 * wpsap_reject_ads(), damit der Zustand in der Liste als "Expired" (statt 128 * "Rejected") erkennbar bleibt und das Ablaufdatum festgehalten wird. 129 */ 130 function wpsap_expire_ads($order_id){ 131 $subscription_id = get_post_meta($order_id,'wpsap_subscription_id',true); 132 if($subscription_id){ 133 $result = wpsap_stripe_cancel_subscription($subscription_id); 134 if(is_wp_error($result)){ 135 return $result; 136 } 137 } 138 139 // Ablaufdatum = Bestelldatum + 14 Tage, dieselbe Frist wie in 140 // wpsap_order_days_left(). Festgehalten, damit die Liste "Expired on <Tag>" 141 // zeigen kann, ohne es jedes Mal neu herzuleiten. 142 $placed = get_post_time('U',true,$order_id); 143 $expires = $placed ? $placed + 14 * DAY_IN_SECONDS : time(); 144 update_post_meta($order_id,'wpsap_expired_on',$expires); 145 146 update_post_meta($order_id,"wpsap_order_status",'expired'); 147 wp_update_post( array( 148 'ID' => $order_id, 149 'post_status' => 'rejected', 150 ) ); 151 152 // Wie beim Ablehnen: Motiv und Link sind mit dem Ablauf tot. 153 wpsap_delete_order_media($order_id); 154 64 155 return true; 65 156 } … … 80 171 return new WP_Error('wpsap_subscription_gone',__('This subscription is no longer active at Stripe.','wpsap_ads_plugin')); 81 172 } 173 174 // Erst mit der Annahme wird belastet: das Abo lief bis hierher im Trial 175 // (siehe wpsap_stripe_build_checkout). Das Beenden des Trials stellt die 176 // erste Rechnung sofort aus. 177 $charged = wpsap_stripe_end_trial($subscription_id); 178 if(is_wp_error($charged)){ 179 return $charged; 180 } 82 181 } 83 182 -
sell-ads/trunk/inc/hooks.php
r3626067 r3627752 144 144 } 145 145 146 $order_date = get_the_date( 'l F j, Y',$order_id); 147 $expected_date = date('l F j, Y',strtotime($order_date."+ 7days")); 148 146 // Die Datumsangaben der Bestaetigungstabelle berechnet confirm.php 147 // selbst aus dem Bestellzeitpunkt - hier ist nichts vorzubereiten. 149 148 require WPSAP_Plugin_Path.'inc/page/confirm.php'; 150 149 die(); … … 229 228 // neu registriert - die alte Registrierung ueberschrieb ihn global fuer 230 229 // alle Post-Types. 230 231 232 /* -------------------------------------------------------------------------- 233 * Klick-Tracking ueber /goto/<slug> 234 * 235 * Die veroeffentlichte Anzeige verlinkt nicht mehr direkt auf die Zielseite, 236 * sondern ueber diesen Endpoint (inc/shortcode.php). Er zaehlt den Klick auf 237 * der Kampagne (wpsap_click_count) und leitet dann zur Zielseite weiter. Der 238 * Zaehler erscheint in der Spalte "Clicks" der Kampagnenliste. 239 * ------------------------------------------------------------------------- */ 240 241 add_filter('query_vars','wpsap_goto_query_var'); 242 function wpsap_goto_query_var($vars){ 243 $vars[] = 'wpsap_goto'; 244 return $vars; 245 } 246 247 add_action('init','wpsap_goto_rewrite'); 248 function wpsap_goto_rewrite(){ 249 add_rewrite_rule('^goto/([^/]+)/?$','index.php?wpsap_goto=$matches[1]','top'); 250 251 // Beim reinen Plugin-Update laeuft der Aktivierungshook nicht - ohne 252 // diesen Guard griffe die Rewrite-Rule auf cybie.de erst nach manuellem 253 // Neu-Speichern der Permalinks. Der Flush erfolgt genau einmal je Version. 254 if(get_option('wpsap_rewrite_version') !== WPSAP_Version){ 255 flush_rewrite_rules(false); 256 update_option('wpsap_rewrite_version',WPSAP_Version); 257 } 258 } 259 260 add_action('template_redirect','wpsap_handle_goto'); 261 function wpsap_handle_goto(){ 262 $slug = get_query_var('wpsap_goto'); 263 if($slug === '' || $slug === null){ 264 return; 265 } 266 267 $home = home_url('/'); 268 269 // Slug -> Kampagne. Numerischer Wert wird als ID behandelt, sonst ueber 270 // den post_name aufgeloest. Der CPT ist nicht oeffentlich, get_page_by_path 271 // findet ihn trotzdem, weil der Post-Type explizit uebergeben wird. 272 $campaign = null; 273 if(ctype_digit((string) $slug)){ 274 $maybe = get_post(absint($slug)); 275 if($maybe && $maybe->post_type === 'ads_campaign'){ 276 $campaign = $maybe; 277 } 278 } 279 if(!$campaign){ 280 $campaign = get_page_by_path(sanitize_title($slug),OBJECT,'ads_campaign'); 281 } 282 283 if(!$campaign){ 284 nocache_headers(); 285 wp_redirect($home,302); 286 exit; 287 } 288 289 // Zielseite = URL der aktuell veroeffentlichten Anzeige dieses Slots. 290 $target = ''; 291 foreach(wpsap_get_active_ads($campaign->ID) as $ad){ 292 $url = get_post_meta($ad->ID,'order_url',true); 293 if(!empty($url)){ 294 $target = $url; 295 break; 296 } 297 } 298 299 if(empty($target)){ 300 nocache_headers(); 301 wp_redirect($home,302); 302 exit; 303 } 304 305 // Selbst-Klicks von Redakteuren verfaelschen die Statistik nicht. 306 if(!(is_user_logged_in() && current_user_can('edit_posts'))){ 307 $count = (int) get_post_meta($campaign->ID,'wpsap_click_count',true); 308 update_post_meta($campaign->ID,'wpsap_click_count',$count + 1); 309 } 310 311 nocache_headers(); 312 // Ziel ist eine fremde Domain - wp_safe_redirect() wuerde das blocken. 313 wp_redirect(esc_url_raw($target),302); 314 exit; 315 } -
sell-ads/trunk/inc/page/confirm.php
r3626502 r3627752 43 43 // Fuer die Seitenspalte: beide Zahlungswege legen diese Felder an - 44 44 // wpsap_sync_order_from_session() ebenso wie wpsap_create_test_order(). 45 $wpsap_place_id = (int) get_post_meta($order_id,'wpsap_place_id',true);46 $wpsap_campaign_label = '';47 if($wpsap_place_id){48 $wpsap_campaign_label = (string) get_post_meta($wpsap_place_id,'wpsap_campaign_title',true);49 if($wpsap_campaign_label === ''){50 $wpsap_campaign_label = (string) get_the_title($wpsap_place_id);51 }52 }53 54 45 $wpsap_price_label = ''; 55 46 $wpsap_order_total = (int) get_post_meta($order_id,'order_total',true); … … 58 49 $wpsap_price_label = number_format_i18n($wpsap_order_total / 100,2).' '.strtoupper((string) get_post_meta($order_id,'wpsap_currency',true)); 59 50 } 51 52 // Datumsangaben der Bestaetigungstabelle. Bezugspunkt ist der Zeitpunkt der 53 // Bestellung; wp_date() wendet die WP-Zeitzone an. Der Kaeufer-Flow ist 54 // durchgaengig englisch, deshalb erzwingt switch_to_locale('en_US') englische 55 // Monatsnamen auch auf einer de_DE-Site. Das Billing-Datum ist eine 56 // Anzeige-Schaetzung fuer den Kaeufer (Prueffrist bis 14 Tage + ein Abo-Monat) - 57 // Stripe bucht im Abo technisch bereits beim Checkout. 58 $wpsap_order_ts = get_post_timestamp($order_id); 59 $wpsap_switched_locale = switch_to_locale('en_US'); 60 $wpsap_submitted_date = $wpsap_order_ts ? wp_date('F j, Y',$wpsap_order_ts) : ''; 61 $wpsap_billing_date = $wpsap_order_ts ? wp_date('F j, Y',strtotime('+14 days +1 month',$wpsap_order_ts)) : ''; 62 if($wpsap_switched_locale){ restore_previous_locale(); } 60 63 61 64 // Solange Bild oder Link fehlen, steht der Kaeufer noch im Upload-Schritt. … … 85 88 <?php } ?> 86 89 87 <div class="wpsap-flow__grid"> 88 89 <aside class="wpsap-flow__aside"> 90 <div class="wpsap-flow__site"><?php echo esc_html(get_bloginfo('name')); ?></div> 91 92 <?php if($wpsap_campaign_label !== '' || $wpsap_price_label !== ''){ ?> 93 <div class="wpsap-flow__facts"> 94 <?php if($wpsap_campaign_label !== ''){ ?> 95 <div class="wpsap-flow__fact"> 96 <span class="wpsap-flow__fact-label"><?php esc_html_e('Ad space','wpsap_ads_plugin'); ?></span> 97 <span class="wpsap-flow__fact-value"><?php echo esc_html($wpsap_campaign_label); ?></span> 98 </div> 99 <?php } ?> 100 <?php if($wpsap_price_label !== ''){ ?> 101 <div class="wpsap-flow__fact"> 102 <span class="wpsap-flow__fact-label"><?php esc_html_e('Per month','wpsap_ads_plugin'); ?></span> 103 <span class="wpsap-flow__fact-value"><?php echo esc_html($wpsap_price_label); ?></span> 104 </div> 105 <?php } ?> 106 </div> 90 <?php /* Schritt 1: Upload - einspaltig zentriert. Bewusst NICHT im 91 Zwei-Spalten-Grid: die Aside gehoert erst auf die Bestaetigung. 92 Sichtbar bzw. verborgen nur ueber display:none - der gezeigte 93 Zustand kommt aus dem Stylesheet, damit wp-sap.js ihn per 94 .hide()/.show() korrekt umschalten kann. */ ?> 95 <section class="upload_ads_area" <?php if($wpsap_step_done){ echo 'style="display:none"'; } ?>> 96 <div class="wpsap-single"> 97 98 <h1 class="wpsap-step__title">Upload your Ad</h1> 99 100 <p class="wpsap-step__lead">Attention: Make sure that you upload your desired advertising image (JPG, PNG, GIF) in the preferred resolution (up to max. 10 MB) and add the correct link to your offer.</p> 101 102 <?php if(trim($note_on_upload_page) !== ''){ ?> 103 <div class="wpsap-note"><?php echo esc_html($note_on_upload_page); ?></div> 107 104 <?php } ?> 108 105 109 <?php if(trim($note_on_thanks_page) !== ''){ ?> 110 <div class="wpsap-flow__aside-note"><?php echo esc_html($note_on_thanks_page); ?></div> 111 <?php } ?> 112 113 <p class="wpsap-flow__copyright">Copyright <?php echo esc_html(get_bloginfo('name')); ?></p> 114 </aside> 115 116 <div class="wpsap-flow__main"> 117 118 <section class="upload_ads_area" style="<?php echo $wpsap_step_done ? 'display:none' : 'display:block'; ?>"> 119 120 <h1 class="wpsap-step__title">Upload your Ad</h1> 121 <p class="wpsap-step__lead">Attention: Make sure that you upload your desired advertising image (JPG, PNG, GIF) in the preferred resolution (up to max. 10 MB) and add the correct link to your offer.</p> 122 123 <?php if(trim($note_on_upload_page) !== ''){ ?> 124 <div class="wpsap-note"><?php echo esc_html($note_on_upload_page); ?></div> 125 <?php } ?> 126 127 <?php /* Nimmt die Meldungen auf, fuer die wp-sap.js bis 1.8.0 128 alert() aufrief. */ ?> 129 <div class="wpsap-alert" id="wpsap_form_error" role="alert"></div> 130 131 <form action="" id="wp_sap_form" method="post" enctype="multipart/form-data" class="wpsap-card"> 132 <div class="file-area"> 133 <input type="hidden" name="action" value="wpsap_upload_image"> 134 <input type="hidden" name="security" id="wpsap_security" value=""> 135 <?php /* Die Bestellung wird serverseitig ueber die Session-ID 136 aufgeloest. Eine mitgeschickte order_id waere im Browser 137 frei aenderbar. */ ?> 138 <input type="hidden" name="session" value="<?php echo esc_attr($session_id); ?>"> 139 <input type="file" name="image" id="images" accept="image/*" required="required"> 140 <div class="file-dummy"> 141 <?php if($image_uploaded){ ?> 142 <div class="default"> 143 <img src="<?php echo esc_url($image_uploaded); ?>" alt=""> 144 <h6>Click on the image to change it</h6> 145 </div> 146 <?php } else { ?> 147 <div class="default"> 148 <span class="wpsap-drop__icon" aria-hidden="true"> 149 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" focusable="false"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><path d="M21 15l-5-5L5 21"/></svg> 150 </span> 151 <h6>Drop image here or click to upload</h6> 152 </div> 153 <?php } ?> 154 <div class="success" id="image_uploaded_area"> 155 <h5>Image Uploading....</h5> 156 </div> 106 <?php /* Nimmt die Meldungen auf, fuer die wp-sap.js bis 1.8.0 107 alert() aufrief. */ ?> 108 <div class="wpsap-alert" id="wpsap_form_error" role="alert"></div> 109 110 <form action="" id="wp_sap_form" method="post" enctype="multipart/form-data" class="wpsap-card"> 111 <div class="file-area"> 112 <input type="hidden" name="action" value="wpsap_upload_image"> 113 <input type="hidden" name="security" id="wpsap_security" value=""> 114 <?php /* Die Bestellung wird serverseitig ueber die Session-ID 115 aufgeloest. Eine mitgeschickte order_id waere im Browser 116 frei aenderbar. */ ?> 117 <input type="hidden" name="session" value="<?php echo esc_attr($session_id); ?>"> 118 <input type="file" name="image" id="images" accept="image/*" required="required"> 119 <div class="file-dummy"> 120 <?php if($image_uploaded){ ?> 121 <div class="default"> 122 <img src="<?php echo esc_url($image_uploaded); ?>" alt=""> 123 <h6>Click on the image to change it</h6> 124 </div> 125 <?php } else { ?> 126 <div class="default"> 127 <span class="wpsap-drop__icon" aria-hidden="true"> 128 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" focusable="false"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><path d="M21 15l-5-5L5 21"/></svg> 129 </span> 130 <h6>Drop image here or click to upload</h6> 131 </div> 132 <?php } ?> 133 <div class="success" id="image_uploaded_area"> 134 <h5>Image Uploading....</h5> 157 135 </div> 158 136 </div> 159 160 <div class="wpsap-field"> 161 <input type="submit" value="Upload image" id="hidden_upload_image_btn" style="display:none;"> 162 <button type="button" id="upload_image_btn" class="wpsap-btn wpsap-btn--secondary">Upload image</button> 163 </div> 164 165 <div class="wpsap-field"> 166 <label class="wpsap-field__label" for="site_url">Link to your offer</label> 167 <input type="text" id="site_url" name="site_url" value="<?php echo esc_url($link_added); ?>" placeholder="Paste your product link here..."> 168 </div> 169 </form> 170 137 </div> 138 139 <div class="wpsap-field"> 140 <input type="submit" value="Upload image" id="hidden_upload_image_btn" style="display:none;"> 141 <?php /* Der Upload-Button ist bewusst blau (SS3) und damit von 142 der schwarzen Primaeraktion "Next" unterscheidbar. */ ?> 143 <button type="button" id="upload_image_btn" class="wpsap-btn wpsap-btn--upload">Upload image</button> 144 </div> 145 146 <div class="wpsap-field"> 147 <label class="wpsap-field__label" for="site_url">Link to your offer</label> 148 <input type="text" id="site_url" name="site_url" value="<?php echo esc_url($link_added); ?>" placeholder="Paste your product link here..."> 149 </div> 150 </form> 151 152 <?php if($terms || $cencel || $cencel_policy){ ?> 153 <ul class="wpsap-links"> 154 <?php if($terms){ ?> 155 <li><a href="<?php echo esc_url(get_the_permalink($terms)); ?>" target="_blank" rel="noopener noreferrer"><?php echo esc_html(get_the_title($terms)); ?></a></li> 156 <?php } ?> 171 157 <?php if($cencel){ ?> 172 <ul class="wpsap-links"> 173 <li><a href="<?php echo esc_url(get_the_permalink($cencel)); ?>"><?php echo esc_html(get_the_title($cencel)); ?></a></li> 174 </ul> 158 <li><a href="<?php echo esc_url(get_the_permalink($cencel)); ?>" target="_blank" rel="noopener noreferrer"><?php echo esc_html(get_the_title($cencel)); ?></a></li> 175 159 <?php } ?> 176 177 <div class="wpsap-actions"> 178 <input type="hidden" id="ads_image" value="<?php echo esc_url($image_uploaded); ?>"> 179 <button type="button" class="btn next wpsap-btn wpsap-btn--primary">Next</button> 180 </div> 181 182 </section> 183 184 <section class="purchased_area" style="<?php echo $wpsap_step_done ? 'display:block' : 'display:none'; ?>"> 185 186 <h1 class="wpsap-step__title">Your order has been placed</h1> 187 <?php /* Kein Erstattungsversprechen: wpsap_reject_ads() kuendigt 188 das Abo bei Stripe, mehr nicht. Bis 1.8.1 stand hier 189 "you will automatically get your money back" - das 190 loeste der Code nie ein. */ ?> 191 <p class="wpsap-step__lead">The advertisement has been successfully sent to the website owner. It may take up to 14 days for the ad to be reviewed and accepted. If your request is rejected or stays unanswered, your subscription is cancelled automatically and you will not be charged again. If your ad has been accepted, your advertising partnership will remain active until you or the website owner cancel it.</p> 192 193 <table> 194 <tbody> 195 <tr> 196 <th scope="row">Start date</th> 197 <td>After the website owner accept your ads.</td> 198 </tr> 199 <tr> 200 <th scope="row">End date</th> 201 <td>Until someone quits</td> 202 </tr> 203 </tbody> 204 </table> 205 206 <div class="link_input_desc_area"> 207 <div class="input-group"> 208 <?php /* Fuehrt in das Billing Portal von Stripe - dort kann der Kaeufer 209 selbst kuendigen und seine Rechnungen einsehen. */ ?> 210 <input id="foo" type="text" class="link_copied_button" readonly value="<?php echo esc_url(add_query_arg(array('action' => 'wpsap_billing_portal','session' => $session_id),admin_url('admin-post.php'))); ?>"> 211 <span class="input-group-button"> 212 <button class="wpsap_ads_copy_btn" type="button" data-clipboard-target="#foo" title="Copy to clipboard" aria-label="Copy to clipboard"> 213 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg> 214 </button> 215 </span> 216 </div> 217 218 <div class="wpsap-copy-hint"> 219 <span class="wpsap-copy-hint__icon" aria-hidden="true"> 220 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" focusable="false"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg> 221 </span> 222 <p>Save this link. With this link you can cancel your monthly advertising space rental in the future. If you want to cancel, you can use this link or simply ask the website owner directly.</p> 223 </div> 224 </div> 225 226 <?php if($cencel_policy || $terms){ ?> 227 <ul class="wpsap-links"> 228 <?php if($cencel_policy){ ?> 229 <li><a href="<?php echo esc_url(get_the_permalink($cencel_policy)); ?>"><?php echo esc_html(get_the_title($cencel_policy)); ?></a></li> 230 <?php } ?> 231 <?php if($terms){ ?> 232 <li><a href="<?php echo esc_url(get_the_permalink($terms)); ?>"><?php echo esc_html(get_the_title($terms)); ?></a></li> 233 <?php } ?> 234 </ul> 160 <?php if($cencel_policy){ ?> 161 <li><a href="<?php echo esc_url(get_the_permalink($cencel_policy)); ?>" target="_blank" rel="noopener noreferrer"><?php echo esc_html(get_the_title($cencel_policy)); ?></a></li> 235 162 <?php } ?> 236 237 <div class="wpsap-actions">238 <button type="button" class="btn_back wpsap-btn wpsap-btn--quiet">Back</button> 239 <button type="button" class="btn_finish wpsap-btn wpsap-btn--primary" data-link="<?php echo esc_url(get_site_url()); ?>">Finish</button>240 < /div>241 242 </ section>163 </ul> 164 <?php } ?> 165 166 <div class="wpsap-actions"> 167 <input type="hidden" id="ads_image" value="<?php echo esc_url($image_uploaded); ?>"> 168 <button type="button" class="btn next wpsap-btn wpsap-btn--primary">Next</button> 169 </div> 243 170 244 171 </div> 245 </div> 172 </section> 173 174 <?php /* Schritt 2: Bestaetigung - einspaltig, zentriert wie der 175 Upload-Schritt. Die frueher linke Aside (Logo, Fakten, Copyright) 176 wurde bewusst entfernt; nur .wpsap-flow__main traegt den Inhalt. */ ?> 177 <section class="purchased_area" <?php if(!$wpsap_step_done){ echo 'style="display:none"'; } ?>> 178 179 <div class="wpsap-flow__main"> 180 181 <span class="wpsap-badge" aria-hidden="true"> 182 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round" focusable="false"><path d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"/><path d="m9 12 2 2 4-4"/></svg> 183 </span> 184 185 <h1 class="wpsap-step__title">Your order has been placed</h1> 186 <?php /* Kein Erstattungsversprechen: wpsap_reject_ads() kuendigt 187 das Abo bei Stripe, mehr nicht. Bis 1.8.1 stand hier 188 "you will automatically get your money back" - das 189 loeste der Code nie ein. */ ?> 190 <p class="wpsap-step__lead">The advertisement has been successfully sent to the website owner. It may take up to 14 days for the ad to be reviewed and approved. If your request is rejected or remains unanswered, your subscription will be cancelled automatically, and you will not be charged. If your ad is approved, your advertising partnership will remain active until you or the website owner cancels it.</p> 191 192 <?php /* Stand bis 1.8.3 in der linken Aside. Die Notiz ist optional 193 konfigurierbar und darf mit der entfernten Spalte nicht 194 verschwinden - sie sitzt jetzt hier im Hauptbereich. */ ?> 195 <?php if(trim($note_on_thanks_page) !== ''){ ?> 196 <div class="wpsap-note"><?php echo esc_html($note_on_thanks_page); ?></div> 197 <?php } ?> 198 199 <table> 200 <tbody> 201 <tr> 202 <th scope="row">Offer Submitted</th> 203 <td><?php echo esc_html($wpsap_submitted_date); ?></td> 204 </tr> 205 <tr> 206 <th scope="row">Expected start date</th> 207 <td>Waiting for website owner to review (Maximum 14 days)</td> 208 </tr> 209 <tr> 210 <th scope="row">End date</th> 211 <td>Until you or website owner cancels</td> 212 </tr> 213 <tr> 214 <th scope="row">Billing date</th> 215 <td><?php echo esc_html($wpsap_billing_date); ?></td> 216 </tr> 217 </tbody> 218 </table> 219 220 <div class="link_input_desc_area"> 221 <div class="input-group"> 222 <?php /* Fuehrt in das Billing Portal von Stripe - dort kann der Kaeufer 223 selbst kuendigen und seine Rechnungen einsehen. */ ?> 224 <input id="foo" type="text" class="link_copied_button" readonly value="<?php echo esc_url(add_query_arg(array('action' => 'wpsap_billing_portal','session' => $session_id),admin_url('admin-post.php'))); ?>"> 225 <span class="input-group-button"> 226 <button class="wpsap_ads_copy_btn" type="button" data-clipboard-target="#foo" title="Copy to clipboard" aria-label="Copy to clipboard"> 227 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg> 228 </button> 229 </span> 230 </div> 231 232 <div class="wpsap-copy-hint"> 233 <span class="wpsap-copy-hint__icon" aria-hidden="true"> 234 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" focusable="false"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg> 235 </span> 236 <p>Please save this link. You can use it at any time to manage your subscription or cancel your monthly advertising space rental. If you wish to cancel, simply use this link or contact the website owner directly.</p> 237 </div> 238 </div> 239 240 <div class="wpsap-actions"> 241 <button type="button" class="btn_back wpsap-btn wpsap-btn--quiet">Back</button> 242 <button type="button" class="btn_finish wpsap-btn wpsap-btn--primary" data-link="<?php echo esc_url(get_site_url()); ?>">Finish</button> 243 </div> 244 245 </div> 246 </section> 247 246 248 </div> 247 249 -
sell-ads/trunk/inc/page/style.css
r3626502 r3627752 107 107 108 108 /* ========================================================================== 109 Zweispaltiger Rahmen109 Rahmen: Upload einspaltig (SS3), Bestaetigung zweispaltig (SS4) 110 110 ========================================================================== */ 111 111 … … 120 120 } 121 121 122 .wpsap-flow__grid { 122 /* Die Bestaetigung ist einspaltig (die frueher linke Aside mit Logo, Fakten 123 und Copyright ist entfernt). flex:1 1 auto fuellt die Resthoehe unter dem 124 Flex-#wpsap-flow - das tat vorher .wpsap-flow__grid. */ 125 .purchased_area { 123 126 flex: 1 1 auto; 124 display: grid; 125 grid-template-columns: minmax(240px, 320px) 1fr; 126 align-items: stretch; 127 } 128 129 .wpsap-flow__aside { 130 background-color: var(--wpsap-canvas-soft, #fafafa); 131 border-right: 1px solid var(--wpsap-line, #dcdfe3); 132 padding: 2.5rem 1.75rem; 133 display: flex; 134 flex-direction: column; 135 gap: 1.5rem; 136 } 137 127 } 128 129 /* Bleibt fuer den Upload-Schritt (Marken-Text als Logo-Fallback). */ 138 130 #wpsap-flow .wpsap-flow__site { 139 131 font-size: 22px; … … 144 136 } 145 137 146 .wpsap-flow__facts { 138 /* Bestaetigung: Inhalt zentriert mit fester Maximalbreite (SS4). Die 139 Blanket-Regel gibt jedem direkten Kind dieselbe Breite, damit Badge, Titel, 140 Tabelle und Aktionszeile buendig uebereinanderstehen. */ 141 .wpsap-flow__main { 142 padding: 3rem 1.75rem; 147 143 display: flex; 148 144 flex-direction: column; 149 gap: .75rem; 150 } 151 152 .wpsap-flow__fact { 153 display: flex; 154 flex-direction: column; 155 gap: .15rem; 156 } 157 158 #wpsap-flow .wpsap-flow__fact-label { 159 font-size: 12px; 145 align-items: center; 146 text-align: center; 147 } 148 149 .wpsap-flow__main > * { 150 width: 100%; 151 max-width: 520px; 152 } 153 154 /* Schritt 1 ist einspaltig und ohne Aside. wp-sap.js schaltet die Sichtbarkeit 155 per .hide()/.show(); der gezeigte Zustand kommt aus dem Stylesheet, das 156 Markup setzt inline nur display:none fuer den verborgenen Schritt - so 157 ueberschreibt keine Inline-Regel das Grid der Bestaetigung. */ 158 .upload_ads_area { 159 flex: 1 1 auto; 160 padding: 3rem 1.25rem; 161 } 162 163 .wpsap-single { 164 width: 100%; 165 max-width: 560px; 166 margin: 0 auto; 167 } 168 169 /* Nur der Kopfbereich des Upload-Schritts ist zentriert; Karte und Felder 170 darunter bleiben linksbuendig. */ 171 .wpsap-single > .wpsap-flow__brand, 172 .wpsap-single > .wpsap-step__title, 173 .wpsap-single > .wpsap-step__subtitle, 174 .wpsap-single > .wpsap-step__lead { 175 text-align: center; 176 } 177 178 .wpsap-single > .wpsap-flow__brand { 179 margin-bottom: 1.5rem; 180 } 181 182 .upload_ads_area .wpsap-links { 183 justify-content: center; 184 } 185 186 187 /* ========================================================================== 188 Logo, Untertitel und Erfolgs-Badge 189 ========================================================================== */ 190 191 /* Logo (get_custom_logo) oben im Upload-Schritt bzw. in der Aside. In der 192 Aside bleibt es linksbuendig wie die uebrigen Angaben. */ 193 #wpsap-flow .wpsap-flow__brand img, 194 #wpsap-flow .custom-logo { 195 display: inline-block; 196 width: auto; 197 height: auto; 198 max-height: 52px; 199 } 200 201 #wpsap-flow .wpsap-step__subtitle { 202 font-size: 16px; 160 203 font-weight: 600; 161 letter-spacing: .04em; 162 text-transform: uppercase; 163 color: var(--wpsap-muted, #6b7280); 164 } 165 166 #wpsap-flow .wpsap-flow__fact-value { 167 font-size: 16px; 168 font-weight: 500; 169 color: var(--wpsap-ink, #161616); 170 overflow-wrap: anywhere; 171 } 172 173 #wpsap-flow .wpsap-flow__aside-note { 174 font-size: 14px; 175 line-height: 1.55; 204 line-height: 1.35; 176 205 color: var(--wpsap-ink-soft, #4a4a4a); 177 white-space: pre-line; 178 } 179 180 /* Schiebt das Copyright ans untere Ende, ohne es dort festzunageln - 181 bei viel Inhalt rutscht es einfach mit. */ 182 #wpsap-flow .wpsap-flow__copyright { 183 margin-top: auto; 184 padding-top: 1.5rem; 185 font-size: 13px; 186 color: var(--wpsap-muted, #6b7280); 187 } 188 189 .wpsap-flow__main { 190 padding: 2.5rem 1.75rem 3rem; 206 margin: 0 0 1rem 0; 207 } 208 209 /* Siegel mit Haken ueber dem Titel der Bestaetigung (SS4). */ 210 .wpsap-badge { 191 211 display: flex; 192 212 justify-content: center; 193 } 194 195 /* Die beiden Schritte behalten ihre Bestandsklassen: inc/page/wp-sap.js 196 blendet sie ueber .hide()/.show() um und setzt dabei display:block. */ 197 .upload_ads_area, 198 .purchased_area { 199 width: 100%;200 max-width: 640px;213 color: var(--wpsap-ink, #161616); 214 margin-bottom: 1rem; 215 } 216 217 #wpsap-flow .wpsap-badge svg { 218 display: block; 219 width: 64px; 220 height: 64px; 201 221 } 202 222 … … 331 351 } 332 352 353 /* Blauer Upload-Button (SS3) - hebt das Hochladen von der schwarzen 354 Primaeraktion "Next" ab. Fuellt die Breite der Karte. */ 355 #wpsap-flow .wpsap-btn--upload { 356 width: 100%; 357 background-color: #337ab6; 358 border-color: #337ab6; 359 color: #fff; 360 } 361 362 #wpsap-flow .wpsap-btn--upload:hover { 363 background-color: #2b6698; 364 border-color: #2b6698; 365 } 366 333 367 #wpsap-flow .wpsap-btn[disabled] { 334 368 opacity: .6; … … 507 541 text-align: left; 508 542 vertical-align: top; 543 /* Beide Spalten identisch: schwarze Schrift auf weissem Grund. Explizit 544 gesetzt, damit kein Theme-CSS auf der Bestaetigungsseite durchschlaegt. */ 545 color: #000; 546 background-color: #fff; 509 547 } 510 548 511 549 #wpsap-flow .purchased_area th { 512 550 width: 40%; 513 font-weight: 600;514 color: var(--wpsap-ink, #161616);515 background-color: var(--wpsap-canvas-soft, #fafafa);516 551 } 517 552 … … 521 556 border-radius: var(--wpsap-radius-sm, 5px); 522 557 padding: 1rem; 558 /* Der Hauptbereich zentriert seinen Inhalt (SS4); Feld und Hinweis bleiben 559 darin aber linksbuendig. */ 560 text-align: left; 523 561 } 524 562 … … 604 642 } 605 643 606 .wpsap-flow__grid {607 grid-template-columns: 1fr;608 }609 610 .wpsap-flow__aside {611 border-right: 0;612 border-bottom: 1px solid var(--wpsap-line, #dcdfe3);613 padding: 1.75rem 1.25rem;614 gap: 1.25rem;615 }616 617 /* Gestapelt gehoert das Copyright unter den Inhalt der Spalte,618 nicht ans Ende eines nicht mehr vorhandenen Streifens. */619 #wpsap-flow .wpsap-flow__copyright {620 margin-top: 0;621 padding-top: 0;622 }623 624 644 .wpsap-flow__main { 625 645 padding: 1.75rem 1.25rem 2.5rem; -
sell-ads/trunk/inc/settings.php
r3626502 r3627752 94 94 <?php $this->wpsap_notify_callback(); ?> 95 95 96 <details class="wpsap-more"> 97 <summary><?php esc_html_e( 'Pages and texts','wpsap_ads_plugin' ); ?></summary> 96 <h2 class="wpsap-step"><?php esc_html_e( 'Pages and texts','wpsap_ads_plugin' ); ?></h2> 98 97 <table class="form-table" role="presentation"> 99 98 <tr> 100 <th scope="row"><label for="terms_condtions_0"><?php esc_html_e( 'Terms of Service ','wpsap_ads_plugin' ); ?></label></th>99 <th scope="row"><label for="terms_condtions_0"><?php esc_html_e( 'Terms of Service (Displayed on the upload page)','wpsap_ads_plugin' ); ?></label></th> 101 100 <td><?php $this->wpsap_terms_condtions_0_callback(); ?></td> 102 101 </tr> 103 102 <tr> 104 <th scope="row"><label for="template_cencel_subscription_1"><?php esc_html_e( 'Uploading Policy ','wpsap_ads_plugin' ); ?></label></th>103 <th scope="row"><label for="template_cencel_subscription_1"><?php esc_html_e( 'Uploading Policy (Displayed on the upload page)','wpsap_ads_plugin' ); ?></label></th> 105 104 <td><?php $this->wpsap_template_cencel_subscription_1_callback(); ?></td> 106 105 </tr> 107 106 <tr> 108 <th scope="row"><label for="template_cencel_policy_1"><?php esc_html_e( 'Cancel Policy ','wpsap_ads_plugin' ); ?></label></th>107 <th scope="row"><label for="template_cencel_policy_1"><?php esc_html_e( 'Cancel Policy (Displayed on the upload page)','wpsap_ads_plugin' ); ?></label></th> 109 108 <td><?php $this->wpsap_template_cencel_policy_1_callback(); ?></td> 110 109 </tr> 111 110 <tr> 112 <th scope="row"><label for="notification_2"><?php esc_html_e( 'Note for the buyer ','wpsap_ads_plugin' ); ?></label></th>111 <th scope="row"><label for="notification_2"><?php esc_html_e( 'Note for the buyer (Shown on the Stripe payment page)','wpsap_ads_plugin' ); ?></label></th> 113 112 <td><?php $this->wpsap_notification_2_callback(); ?></td> 114 113 </tr> … … 122 121 </tr> 123 122 </table> 124 </details>125 123 126 124 <?php submit_button(); ?> … … 142 140 border: 1px solid #dcdcde; 143 141 border-left: 4px solid #2271b1; 144 }145 .wpsap-settings .wpsap-more {146 margin-top: 32px;147 padding-top: 8px;148 border-top: 1px solid #dcdcde;149 }150 .wpsap-settings .wpsap-more > summary {151 cursor: pointer;152 font-size: 1.15em;153 font-weight: 600;154 padding: 8px 0;155 142 } 156 143 </style> … … 241 228 $status = wpsap_connect_account_status(); 242 229 ?> 243 <p>Payments run through the Sell Ads platform at <code>sellads.cybie.de</code>.230 <p>Payments run through our SellAds platform. 244 231 Your advertisers pay into your own Stripe account. No API key and no webhook setup needed.</p> 245 232 … … 330 317 </p> 331 318 <p class="description">Stripe cannot change this later, so please pick the country your business is registered in.</p> 332 <p class="description">333 <a href="https://sellads.cybie.de/terms.html" target="_blank" rel="noopener noreferrer">Terms of service</a>334 ·335 <a href="https://sellads.cybie.de/privacy.html" target="_blank" rel="noopener noreferrer">Privacy policy</a>336 </p>337 319 <?php 338 320 } … … 505 487 <label class="wpsap-choice"> 506 488 <input type="radio" name="wpsap_test_mode" value="live" <?php checked( 'live', $mode ); ?>> 507 Live — buyers pay through Stripe489 Live 508 490 </label> 509 491 <label class="wpsap-choice"> 510 492 <input type="radio" name="wpsap_test_mode" value="test" <?php checked( 'test', $mode ); ?>> 511 Test mode — walk through the plugin without setting up Stripe493 Test mode 512 494 </label> 513 495 <p class="description"> … … 519 501 if ( wpsap_test_mode() ) { 520 502 echo '<p class="notice notice-warning inline" style="padding:8px 12px;margin:8px 0 0;">' 521 . '<strong>Test mode is on.</strong> Visitors can place orders without paying , and the ad space says so.'503 . '<strong>Test mode is on.</strong> Visitors can place orders without paying.' 522 504 . '</p>'; 523 505 } … … 529 511 <label class="wpsap-choice"> 530 512 <input type="radio" name="wpsap_payment_mode" value="connect" <?php checked( 'connect', $mode ); ?>> 531 Connect with Stripe — one click, nothing to set up513 Connect with Stripe Express — Suggestion for Beginners 532 514 </label> 533 515 <label class="wpsap-choice"> 534 516 <input type="radio" name="wpsap_payment_mode" value="own_key" <?php checked( 'own_key', $mode ); ?>> 535 Use my own Stripe key — you add the key and the webhook yourself517 Use my own Stripe key — Suggestion for Advanced Users 536 518 </label> 537 519 <?php … … 627 609 public function wpsap_terms_condtions_0_callback() { 628 610 ?> <select name="wpsap_option_name[terms_condtions_0]" id="terms_condtions_0"> 629 <?php foreach($this->wpsap_get_pages() as $page){ ?> 611 <option value="" <?php echo empty( $this->wpsap_options['terms_condtions_0'] ) ? 'selected' : ''; ?>><?php esc_html_e( '— None —', 'wpsap_ads_plugin' ); ?></option> 612 <?php foreach($this->wpsap_get_pages() as $page){ ?> 630 613 <?php $selected = (isset( $this->wpsap_options['terms_condtions_0'] ) && $this->wpsap_options['terms_condtions_0'] == $page->ID) ? 'selected' : '' ; ?> 631 614 <option value="<?php echo esc_attr($page->ID); ?>" <?php echo esc_attr($selected); ?>><?php echo esc_html(get_the_title($page->ID)); ?></option> … … 637 620 public function wpsap_template_cencel_subscription_1_callback() { 638 621 ?> <select name="wpsap_option_name[template_cencel_subscription_1]" id="template_cencel_subscription_1"> 639 640 <?php foreach($this->wpsap_get_pages() as $page){ ?> 622 <option value="" <?php echo empty( $this->wpsap_options['template_cencel_subscription_1'] ) ? 'selected' : ''; ?>><?php esc_html_e( '— None —', 'wpsap_ads_plugin' ); ?></option> 623 <?php foreach($this->wpsap_get_pages() as $page){ ?> 641 624 <?php $selected = (isset( $this->wpsap_options['template_cencel_subscription_1'] ) && $this->wpsap_options['template_cencel_subscription_1'] == $page->ID) ? 'selected' : '' ; ?> 642 625 <option value="<?php echo esc_attr($page->ID); ?>" <?php echo esc_attr($selected); ?>><?php echo esc_html(get_the_title($page->ID)); ?></option> … … 647 630 public function wpsap_template_cencel_policy_1_callback() { 648 631 ?> <select name="wpsap_option_name[template_cencel_policy_1]" id="template_cencel_policy_1"> 649 650 <?php foreach($this->wpsap_get_pages() as $page){ ?> 632 <option value="" <?php echo empty( $this->wpsap_options['template_cencel_policy_1'] ) ? 'selected' : ''; ?>><?php esc_html_e( '— None —', 'wpsap_ads_plugin' ); ?></option> 633 <?php foreach($this->wpsap_get_pages() as $page){ ?> 651 634 <?php $selected = (isset( $this->wpsap_options['template_cencel_policy_1'] ) && $this->wpsap_options['template_cencel_policy_1'] == $page->ID) ? 'selected' : '' ; ?> 652 635 <option value="<?php echo esc_attr($page->ID); ?>" <?php echo esc_attr($selected); ?>><?php echo esc_html(get_the_title($page->ID)); ?></option> -
sell-ads/trunk/inc/shortcode.php
r3626502 r3627752 8 8 $price = get_post_meta($id,"wpsap_campaign_price",true); 9 9 $button_text = get_post_meta($id, "wpsap_button_text",true); 10 if(empty($title)){ 11 $title = __('This Ad Space is for Sale','wpsap_ads_plugin'); 12 } 10 // Kein Default-Titel: der Platz zeigt einen Titel nur, wenn der Betreiber 11 // ihn aktiv gesetzt hat (Ausgabe unten bedingt). 13 12 if(empty($button_text)){ 14 13 $button_text = __('Buy','wpsap_ads_plugin'); … … 27 26 <div class="wpsap_ads_plugin_ads_box"> 28 27 <div class="wpsap_ads_plugin_ads_box_container"> 28 <?php if((string) $title !== ''){ ?> 29 29 <div class="wpsap_ads_plugin_ads_box_title"><?php echo esc_html($title); ?></div> 30 <?php } ?> 30 31 <form class="wpsap_ads_plugin_ads_box_form" method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>"> 31 32 <input type="hidden" name="action" value="wpsap_start_checkout"> … … 48 49 } 49 50 else { 51 // Klicks auf die veroeffentlichte Anzeige laufen ueber /goto/<slug>, 52 // damit der Zaehler der Kampagne hochlaeuft (inc/hooks.php) - derselbe 53 // Zaehler, den auch der Buy-Button-Klick erhoeht (inc/checkout.php). 54 // Fallback auf die ID, falls der Slug (post_name) leer ist. 55 $slug = get_post_field('post_name',$id); 56 if(empty($slug)){ 57 $slug = $id; 58 } 59 // user_trailingslashit() richtet sich nach der Permalink-Struktur der 60 // Seite. Ohne das haengt WordPress bei Trailing-Slash-Permalinks erst 61 // einen 301 an, bevor der Redirect greift - ein unnoetiger Hop auf 62 // jedem Anzeigenklick. 63 $goto_url = home_url(user_trailingslashit('goto/'.$slug)); 50 64 foreach($activer_orders as $ad){ 51 $url = get_post_meta($ad->ID, "order_url",true); 52 ?> 65 ?> 53 66 <div class="wpsap_ads_plugin_ads_box"> 54 67 <div class="wpsap_ads_plugin_ads_box_container"> 55 <a href="<?php echo esc_ attr($url); ?>" target="_blank" rel="noopener noreferrer nofollow"><img style="max-width:100%;" src="<?php echo esc_attr(get_post_meta($ad->ID, "order_image",true)); ?>"></a>68 <a href="<?php echo esc_url($goto_url); ?>" target="_blank" rel="noopener noreferrer nofollow"><img style="max-width:100%;" src="<?php echo esc_attr(get_post_meta($ad->ID, "order_image",true)); ?>"></a> 56 69 </div> 57 70 </div> -
sell-ads/trunk/inc/stripe.php
r3626067 r3627752 157 157 ), 158 158 'subscription_data' => array( 159 // Waehrend der Pruefungsfrist wird nicht belastet: das Abo startet 160 // im Trial, die erste Rechnung entsteht erst, wenn der Betreiber die 161 // Bestellung annimmt (wpsap_stripe_end_trial) - oder gar nicht, wenn 162 // sie nach 14 Tagen ablaeuft und das Abo vorher gekuendigt wird. 163 // 16 statt 14 Tage: der Ablauf-Cron laeuft nur taeglich, der Puffer 164 // stellt sicher, dass die Kuendigung immer vor dem Trial-Ende greift. 165 'trial_period_days' => 16, 159 166 'metadata' => array( 160 167 'wpsap_place_id' => (string) $campaign_id, … … 210 217 } 211 218 return wpsap_stripe_request('DELETE','subscriptions/'.rawurlencode($subscription_id)); 219 } 220 221 /** 222 * Beendet den Trial eines Abos sofort. Dadurch stellt Stripe die erste 223 * Rechnung unmittelbar aus. Aufgerufen beim Annehmen einer Bestellung: erst 224 * dann - nicht schon beim Checkout - soll der Kaeufer belastet werden. 225 */ 226 function wpsap_stripe_end_trial($subscription_id){ 227 $subscription_id = sanitize_text_field($subscription_id); 228 if(empty($subscription_id)){ 229 return new WP_Error('wpsap_no_subscription',__('No subscription stored for this order.','wpsap_ads_plugin')); 230 } 231 if(wpsap_connect_is_active()){ 232 return wpsap_connect_end_trial($subscription_id); 233 } 234 return wpsap_stripe_request('POST','subscriptions/'.rawurlencode($subscription_id),array('trial_end' => 'now')); 212 235 } 213 236 -
sell-ads/trunk/readme.txt
r3626505 r3627752 5 5 Tested up to: 7.0 6 6 Requires PHP: 7.0 7 Stable tag: 1. 8.27 Stable tag: 1.9.6 8 8 License: GPLv2 or later 9 9 License URI: http://www.gnu.org/licenses/gpl.html … … 241 241 If you want to fill unsold inventory automatically, you want an ad network, not this. This plugin 242 242 does nothing until a real advertiser buys a real space from you. If you need impression counting, 243 click tracking, geo-targeting or A/B rotation, this plugin has none of it on purpose: an ad here is 244 an image and a link, and that is the entire point. And if you would rather never speak to an 243 geo-targeting or A/B rotation, this plugin has none of it on purpose: an ad here is an image and a 244 link, and that is the entire point. It does count clicks — first-party, on your own server, with no 245 cookies and no third-party script — but that is as far as the measuring goes. And if you would rather never speak to an 245 246 advertiser, be aware that even though the purchase itself is automatic, you are the one who decides 246 247 what runs on your site. … … 402 403 403 404 == Changelog == 405 406 = 1.9.0 = 407 * New: the campaign list shows a "Clicks" column again, counting how often each ad space was clicked. Published ads now link through a first-party /goto/<slug> redirect on your own domain that counts the click and forwards the visitor to the advertiser — no cookies and no third-party script are involved, and clicks from logged-in editors are not counted. 408 * Fixed: the "PHP" and "Shortcode" columns showed their raw HTML instead of a usable field. They are copyable input fields again, each with a copy button. 409 410 = 1.8.4 = 411 * The confirmation step is now a single centred column, matching the upload step. The left column that repeated your site name, the ad space and the monthly price has been removed; the confirmation badge, the summary table and the cancellation link stay. 412 413 = 1.8.3 = 414 * The buyer flow was reworked to match the intended design. The ad space now shows as a rounded card instead of a square band. 415 * The upload step is a single centred column again, with your site logo on top, the ad space name below the heading, and a clearly separated blue upload button. Your terms and refund pages are linked right there. 416 * The confirmation step keeps its two columns and now opens with a confirmation badge and a four-row summary: when the request was submitted, the expected review window, that the partnership runs until either side cancels, and the expected first billing date. 417 * Uses your WordPress site logo (Appearance → Customize) on both pages when one is set, otherwise your site name. 404 418 405 419 = 1.8.2 = … … 456 470 == Upgrade Notice == 457 471 472 = 1.9.0 = 473 The campaign list has a Clicks column again and published ads are counted through a first-party /goto redirect on your own domain. The PHP and Shortcode columns are copyable fields again. No reconfiguration needed; the redirect rule is registered automatically on update. 474 475 = 1.8.4 = 476 The confirmation page after upload is now a single centred column; the left sidebar with the site name and price has been removed. No reconfiguration needed. 477 478 = 1.8.3 = 479 Visual update to the pages buyers see. The ad space is a rounded card, the upload step is a single centred column with your site logo, and the confirmation shows a badge and a clear date summary. No reconfiguration needed. 480 458 481 = 1.8.2 = 459 482 Documentation only — the plugin code is identical to 1.8.1. The description now covers pricing, placement and finding your first advertiser. -
sell-ads/trunk/wp-sap.php
r3626505 r3627752 5 5 * Plugin URI: https://cybie.de 6 6 * Description: The easiest way to sell adspace on your WordPress Website 7 * Version: 1. 8.27 * Version: 1.9.6 8 8 * Requires at least: 6.0 9 9 * Requires PHP: 7.0 … … 17 17 18 18 19 define("WPSAP_Version",'1. 8.2');19 define("WPSAP_Version",'1.9.6'); 20 20 define('WPSAP_Plugin_Path',plugin_dir_path( __FILE__ )); 21 21 define('WPSAP_Plugin_Dir',plugin_dir_url( __FILE__ )); … … 81 81 wp_schedule_event(time() + HOUR_IN_SECONDS,'daily','wpsap_expire_pending_orders'); 82 82 } 83 84 // Damit /goto/<slug> sofort nach der Aktivierung greift, muss die 85 // Rewrite-Rule bekannt sein und einmal geflusht werden. Die laufende 86 // Absicherung uebernimmt der Versions-Guard in wpsap_goto_rewrite(). 87 wpsap_goto_rewrite(); 88 flush_rewrite_rules(); 83 89 } 84 90 … … 86 92 function wpsap_deactivate(){ 87 93 wp_clear_scheduled_hook('wpsap_expire_pending_orders'); 94 95 // Die /goto-Rewrite-Rule wird ohne aktives Plugin nicht mehr registriert - 96 // der Flush raeumt sie aus den gespeicherten Regeln. Beim naechsten 97 // Aktivieren sorgt der Versions-Guard fuer die Neuanlage. 98 delete_option('wpsap_rewrite_version'); 99 flush_rewrite_rules(); 88 100 } 89 101
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)