Plugin Directory

Changeset 3616586


Ignore:
Timestamp:
07/21/2026 06:59:57 AM (3 months ago)
Author:
opengraphxyz
Message:

Update to version 1.6.0 from GitHub

Location:
opengraph-xyz
Files:
2 added
18 edited
1 copied

Legend:

Unmodified
Added
Removed
  • opengraph-xyz/tags/1.6.0/opengraph-xyz.php

    r3610433 r3616586  
    44Plugin URI: https://github.com/opengraph-xyz/opengraph-wp
    55Description: Dynamic Open Graph images for your website
    6 Version: 1.5.7
     6Version: 1.6.0
    77Author: OpenGraph.xyz
    8 Author URI: https://opengraph.xyz
     8Author URI: https://www.opengraph.xyz
    99License: GPLv3
    1010License URI: https://www.gnu.org/licenses/gpl-3.0.html
  • opengraph-xyz/tags/1.6.0/readme.txt

    r3610433 r3616586  
    55Tested up to: 7.1
    66Requires PHP: 5.6
    7 Version: 1.5.7
    8 Stable tag: 1.5.7
     7Version: 1.6.0
     8Stable tag: 1.6.0
    99License: GPLv3
    1010License URI: https://www.gnu.org/licenses/gpl-3.0.html
    … …  
    9494== Changelog ==
    9595
     96= 1.6.0 =
     97* Add troubleshooting help and improve the plugin menu and user experience
     98
    9699= 1.5.7 =
    97100* Fix plugin packaging so runtime assets are included in plugin releases
  • opengraph-xyz/tags/1.6.0/src/Admin.php

    r3610433 r3616586  
    1717    add_action('admin_head', array($this, 'add_custom_button'));
    1818    add_action('admin_head', array($this, 'hide_add_new_button'));
     19    add_action('admin_head', array($this, 'hide_redundant_submenu_items'));
    1920    add_action('admin_init', array($this, 'register_plugin_settings'));
    2021
    … …  
    5758      null,
    5859      'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMjBweCIgaGVpZ2h0PSIxMXB4IiB2aWV3Qm94PSIwIDAgMjAgMTEiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8dGl0bGU+R3JvdXA8L3RpdGxlPgogICAgPGcgaWQ9IlBhZ2UtMSIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCI+CiAgICAgICAgPGcgaWQ9Ikdyb3VwIiBmaWxsPSIjMDAwMDAwIiBmaWxsLXJ1bGU9Im5vbnplcm8iPgogICAgICAgICAgICA8cGF0aCBkPSJNNS4wNjgwODY4NywwLjAxMzQ5NDY4NDkgQzMuNTkxODgzMjMsMC4xMTU0ODYyODcgMi4xNTQxMzkyOCwwLjg2MzYwODk3MSAxLjIyMTI4MzEyLDIuMDE0OTk5MjYgQy0wLjM2NDczOTE3OCwzLjk3Mjc0MDUxIC0wLjQxMDMzNDc3LDYuNzIzNDczMzcgMS4xMDk4ODkwMSw4LjczMzczMDYxIEMxLjk1NzQ4NTEyLDkuODU0NjI0NzcgMy4yNjQ3NDQxMiwxMC42Mjk5MjY4IDQuNjU3MzU1ODQsMTAuODM3ODcxNyBDNS4wMDQ3OTA1NSwxMC44ODk3NDI4IDYuMDMyMDgxNDksMTAuODgzMDE3MSA2LjM1MzQ3NDgxLDEwLjgyNjgxNTcgQzcuNTYzMzMzNDcsMTAuNjE1MDkzMyA4LjU2MTk4ODE1LDEwLjA5NDcyNDIgOS4zOTIzNDY5MSw5LjI0MzQxMjIzIEM5LjU1ODk3NDcsOS4wNzI1OTcwMiA5Ljc1OTcwNjUyLDguODQ2OTYyNDggOS44Mzg0NzkzOSw4Ljc0MjAyMjYxIEM5LjkxNzM0NDk0LDguNjM3MTc0ODggOS45OTM3MDgyOSw4LjU1MTMwNjYxIDEwLjAwODI1ODEsOC41NTEzMDY2MSBDMTAuMDIyODA3OSw4LjU1MTMwNjYxIDEwLjEwMTk1MTUsOC42NDQ2Mzc2OCAxMC4xODQxNTMzLDguNzU4NjA2NjEgQzEwLjQ5OTMzNzUsOS4xOTU1OTUwMiAxMS4xMjkyNDI0LDkuNzYwMDAzODQgMTEuNjkxOTU4OCwxMC4xMDk0NjU2IEMxMi4yMzQ1NjQ4LDEwLjQ0NjQ4OTMgMTMuMDQ0NzIwNywxMC43NDAyMTA0IDEzLjcwMTEzMDQsMTAuODM3OTYzOSBDMTQuMDY1NTI0NCwxMC44OTIyMzA0IDE1LjE0MTc0NzIsMTAuODgzMDE3MSAxNS40ODg5MDM5LDEwLjgyMjY2OTcgQzE3LjQ1MTM2NzksMTAuNDgxMzE1NyAxOS4wOTk2NjcxLDkuMDY4OTExNjkgMTkuNzMwMDM1NCw3LjE4ODU2MjQ1IEMxOS45MTIyMzI0LDYuNjQ0NzkxNSAxOS45OTY5MzY0LDYuMTU1ODM5ODkgMTkuOTk5NzE2Niw1LjYzMTY5MzM0IEMyMC4wMDE3NTU1LDUuMjMwOTEzMzQgMTkuOTk0MjQ4OSw1LjE2OTQ2MDQgMTkuOTI4NTQzLDUuMDQ3MTk5NDYgQzE5LjgwODkwMDksNC44MjQ4ODE3MyAxOS42OTQ1NDEzLDQuNzEyNjYzMzIgMTkuNDc4MDU0OSw0LjYwNTE0MzcyIEwxOS4yNzM4OTQxLDQuNTAzNzA0OTIgTDE2Ljg0ODk4NzEsNC41MDM3MDQ5MiBDMTQuMDc1OTAzOSw0LjUwMzcwNDkyIDE0LjIyMTY4MDEsNC40ODk3MDA2NSAxMy45MjYxNDI4LDQuNzgzNTEzODYgQzEzLjQ2NjAxNjUsNS4yNDA5NTU4NyAxMy41ODA0Njg5LDUuOTg1NzYxNzUgMTQuMTU3MzY0Myw2LjI4ODIzNTQ5IEwxNC4zMjg4MTEyLDYuMzc4MTU3NjMgTDE2LjE1NDc2NjQsNi4zODc1NTUyMyBMMTcuOTgwODE0Miw2LjM5Njk1MjgzIEwxNy44OTQzNDk0LDYuNjM2NDA3MzcgQzE3LjIzOTA1MTgsOC40NTE0MzQwNyAxNS4yMTM4NDc2LDkuNDQyMDUxNyAxMy40MTQwMjY0LDguODI3OTgzMDIgQzEyLjI2OTEzMjIsOC40Mzc0Mjk4MSAxMS40NTA5MTM4LDcuNTg2NjcwNTkgMTEuMDg2NTE5Nyw2LjQwODAwODgzIEMxMC45OTk5NjIyLDYuMTI4MTk5ODkgMTAuOTk1MTQzMiw2LjA3ODE3MTQ5IDEwLjk5NTE0MzIsNS40NDkxNzcyMSBDMTAuOTk1MTQzMiw0LjgyMzIyMzMzIDExLjAwMDMzMjksNC43Njg3NzI1MyAxMS4wODU1OTMsNC40ODcxMjA5MiBDMTEuNTk5NTYyOCwyLjc5MDM5MzQxIDEzLjE3MTY4NCwxLjczMzcxNjE5IDE0LjkxODQ5NTYsMS45MTA3MDQzMyBDMTUuMzcwODM3MywxLjk1NjU4NjczIDE1LjcwMDU3MTMsMi4wNDM4MzcgMTYuMDc0NTEwNywyLjIxNjU4NyBDMTYuNjA0MTQyNCwyLjQ2MTI5MzE0IDE2Ljk3MDAxOTMsMi43NDIxMTU1NSAxNy4zNTI1Nzc0LDMuMTk3NDM4NDkgQzE3LjY0MjY0NjksMy41NDI2NjIxIDE3LjgwODI1NTMsMy42NDQ1NjE1NyAxOC4xMTQ1NDI4LDMuNjY2Mzk3MTcgQzE4LjUyNTM2NjUsMy42OTU2MDM0MyAxOC44MzY2NTgzLDMuNTI4NDczNTYgMTkuMDM1MzUxMywzLjE3MTkxNzU2IEMxOS4xMjIwMDE1LDMuMDE2MzA0MzUgMTkuMTM0MzI3MSwyLjk2MDkzMjIyIDE5LjEzNDMyNzEsMi43Mjg2NjQwOCBDMTkuMTM0MzI3MSwyLjQ5NDI3Njg3IDE5LjEyMjY1MDIsMi40NDMwNTA3NCAxOS4wMzQyMzkyLDIuMjkwMzg1OCBDMTguNzk1Njk2NSwxLjg3ODU0OTc5IDE4LjE5ODY5MDcsMS4yOTQ2MDg3MSAxNy42MjYwNTgzLDAuOTEzMDg0NTcyIEMxNy4wMzQ3MDU3LDAuNTE5MTIyNDMgMTYuMjM1NzYzNCwwLjE5ODEyOTg4OSAxNS41MzAyMzY1LDAuMDcwOTg1ODg2MiBDMTUuMDk0NDgzNSwtMC4wMDc0MTk1ODIxNSAxNC4xMDU2NTIzLC0wLjAwODcwOTQ0ODg0IDEzLjY0NDMyMTIsMC4wNjg2ODI1NTI5IEMxMi43NjAxMTg5LDAuMjE2ODMyOTU2IDExLjkyNDAxNDQsMC41NzgwODc3NjQgMTEuMjAzODQ1LDEuMTIzMTQ4NTggQzEwLjg3NTEzMDQsMS4zNzE5MDg1OCAxMC4zOTk3MTI5LDEuODQzMzU0ODYgMTAuMTg2NTYyOCwyLjEzMjAwODYgQzEwLjA5OTE3MTMsMi4yNTAzMDc4IDEwLjAxNzM0MDEsMi4zNDcxMzk5NCAxMC4wMDQ3MzY1LDIuMzQ3MTM5OTQgQzkuOTkyMTMyODMsMi4zNDcxMzk5NCA5Ljg5OTQ1ODg2LDIuMjM4ODgzMjcgOS43OTg3MjIyNiwyLjEwNjU3OTggQzkuNTc2Mzk3NDEsMS44MTQ2MDkyNiA5LjA2Nzg5NTM0LDEuMzEyOTQzMjUgOC43NzIzNTgwNiwxLjA5NDAzNDQ0IEM3LjcwMjI1MTc0LDAuMzAxNDExMzU4IDYuMzk5OTA0NDcsLTAuMDc4NDU0MzgzOCA1LjA2ODA4Njg3LDAuMDEzNDk0Njg0OSBNNS45MDMyNjQ2NywxLjkxNzA2MTUzIEM2LjMxNzE0NjYxLDEuOTY3MzY2MzMgNi42NDMzNTg5OCwyLjA2MzU1MzUzIDcuMDI1MDgzMDYsMi4yNDc4MjAyIEM4LjI3MDQzNTg0LDIuODQ4OTkwMjIgOS4wMzkzNTE3Niw0LjA2ODQ2NzA0IDkuMDM5MzUxNzYsNS40NDI0NTE0NyBDOS4wMzkzNTE3Niw3LjI2NzI0NDMxIDcuNzI0OTU2ODcsOC43NDA1NDg0OCA1Ljg3ODQyODA1LDguOTg1NTMxMDIgQzQuODQ5MjgzNjMsOS4xMjIwNzI2MiAzLjcxMTg5NjAyLDguNzI0NDI1MTUgMi45NTQ4NDIzNyw3Ljk2MzIxOTUzIEMyLjUxNzIzNTg5LDcuNTIzMjgyODUgMi4yNzMwMzk5OCw3LjEyODIxNTExIDIuMDg0MjYzMTEsNi41NTUxNDU3NyBDMS4zMzQxNjAwMSw0LjI3NzYwOTcxIDMuMDA2MTgzNzUsMS45MzczMzA4NiA1LjQxOTQxMzg4LDEuODg2ODQxNzkgQzUuNTI5OTczOTMsMS44ODQ1Mzg0NiA1Ljc0Nzc1Nzc1LDEuODk4MTc0MTkgNS45MDMyNjQ2NywxLjkxNzA2MTUzIiBpZD0iU2hhcGUiPjwvcGF0aD4KICAgICAgICA8L2c+CiAgICA8L2c+Cjwvc3ZnPg=='
    59     );
    60 
    61     // Add the submenu item with a different name but same slug as the main menu item
    62     add_submenu_page(
    63       'edit.php?post_type=opengraph_template', // Parent slug
    64       'OG Manager',               // Page title
    65       'OG Manager',                   // Menu title
    66       'manage_options',                        // Capability
    67       'edit.php?post_type=opengraph_template', // Menu slug
    68       null                                     // Function (not needed as it's the same as the main menu)
    6960    );
    7061
    … …  
    150141
    151142    do_action('cloudpdf-xyz_save_metabox', $post_id);
     143
     144    wp_redirect(admin_url('edit.php?post_type=opengraph_template'));
     145    exit;
    152146  }
    153147
    154148  public function handle_template_creation()
    155149  {
    156     $templateId = isset($_POST['template_id']) ? sanitize_text_field($_POST['template_id']) : '';
    157     $templateName = isset($_POST['template_name']) ? sanitize_text_field($_POST['template_name']) : '';
    158     $templateVersion = isset($_POST['template_version']) ? sanitize_text_field($_POST['template_version']) : '';
     150    if (!current_user_can('manage_options')) {
     151      wp_die(__('You are not allowed to add Open Graph templates.', 'opengraph-xyz'));
     152    }
     153
     154    check_admin_referer('opengraph_xyz_select_template_action', 'opengraph_xyz_select_template_nonce');
     155
     156    $templateId = isset($_POST['template_id']) ? sanitize_text_field(wp_unslash($_POST['template_id'])) : '';
     157    $templateName = isset($_POST['template_name']) ? sanitize_text_field(wp_unslash($_POST['template_name'])) : '';
     158    $templateVersion = isset($_POST['template_version']) ? sanitize_text_field(wp_unslash($_POST['template_version'])) : '';
    159159
    160160    $new_post = array(
    … …  
    176176
    177177    if ($postId) {
    178       // Redirect to the edit post screen or a confirmation page
    179178      wp_redirect(admin_url('post.php?post=' . $postId . '&action=edit'));
    180179      exit;
    … …  
    254253  }
    255254
     255  /**
     256   * Display shared troubleshooting guidance.
     257   */
     258  public function display_troubleshooting()
     259  {
     260    include plugin_dir_path(__FILE__) . 'views/troubleshooting.php';
     261  }
     262
    256263  public function register_plugin_settings()
    257264  {
    … …  
    373380      'default'
    374381    );
     382
     383    add_meta_box(
     384      'opengraph_template-troubleshooting',
     385      __('Troubleshooting', 'opengraph-xyz'),
     386      array($this, 'display_troubleshooting'),
     387      null,
     388      'normal',
     389      'low'
     390    );
    375391  }
    376392
    … …  
    419435    global $submenu;
    420436
     437    $parent_slug = 'edit.php?post_type=opengraph_template';
     438
    421439    // Remove default "Add New" submenu
    422     if (isset($submenu['edit.php?post_type=opengraph_template'])) {
    423       foreach ($submenu['edit.php?post_type=opengraph_template'] as $key => $item) {
     440    if (isset($submenu[$parent_slug])) {
     441      foreach ($submenu[$parent_slug] as $key => $item) {
    424442        if ($item[2] === 'post-new.php?post_type=opengraph_template') {
    425           unset($submenu['edit.php?post_type=opengraph_template'][$key]);
     443          unset($submenu[$parent_slug][$key]);
    426444          break;
    427445        }
    … …  
    430448
    431449    add_submenu_page(
    432       'edit.php?post_type=opengraph_template',
    433       'Select OG Template',
    434       'Select OG Template',
     450      $parent_slug,
     451      'Add OG Template',
     452      'Add OG Template',
    435453      'manage_options', // Standard capability
    436454      'opengraph_template_selection',
    … …  
    438456      1
    439457    );
     458
     459  }
     460
     461  /**
     462   * Hide routing-only submenu rows while preserving WordPress page metadata.
     463   */
     464  public function hide_redundant_submenu_items()
     465  {
     466    echo '<style type="text/css">
     467            #adminmenu .wp-submenu a[href="edit.php?post_type=opengraph_template"],
     468            #adminmenu .wp-submenu a[href*="page=opengraph_template_selection"] { display: none; }
     469          </style>
     470          <script type="text/javascript">
     471            jQuery(document).ready(function($) {
     472              $("#adminmenu .wp-submenu a[href=\"edit.php?post_type=opengraph_template\"], #adminmenu .wp-submenu a[href*=\"page=opengraph_template_selection\"]").parent().remove();
     473            });
     474          </script>';
    440475  }
    441476
    … …  
    483518
    484519    $variables = $data['data']['variables'];
     520
     521    foreach ($variables as &$variable) {
     522      if (empty($variable['modifications']) || !is_array($variable['modifications'])) {
     523        continue;
     524      }
     525
     526      foreach ($variable['modifications'] as &$modification) {
     527        $property = isset($modification['property']) ? $modification['property'] : '';
     528        $modification['suggestedDynamicTag'] = opengraphxyz_get_suggested_dynamic_tag($variable, $property);
     529      }
     530      unset($modification);
     531    }
     532    unset($variable);
    485533
    486534    wp_send_json_success(array('variables' => $variables));
    … …  
    577625    global $pagenow, $typenow, $post;
    578626
     627    if ($this->is_opengraph_template_selection_page()) {
     628      return;
     629    }
     630
    579631    if (($pagenow == 'edit.php' || $pagenow == 'post.php') && $typenow == 'opengraph_template') {
    580       $customButton = '<a href="edit.php?post_type=opengraph_template&page=opengraph_template_selection" class="page-title-action title-new-template">Select OG Template</a>';
     632      $customButton = $pagenow == 'edit.php'
     633        ? '<a href="edit.php?post_type=opengraph_template&page=opengraph_template_selection" class="page-title-action title-new-template">Add OG Template</a>'
     634        : '';
    581635
    582636      // Add Edit on Open Graph button only on post edit page (post.php) and if post has a template
    … …  
    590644      }
    591645
    592       // Combine both buttons into one string (Edit on Open Graph first, then Select OG Template)
     646      // Show Edit on Open Graph on detail pages and Add OG Template on the overview.
    593647      $allButtons = $editButton . $customButton;
    594648
    … …  
    610664  {
    611665    global $pagenow, $typenow;
     666
     667    if ($this->is_opengraph_template_selection_page()) {
     668      return;
     669    }
    612670
    613671    if (($pagenow == 'edit.php' || $pagenow == 'post.php') && $typenow == 'opengraph_template') {
  • opengraph-xyz/tags/1.6.0/src/Plugin.php

    r3342214 r3616586  
    131131      'name_admin_bar' => _x('OG Image Template', 'add new on admin bar', 'opengraph-xyz'),
    132132      'add_new' => _x('Add New', 'template', 'opengraph-xyz'),
    133       'add_new_item' => __('Select OG Template', 'opengraph-xyz'),
     133      'add_new_item' => __('Add OG Template', 'opengraph-xyz'),
    134134      'new_item' => __('New Template', 'opengraph-xyz'),
    135135      'edit_item' => __('Match Variables', 'opengraph-xyz'),
  • opengraph-xyz/tags/1.6.0/src/functions.php

    r3473900 r3616586  
    1616function opengraphxyz_get_base_url()
    1717{
    18     return defined('OPENGRAPHXYZ_BASE_URL') ? OPENGRAPHXYZ_BASE_URL : 'https://dashboard.opengraph.xyz';
     18    return defined('OPENGRAPHXYZ_BASE_URL') ? OPENGRAPHXYZ_BASE_URL : 'https://www.opengraph.xyz';
     19}
     20
     21/**
     22 * Get the WordPress integration documentation URL.
     23 *
     24 * @param string $section Optional documentation section anchor.
     25 * @return string The WordPress documentation URL.
     26 */
     27function opengraphxyz_get_wordpress_docs_url($section = '')
     28{
     29    $url = opengraphxyz_get_base_url() . '/docs/wordpress';
     30
     31    return empty($section) ? $url : $url . '#' . sanitize_title($section);
     32}
     33
     34/**
     35 * Suggest a WordPress dynamic tag for a common template variable.
     36 *
     37 * @param array  $variable Template variable data.
     38 * @param string $property Modification property.
     39 * @return string Suggested dynamic tag, or an empty string when none applies.
     40 */
     41function opengraphxyz_get_suggested_dynamic_tag($variable, $property)
     42{
     43    $suggestions = array(
     44        'title' => array(
     45            'properties' => array('text'),
     46            'tag' => '{post_title}',
     47        ),
     48        'description' => array(
     49            'properties' => array('text'),
     50            'tag' => '{post_excerpt}',
     51        ),
     52        'image' => array(
     53            'properties' => array('src', 'url'),
     54            'tag' => '{featured_image}',
     55        ),
     56        'url' => array(
     57            'properties' => array('text', 'url'),
     58            'tag' => '{post_url}',
     59        ),
     60        'link' => array(
     61            'properties' => array('text', 'url'),
     62            'tag' => '{post_url}',
     63        ),
     64    );
     65
     66    $variable_names = array_filter(array($variable['name'] ?? '', $variable['id'] ?? ''));
     67
     68    foreach ($variable_names as $variable_name) {
     69        $variable_name = strtolower((string) $variable_name);
     70        $variable_name = preg_replace('/[^a-z0-9]+/', '_', $variable_name);
     71        $variable_name = trim($variable_name, '_');
     72
     73        if (preg_match('/^image_?\d+$/', $variable_name)) {
     74            $variable_name = 'image';
     75        }
     76
     77        if (!isset($suggestions[$variable_name])) {
     78            continue;
     79        }
     80
     81        $suggestion = $suggestions[$variable_name];
     82
     83        if (in_array(strtolower($property), $suggestion['properties'], true)) {
     84            return $suggestion['tag'];
     85        }
     86    }
     87
     88    return '';
    1989}
    2090
    … …  
    39109{
    40110    return defined('OPENGRAPHXYZ_BASE_IMAGE_URL') ? OPENGRAPHXYZ_BASE_IMAGE_URL : 'https://ogcdn.net';
    41 }
    42 
    43 /**
    44  * Get the create template base URL without URL encoding for JavaScript concatenation
    45  *
    46  * @return string The base URL for creating templates
    47  */
    48 function opengraphxyz_get_create_template_baseurl_raw()
    49 {
    50     $base_url = opengraphxyz_get_base_url();
    51     return $base_url . "/register?redirect=/org/[organizationId]/create-template/";
    52 }
    53 
    54 // /org/1/template-editor/c91f620c-b194-449e-86c6-f332e98caf2d
    55 
    56 /**
    57  * Get the OpenGraph.xyz settings URL with wp parameter
    58  *
    59  * @return string The settings URL for OpenGraph.xyz
    60  */
    61 function opengraphxyz_get_settings_url()
    62 {
    63     $base_url = opengraphxyz_get_base_url();
    64     $current_domain = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https://' : 'http://') . ($_SERVER['HTTP_HOST'] ?? '');
    65 
    66     return $base_url . "/register?redirect=/org/[organizationId]/settings/api-keys?wp=" . urlencode($current_domain);
    67111}
    68112
    … …  
    179223{
    180224    $base_url = opengraphxyz_get_base_url();
    181     return $base_url . "/register?redirect=/org/[organizationId]/template-editor/" . $template_id;
    182 }
     225    return $base_url . "/generate/" . $template_id;
     226}
  • opengraph-xyz/tags/1.6.0/src/templates/admin.php

    r3390572 r3616586  
    1010}
    1111
    12 // Get the settings URL using the helper function
    13 $settings_url = opengraphxyz_get_settings_url();
     12$settings_url = opengraphxyz_get_base_url() . '/settings/api-keys';
    1413
    1514// Check if user was redirected from OpenGraph.xyz
    … …  
    5958    <?php if ($redirected_from_opengraphxyz): ?>
    6059        <!-- Message for users redirected from OpenGraph.xyz -->
    61         <div class="api-key-info-banner" style="margin-top: 10px; max-width: 700px; border: 1px solid #007cba; background-color: #eef5fa; color: #007cba; padding: 15px; margin-bottom: 20px; border-radius: 5px;">
     60        <div class="api-key-info-banner"
     61            style="margin-top: 10px; max-width: 700px; border: 1px solid #007cba; background-color: #eef5fa; color: #007cba; padding: 15px; margin-bottom: 20px; border-radius: 5px;">
    6262            <strong>Paste your API key from OpenGraph.xyz in the box below and click save</strong>
    6363        </div>
    6464    <?php else: ?>
    6565        <!-- Banner for API Key information -->
    66         <div class="api-key-info-banner" style="margin-top: 10px; max-width: 700px; border: 1px solid #007cba; background-color: #eef5fa; color: #007cba; padding: 15px; margin-bottom: 20px; border-radius: 5px;">
    67             <strong>Need an API Key?</strong> Obtain your API key from your OpenGraph.xyz account by clicking the button below. In the OpenGraph.xyz dashboard, go to <em>Settings > API Keys</em> to find your existing keys or create a new one by clicking on <em>Create new API key</em>.
     66        <div class="api-key-info-banner"
     67            style="margin-top: 10px; max-width: 700px; border: 1px solid #007cba; background-color: #eef5fa; color: #007cba; padding: 15px; margin-bottom: 20px; border-radius: 5px;">
     68            <strong>Need an API Key?</strong> Get your API key from your OpenGraph.xyz API Key Settings page.
    6869
    6970            <div style="margin-top:20px;">
    70                 <a href="<?php echo esc_url($settings_url); ?>" target="_blank" class="button button-primary" style="background: #0073aa; border-color: #0073aa; color: white; padding: 8px 16px; font-size: 14px; line-height: 1.4; border-radius: 4px; cursor: pointer; text-decoration: none; display: inline-block;">
    71                     <span class="dashicons dashicons-external" style="margin-right: 5px;"></span>
    72                     Go to OpenGraph.xyz Settings
     71                <a href="<?php echo esc_url($settings_url); ?>" target="_blank" class="button button-primary"
     72                    style="background: #0073aa; border-color: #0073aa; color: white; padding: 8px 16px; font-size: 14px; line-height: 1.4; border-radius: 4px; cursor: pointer; text-decoration: none; display: inline-flex; align-items: center; gap: 6px;">
     73                    <span class="dashicons dashicons-external" style="margin: 0; line-height: 1;"></span>
     74                    OpenGraph API Key Settings
    7375                </a>
    7476            </div>
    … …  
    8991                    <th scope="row">API Key</th>
    9092                    <td>
    91                         <textarea
    92                             name="opengraph_xyz_api_key"
     93                        <textarea name="opengraph_xyz_api_key"
    9394                            style="width: 100%; min-height: 100px; font-family: 'Courier New', monospace; font-size: 13px; padding: 8px; border: 1px solid #ddd; border-radius: 4px; resize: vertical;"
    94                             placeholder="Paste your OpenGraph.xyz API key here..."
    95                         ><?php echo esc_textarea(get_option('opengraph_xyz_api_key')); ?></textarea>
    96                         <p class="description">Your API key will be securely stored and used to connect to OpenGraph.xyz services.</p>
     95                            placeholder="Paste your OpenGraph.xyz API key here..."><?php echo esc_textarea(get_option('opengraph_xyz_api_key')); ?></textarea>
     96                        <p class="description">Your API key will be securely stored and used to connect to OpenGraph.xyz
     97                            services.</p>
    9798                    </td>
    9899                </tr>
    … …  
    204205
    205206    // Auto-hide toast after 5 seconds
    206     document.addEventListener('DOMContentLoaded', function() {
     207    document.addEventListener('DOMContentLoaded', function () {
    207208        const toast = document.getElementById('opengraph-xyz-toast');
    208209        if (toast) {
    … …  
    221222    }
    222223
    223     document.addEventListener('DOMContentLoaded', function() {
     224    document.addEventListener('DOMContentLoaded', function () {
    224225        const errorToast = document.getElementById('opengraph-xyz-error-toast');
    225226        if (errorToast) {
    … …  
    231232
    232233    // Show loading overlay when form is submitted
    233     document.addEventListener('DOMContentLoaded', function() {
     234    document.addEventListener('DOMContentLoaded', function () {
    234235        const form = document.querySelector('form[action="options.php"]');
    235236        if (form) {
    236             form.addEventListener('submit', function() {
     237            form.addEventListener('submit', function () {
    237238                showLoadingOverlay();
    238239            });
  • opengraph-xyz/tags/1.6.0/src/templates/template_selection.php

    r3342214 r3616586  
    22
    33// Exit if accessed directly.
    4 defined( 'ABSPATH' ) || exit;
     4defined('ABSPATH') || exit;
    55
    66// Check user capabilities
    7 if ( ! current_user_can( 'manage_options' ) ) {
     7if (!current_user_can('manage_options')) {
    88    return;
    99}
    1010
    11 // Get the create template base URL
    12 $create_template_base_url = opengraphxyz_get_create_template_baseurl_raw();
     11$create_template_url = opengraphxyz_get_base_url() . '/generate';
    1312
    1413$apiKey = get_option('opengraph_xyz_api_key'); // Assuming the API key is stored with this name
    … …  
    1817$hasApiKey = !empty($apiKey);
    1918
    20 // Split templates into user templates and stock templates
    2119$userTemplates = array();
    22 $stockTemplates = array();
    2320
    24 if ( isset( $templates['edges'] ) && is_array( $templates['edges'] ) ) {
    25     foreach ( $templates['edges'] as $edge ) {
     21if (isset($templates['edges']) && is_array($templates['edges'])) {
     22    foreach ($templates['edges'] as $edge) {
    2623        $template = $edge['node'];
    27         if ( isset( $template['organizationId'] ) && !empty( $template['organizationId'] ) ) {
     24        if (isset($template['organizationId']) && !empty($template['organizationId'])) {
    2825            $userTemplates[] = $edge;
    29         } else {
    30             $stockTemplates[] = $edge;
    3126        }
    3227    }
    3328}
    34 
    35 // Determine default tab - if user has templates, default to "Your Templates", otherwise "Stock Templates"
    36 $defaultTab = !empty($userTemplates) ? 'your-templates' : 'stock-templates';
    3729
    3830// Template selection view
    … …  
    4032
    4133<div class="wrap">
    42     <h1 style="margin-bottom: 20px">Select OG Image Template</h1>
     34    <h1 class="wp-heading-inline">Select OG Image Template</h1>
     35    <a href="<?php echo esc_url($create_template_url); ?>" target="_blank" rel="noopener noreferrer"
     36        class="page-title-action">Add new template</a>
     37    <hr class="wp-header-end">
    4338
    44     <?php if ( isset( $templates['authenticated'] ) && ! $templates['authenticated'] ) : ?>
     39    <?php if (isset($templates['authenticated']) && !$templates['authenticated']): ?>
    4540        <!-- Banner for unauthenticated users -->
    46         <div class="unauthenticated-banner" style="border: 1px solid #eab308; color: #854d0e; background-color: #ffffcc; padding: 20px; margin-bottom: 20px; border-radius: 6px; display: flex; align-items: center; gap: 10px;">
    47             <svg style="width: 1.5rem; height: 1.5rem; fill: #eab308; flex-shrink: 0;" width="24" height="24" fill="currentColor" viewBox="0 0 24 24">
    48               <path d="M5 16L3 5L8.5 10L12 4L15.5 10L21 5L19 16H5M19 19C19 19.6 18.6 20 18 20H6C5.4 20 5 19.6 5 19V18H19V19Z"></path>
     41        <div class="unauthenticated-banner"
     42            style="border: 1px solid #eab308; color: #854d0e; background-color: #ffffcc; padding: 20px; margin-bottom: 20px; border-radius: 6px; display: flex; align-items: center; gap: 10px;">
     43            <svg style="width: 1.5rem; height: 1.5rem; fill: #eab308; flex-shrink: 0;" width="24" height="24"
     44                fill="currentColor" viewBox="0 0 24 24">
     45                <path
     46                    d="M5 16L3 5L8.5 10L12 4L15.5 10L21 5L19 16H5M19 19C19 19.6 18.6 20 18 20H6C5.4 20 5 19.6 5 19V18H19V19Z">
     47                </path>
    4948            </svg>
    50             <p style="margin: 0; font-size: 1.2em;">Create unique, custom Open Graph image templates that truly represent your brand's identity.</p>
    51             <a href="https://www.opengraph.xyz/get-started" target="_blank" style="text-decoration: underline; font-weight: bold; color: #854d0e; flex-shrink: 0;">Learn More</a>
     49            <p style="margin: 0; font-size: 1.2em;">Create unique, custom Open Graph image templates that truly represent
     50                your brand's identity.</p>
     51            <a href="https://www.opengraph.xyz/get-started" target="_blank"
     52                style="text-decoration: underline; font-weight: bold; color: #854d0e; flex-shrink: 0;">Learn More</a>
    5253        </div>
    5354    <?php endif; ?>
    5455
    55     <!-- Tab Navigation -->
    56     <div class="tab-navigation" style="margin-bottom: 0; border-bottom: 1px solid #dcdcde;">
    57         <button class="tab-button <?php echo $defaultTab === 'your-templates' ? 'active' : ''; ?>" data-tab="your-templates" style="padding: 12px 24px; margin-right: 0; border: 1px solid #dcdcde; border-bottom: none; background: <?php echo $defaultTab === 'your-templates' ? '#fff' : '#f9f9f9'; ?>; cursor: pointer; border-radius: 4px 4px 0 0; font-weight: 500; color: <?php echo $defaultTab === 'your-templates' ? '#1d2327' : '#646970'; ?>; position: relative; top: 1px;">
    58             Your Templates (<?php echo count($userTemplates); ?>)
    59         </button>
    60         <button class="tab-button <?php echo $defaultTab === 'stock-templates' ? 'active' : ''; ?>" data-tab="stock-templates" style="padding: 12px 24px; margin-right: 0; border: 1px solid #dcdcde; border-bottom: none; background: <?php echo $defaultTab === 'stock-templates' ? '#fff' : '#f9f9f9'; ?>; cursor: pointer; border-radius: 4px 4px 0 0; font-weight: 500; color: <?php echo $defaultTab === 'stock-templates' ? '#1d2327' : '#646970'; ?>; position: relative; top: 1px;">
    61             Stock Templates (<?php echo count($stockTemplates); ?>)
    62         </button>
     56    <div
     57        style="margin-top: 20px; margin-bottom: 20px; border: 1px solid #007cba; background-color: #eef5fa; color: #007cba; padding: 15px; border-radius: 5px;">
     58        <strong>Choose one of your templates to add it to WordPress.</strong>
    6359    </div>
     60    <?php if (!empty($userTemplates)): ?>
     61        <div class="template-grid"
     62            style="display: grid; grid-template-columns: repeat(auto-fill, minmax(500px, 1fr)); gap: 20px;">
     63            <?php foreach ($userTemplates as $edge):
     64                $template = $edge['node'];
     65                $name = $template['name'];
     66                $id = $template['id'];
     67                $version = $template['activeVersion'];
     68                $versionNumber = $version['versionNumber'];
    6469
    65     <!-- Your Templates Tab -->
    66     <div id="your-templates" class="tab-content" style="display: <?php echo $defaultTab === 'your-templates' ? 'block' : 'none'; ?>;">
    67         <div style="margin-top: 20px; margin-bottom: 20px; border: 1px solid #007cba; background-color: #eef5fa; color: #007cba; padding: 15px; border-radius: 5px;">
    68             <strong>Click a template card to create a dynamic Open Graph image template.</strong>
    69         </div>
    70         <?php if ( !empty($userTemplates) ) : ?>
    71             <div class="template-grid" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(500px, 1fr)); gap: 20px;">
    72                 <?php foreach ( $userTemplates as $edge ) :
    73                     $template       = $edge['node'];
    74                     $name           = $template['name'];
    75                     $id             = $template['id'];
    76                     $premium        = $template['isPremium'];
    77                     $organizationId = $template['organizationId'];
    78                     $version        = $template['activeVersion'];
    79                     $versionNumber  = $version['versionNumber'];
    80                    
    81                     // Generate image URL
    82                     $imageUrl = opengraphxyz_generate_image_url($id, $versionNumber, $version['data']['variables']);
    83                     ?>
    84                     <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" class="template-form" id="template-form-<?php echo esc_attr( $id ); ?>">
    85                         <?php wp_nonce_field( 'opengraph_xyz_select_template_action', 'opengraph_xyz_select_template_nonce' ); ?>
     70                // Generate image URL
     71                $imageUrl = opengraphxyz_generate_image_url($id, $versionNumber, $version['data']['variables']);
     72                ?>
     73                <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" class="template-form"
     74                    id="template-form-<?php echo esc_attr($id); ?>">
     75                    <?php wp_nonce_field('opengraph_xyz_select_template_action', 'opengraph_xyz_select_template_nonce'); ?>
    8676
    87                         <input type="hidden" name="action" value="create_opengraph_template">
    88                         <input type="hidden" name="template_id" value="<?php echo esc_attr( $id ); ?>">
    89                         <input type="hidden" name="template_name" value="<?php echo esc_attr( $name ); ?>">
    90                         <input type="hidden" name="template_version" value="<?php echo esc_attr( $versionNumber ); ?>">
    91                        
    92                         <div onclick="handleTemplateClick('<?php echo esc_attr( $id ); ?>', 'user')" style="cursor: pointer; border-radius: 6px; overflow: hidden; box-shadow: 0 1px 1px -1px rgba(0,0,0,.1); border: 1px solid #dcdcde;">
    93                             <div class="template-card" style="position: relative; padding-top: 52.5%; background-color: #fff">
    94                                 <img src="<?php echo esc_url( $imageUrl ); ?>" alt="<?php echo esc_attr( $name ); ?>" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover;">
    95                             </div>
    96                             <div class="template-details" style="width: 100%; background: rgba(255,255,255,.65); color: #000; text-align: center; font-size: 16px;">
    97                                 <div style="padding: 1rem; display: flex; align-items: center; justify-content: center; gap: .5rem; border-top: 1px solid #dcdcde;">
    98                                     <?php echo esc_html( $name ); ?>
    99                                 </div>
     77                    <input type="hidden" name="action" value="create_opengraph_template">
     78                    <input type="hidden" name="template_id" value="<?php echo esc_attr($id); ?>">
     79                    <input type="hidden" name="template_name" value="<?php echo esc_attr($name); ?>">
     80                    <input type="hidden" name="template_version" value="<?php echo esc_attr($versionNumber); ?>">
     81
     82                    <div onclick="handleTemplateClick('<?php echo esc_attr($id); ?>')"
     83                        style="cursor: pointer; border-radius: 6px; overflow: hidden; box-shadow: 0 1px 1px -1px rgba(0,0,0,.1); border: 1px solid #dcdcde;">
     84                        <div class="template-card" style="position: relative; padding-top: 52.5%; background-color: #fff">
     85                            <img src="<?php echo esc_url($imageUrl); ?>" alt="<?php echo esc_attr($name); ?>"
     86                                style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover;">
     87                        </div>
     88                        <div class="template-details"
     89                            style="width: 100%; background: rgba(255,255,255,.65); color: #000; text-align: center; font-size: 16px;">
     90                            <div
     91                                style="padding: 1rem; display: flex; align-items: center; justify-content: center; gap: .5rem; border-top: 1px solid #dcdcde;">
     92                                <?php echo esc_html($name); ?>
    10093                            </div>
    10194                        </div>
    102                     </form>
    103                 <?php endforeach; ?>
    104             </div>
    105         <?php elseif ( !$hasApiKey ) : ?>
    106             <div style="text-align: center; padding: 40px; background: #f9f9f9; border-radius: 6px;">
    107                 <p style="font-size: 1.2em; color: #666; margin-bottom: 20px;">Connect your Open Graph account with an API Key to see your custom templates.</p>
    108                 <a href="<?php echo esc_url( admin_url( 'edit.php?post_type=opengraph_template&page=og-xyz-settings' ) ); ?>" style="background: #0073aa; color: white; padding: 10px 20px; text-decoration: none; border-radius: 4px;">Add an API Key</a>
    109             </div>
    110         <?php else : ?>
    111             <div style="text-align: center; padding: 40px; background: #f9f9f9; border-radius: 6px;">
    112                 <p style="font-size: 1.2em; color: #666; margin-bottom: 20px;">You don't have any custom templates yet.</p>
    113                 <a href="https://www.opengraph.xyz/get-started" target="_blank" style="background: #0073aa; color: white; padding: 10px 20px; text-decoration: none; border-radius: 4px;">Create Your First Template</a>
    114             </div>
    115         <?php endif; ?>
    116     </div>
    117 
    118     <!-- Stock Templates Tab -->
    119     <div id="stock-templates" class="tab-content" style="display: <?php echo $defaultTab === 'stock-templates' ? 'block' : 'none'; ?>;">
    120         <div style="margin-top: 20px; margin-bottom: 20px; border: 1px solid #007cba; background-color: #eef5fa; color: #007cba; padding: 15px; border-radius: 5px;">
    121             <strong>Click a card to create a template based on the example image. (Redirects to Open Graph.xyz). <br/><br/>When you're done, return here and refresh the page to start matching your variables.</strong>
     95                    </div>
     96                </form>
     97            <?php endforeach; ?>
    12298        </div>
    123         <?php if ( !empty($stockTemplates) ) : ?>
    124             <div class="template-grid" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(500px, 1fr)); gap: 20px;">
    125                 <?php foreach ( $stockTemplates as $edge ) :
    126                     $template       = $edge['node'];
    127                     $name           = $template['name'];
    128                     $id             = $template['id'];
    129                     $premium        = $template['isPremium'];
    130                     $organizationId = $template['organizationId'];
    131                     $version        = $template['activeVersion'];
    132                     $versionNumber  = $version['versionNumber'];
    133                    
    134                     // Generate image URL
    135                     $imageUrl = opengraphxyz_generate_image_url($id, $versionNumber, $version['data']['variables']);
    136                     ?>
    137                     <?php if ( $premium ) : ?>
    138                         <!-- Premium template -->
    139                         <a href="https://www.opengraph.xyz/get-started" target="_blank" class="template-card" style="text-decoration: none">
    140                     <?php else : ?>
    141                         <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" class="template-form" id="template-form-<?php echo esc_attr( $id ); ?>">
    142                             <?php wp_nonce_field( 'opengraph_xyz_select_template_action', 'opengraph_xyz_select_template_nonce' ); ?>
    143 
    144                             <input type="hidden" name="action" value="create_opengraph_template">
    145                             <input type="hidden" name="template_id" value="<?php echo esc_attr( $id ); ?>">
    146                             <input type="hidden" name="template_name" value="<?php echo esc_attr( $name ); ?>">
    147                             <input type="hidden" name="template_version" value="<?php echo esc_attr( $versionNumber ); ?>">
    148                     <?php endif; ?>
    149                         <div onclick="handleTemplateClick('<?php echo esc_attr( $id ); ?>', 'stock')" style="cursor: pointer; border-radius: 6px; overflow: hidden; box-shadow: 0 1px 1px -1px rgba(0,0,0,.1); border: 1px solid #dcdcde;">
    150                             <div class="template-card" style="position: relative; padding-top: 52.5%; background-color: #fff">
    151                                 <img src="<?php echo esc_url( $imageUrl ); ?>" alt="<?php echo esc_attr( $name ); ?>" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover;">
    152                             </div>
    153                             <div class="template-details" style="width: 100%; background: rgba(255,255,255,.65); color: #000; text-align: center; font-size: 16px;">
    154                                 <div style="padding: 1rem; display: flex; align-items: center; justify-content: center; gap: .5rem; border-top: 1px solid #dcdcde;">
    155                                     <?php echo esc_html( $name ); ?>
    156                                     <?php if ( isset( $premium ) ) : ?>
    157                                         <span style="font-size: .75rem; line-height: 1rem; padding: .25rem .5rem; border-radius: 9999px; background-color: #ffffcc; color: #854d0e; display: inline-flex; -moz-column-gap: .375rem; column-gap: 0.375rem; align-items: center;">
    158                                             <svg style="width: 1rem; height: 1rem; fill: #eab308;" width="24" height="24" fill="currentColor" viewBox="0 0 24 24">
    159                                                 <path d="M5 16L3 5L8.5 10L12 4L15.5 10L21 5L19 16H5M19 19C19 19.6 18.6 20 18 20H6C5.4 20 5 19.6 5 19V18H19V19Z"></path>
    160                                             </svg>
    161                                             Premium
    162                                         </span>
    163                                     <?php endif; ?>
    164                                 </div>
    165                             </div>
    166                         </div>
    167                     <?php if ( $premium ) : ?>
    168                         </a>
    169                     <?php else : ?>
    170                         </form>
    171                     <?php endif; ?>
    172                 <?php endforeach; ?>
    173             </div>
    174         <?php else : ?>
    175             <p>No stock templates available.</p>
    176         <?php endif; ?>
    177     </div>
     99    <?php elseif (!$hasApiKey): ?>
     100        <div style="text-align: center; padding: 40px; background: #f9f9f9; border-radius: 6px;">
     101            <p style="font-size: 1.2em; color: #666; margin-bottom: 20px;">Connect your Open Graph account with an API
     102                Key to see your custom templates.</p>
     103            <a href="<?php echo esc_url(admin_url('edit.php?post_type=opengraph_template&page=og-xyz-settings')); ?>"
     104                style="background: #0073aa; color: white; padding: 10px 20px; text-decoration: none; border-radius: 4px;">Add
     105                an API Key</a>
     106        </div>
     107    <?php else: ?>
     108        <div style="text-align: center; padding: 40px; background: #f9f9f9; border-radius: 6px;">
     109            <p style="font-size: 1.2em; color: #666; margin-bottom: 20px;">You don't have any custom templates yet.</p>
     110            <a href="<?php echo esc_url($create_template_url); ?>" target="_blank"
     111                style="background: #0073aa; color: white; padding: 10px 20px; text-decoration: none; border-radius: 4px;">Create
     112                Your First Template</a>
     113        </div>
     114    <?php endif; ?>
    178115</div>
    179116
    … …  
    182119
    183120<script>
    184 // Check if user has API key
    185 const hasApiKey = <?php echo $hasApiKey ? 'true' : 'false'; ?>;
     121    // Check if user has API key
     122    const hasApiKey = <?php echo $hasApiKey ? 'true' : 'false'; ?>;
    186123
    187 // Get the create template base URL from PHP
    188 const createTemplateBaseUrl = '<?php echo esc_js($create_template_base_url); ?>';
     124    // Debug: Log template data
     125    <?php if (isset($templates['edges']) && is_array($templates['edges'])): ?>
     126        console.log('Template data:', <?php echo json_encode($templates['edges']); ?>);
     127    <?php endif; ?>
    189128
    190 // Debug: Log template data
    191 <?php if ( isset( $templates['edges'] ) && is_array( $templates['edges'] ) ) : ?>
    192 console.log('Template data:', <?php echo json_encode($templates['edges']); ?>);
    193 <?php endif; ?>
     129    // Handle template click - check for API key first
     130    function handleTemplateClick(templateId) {
     131        if (!hasApiKey) {
     132            // Show API key modal if no API key
     133            showApiKeyModal();
     134            return;
     135        }
    194136
    195 // Tab functionality
    196 document.addEventListener('DOMContentLoaded', function() {
    197     const tabButtons = document.querySelectorAll('.tab-button');
    198     const tabContents = document.querySelectorAll('.tab-content');
    199 
    200     tabButtons.forEach(button => {
    201         button.addEventListener('click', function() {
    202             const targetTab = this.getAttribute('data-tab');
    203            
    204             // Update button styles
    205             tabButtons.forEach(btn => {
    206                 btn.style.background = '#f9f9f9';
    207                 btn.style.color = '#646970';
    208                 btn.classList.remove('active');
    209             });
    210             this.style.background = '#fff';
    211             this.style.color = '#1d2327';
    212             this.classList.add('active');
    213            
    214             // Show/hide tab content
    215             tabContents.forEach(content => {
    216                 content.style.display = 'none';
    217             });
    218             document.getElementById(targetTab).style.display = 'block';
    219         });
    220     });
    221 });
    222 
    223 // Handle template click - check for API key first
    224 function handleTemplateClick(templateId, templateType) {
    225     if (!hasApiKey) {
    226         // Show API key modal if no API key
    227         showApiKeyModal();
    228         return;
    229     }
    230    
    231     if (templateType === 'user') {
    232         // This is a user template - submit the form
    233137        var formId = "template-form-" + templateId;
    234138        const form = document.getElementById(formId);
    … …  
    238142            form.submit();
    239143        }
    240     } else {
    241         // This is a stock template - use the existing behavior
    242         submitTemplateForm(templateId);
    243144    }
    244 }
    245 
    246 // Prevent multiple template creations when choosing a template
    247 function submitTemplateForm(templateId) {
    248     const createTemplateUrl = createTemplateBaseUrl + templateId;
    249     console.log(createTemplateUrl);
    250     window.open(createTemplateUrl, '_blank');
    251 }
    252145</script>
  • opengraph-xyz/tags/1.6.0/src/ui/api-key-modal.php

    r3342214 r3616586  
    11<?php
    22// Exit if accessed directly.
    3 defined( 'ABSPATH' ) || exit;
     3defined('ABSPATH') || exit;
    44
    5 // Get the settings URL using the helper function
    6 $settings_url = opengraphxyz_get_settings_url();
     5$settings_url = opengraphxyz_get_base_url() . '/settings/api-keys';
    76?>
    87
    9 <div id="api-key-modal" class="api-key-modal" style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.5); z-index: 9999; align-items: center; justify-content: center;">
    10     <div class="modal-content" style="background: white; padding: 2rem; border-radius: 8px; max-width: 500px; width: 90%; text-align: center; box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);">
     8<div id="api-key-modal" class="api-key-modal"
     9    style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.5); z-index: 9999; align-items: center; justify-content: center;">
     10    <div class="modal-content"
     11        style="background: white; padding: 2rem; border-radius: 8px; max-width: 500px; width: 90%; text-align: center; box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);">
    1112        <div style="margin-bottom: 1rem;">
    12             <img src="<?php echo esc_url(plugin_dir_url(__FILE__) . '../../assets/icon-128x128.png'); ?>" alt="OpenGraph Logo" style="width: 3rem; height: 3rem; margin: 0 auto 1rem; display: block;">
     13            <img src="<?php echo esc_url(plugin_dir_url(__FILE__) . '../../assets/icon-128x128.png'); ?>"
     14                alt="OpenGraph Logo" style="width: 3rem; height: 3rem; margin: 0 auto 1rem; display: block;">
    1315        </div>
    14        
     16
    1517        <div class="modal-header" style="margin-bottom: 1rem;">
    1618            <h2 style="margin: 0; color: #333; font-size: 1.5rem;">API Key Required</h2>
    1719        </div>
    18        
     20
    1921        <div class="modal-body" style="margin-bottom: 2rem;">
    2022            <p style="margin: 0; color: #666; font-size: 1.1rem; line-height: 1.5;">
    … …  
    2224            </p>
    2325        </div>
    24        
     26
    2527        <div class="modal-footer" style="display: flex; gap: 1rem; justify-content: center;">
    26             <button type="button" class="button button-secondary" onclick="closeApiKeyModal()" style="padding: 0.5rem 1rem; border: 1px solid #ddd; background: #f9f9f9; border-radius: 4px; cursor: pointer;">
     28            <button type="button" class="button button-secondary" onclick="closeApiKeyModal()"
     29                style="padding: 0.5rem 1rem; border: 1px solid #ddd; background: #f9f9f9; border-radius: 4px; cursor: pointer;">
    2730                Cancel
    2831            </button>
    29             <a id="register-link" href="<?php echo esc_url($settings_url); ?>" target="_blank" class="button button-primary" style="padding: 0.5rem 1rem; background: #0073aa; color: white; text-decoration: none; border-radius: 4px; display: inline-block;">
     32            <a id="register-link" href="<?php echo esc_url($settings_url); ?>" target="_blank"
     33                class="button button-primary"
     34                style="padding: 0.5rem 1rem; background: #0073aa; color: white; text-decoration: none; border-radius: 4px; display: inline-block;">
    3035                Get API Key
    3136            </a>
    … …  
    3540
    3641<script>
    37 function showApiKeyModal() {
    38     const modal = document.getElementById('api-key-modal');
    39     modal.style.display = 'flex';
    40 }
     42    function showApiKeyModal() {
     43        const modal = document.getElementById('api-key-modal');
     44        modal.style.display = 'flex';
     45    }
    4146
    42 function closeApiKeyModal() {
    43     const modal = document.getElementById('api-key-modal');
    44     modal.style.display = 'none';
    45 }
     47    function closeApiKeyModal() {
     48        const modal = document.getElementById('api-key-modal');
     49        modal.style.display = 'none';
     50    }
    4651
    47 // Close modal when clicking outside
    48 document.addEventListener('DOMContentLoaded', function() {
    49     const modal = document.getElementById('api-key-modal');
    50     modal.addEventListener('click', function(e) {
    51         if (e.target === modal) {
    52             closeApiKeyModal();
    53         }
     52    // Close modal when clicking outside
     53    document.addEventListener('DOMContentLoaded', function () {
     54        const modal = document.getElementById('api-key-modal');
     55        modal.addEventListener('click', function (e) {
     56            if (e.target === modal) {
     57                closeApiKeyModal();
     58            }
     59        });
    5460    });
    55 });
    56 </script>
     61</script>
  • opengraph-xyz/tags/1.6.0/src/views/modifications.php

    r3487287 r3616586  
    99$custom_fields = empty($opengraphxyz['custom_fields']) ? array() : $opengraphxyz['custom_fields'];
    1010$dynamic_tags = wp_list_pluck(opengraphxyz_init()->get_tags(), 'description');
     11$variable_mapping_docs_url = opengraphxyz_get_wordpress_docs_url('variable-mapping');
    1112
    1213wp_nonce_field('opengraph-xyz', 'opengraph-xyz-nonce');
    … …  
    3940</style>
    4041
     42<div class="notice notice-info inline" style="margin: 0 0 20px;">
     43  <p>
     44    <strong><?php esc_html_e('Choose which WordPress content should appear in your Open Graph image.', 'opengraph-xyz'); ?></strong>
     45  </p>
     46  <p>
     47    <?php esc_html_e('First, select the template version you want to use. Then use the dropdowns below to connect the template\'s text and images to details from each WordPress post, such as its title, excerpt, or featured image. Choose Default to keep the text or image already saved in your OpenGraph.xyz template.', 'opengraph-xyz'); ?>
     48    <a href="<?php echo esc_url($variable_mapping_docs_url); ?>" target="_blank" rel="noopener noreferrer"><?php esc_html_e('Learn about variable mapping', 'opengraph-xyz'); ?></a>.
     49  </p>
     50</div>
     51
    4152<?php if (!empty($thumbnailUrl)): ?>
    4253<div style="margin-bottom: 20px; padding: 15px; background: #f9f9f9; border: 1px solid #ddd; border-radius: 4px;">
    … …  
    7081            <select name="opengraph[modifications][<?php echo esc_attr($variable['id']); ?>][<?php echo esc_attr($modification['property']); ?>]" id="opengraph-modification-<?php echo esc_attr($variable['id']); ?>__<?php echo esc_attr($modification['property']); ?>" class="regular-text">
    7182              <?php
    72               $current_value = isset($current_modifications[$variable['id']][$modification['property']]) ? $current_modifications[$variable['id']][$modification['property']] : '';
     83              $has_saved_mapping = isset($current_modifications[$variable['id']]) && array_key_exists($modification['property'], $current_modifications[$variable['id']]);
     84              $current_value = $has_saved_mapping ? $current_modifications[$variable['id']][$modification['property']] : opengraphxyz_get_suggested_dynamic_tag($variable, $modification['property']);
    7385              $custom_field = isset($custom_fields[$variable['id']][$modification['property']]) ? $custom_fields[$variable['id']][$modification['property']] : '';
    7486              ?>
    75               <option value="_" <?php selected($current_value, ''); ?>><?php esc_html_e('Default', 'opengraph-xyz'); ?></option>
     87              <option value="_" <?php selected($current_value, '_'); ?>><?php esc_html_e('Default', 'opengraph-xyz'); ?></option>
    7688              <?php foreach ($dynamic_tags as $dynamic_tag => $description): ?>
    7789                                <option value="{<?php echo esc_attr($dynamic_tag); ?>}" <?php selected($current_value, '{' . $dynamic_tag . '}'); ?>>
    … …  
    309321
    310322                // Add default option
    311                 var defaultOption = $('<option></option>').attr({value: ''}).text('Default');
     323                var defaultOption = $('<option></option>').attr({value: '_'}).text('Default');
    312324                select.append(defaultOption);
    313325
    … …  
    353365                  select.val(currentSelections[selectId]);
    354366                  toggleCustomFieldInput(select);
    355                 } else {
     367                } else if (modification.suggestedDynamicTag) {
     368                  select.val(modification.suggestedDynamicTag);
    356369                }
    357370
  • opengraph-xyz/trunk/opengraph-xyz.php

    r3610433 r3616586  
    44Plugin URI: https://github.com/opengraph-xyz/opengraph-wp
    55Description: Dynamic Open Graph images for your website
    6 Version: 1.5.7
     6Version: 1.6.0
    77Author: OpenGraph.xyz
    8 Author URI: https://opengraph.xyz
     8Author URI: https://www.opengraph.xyz
    99License: GPLv3
    1010License URI: https://www.gnu.org/licenses/gpl-3.0.html
  • opengraph-xyz/trunk/readme.txt

    r3610433 r3616586  
    55Tested up to: 7.1
    66Requires PHP: 5.6
    7 Version: 1.5.7
    8 Stable tag: 1.5.7
     7Version: 1.6.0
     8Stable tag: 1.6.0
    99License: GPLv3
    1010License URI: https://www.gnu.org/licenses/gpl-3.0.html
    … …  
    9494== Changelog ==
    9595
     96= 1.6.0 =
     97* Add troubleshooting help and improve the plugin menu and user experience
     98
    9699= 1.5.7 =
    97100* Fix plugin packaging so runtime assets are included in plugin releases
  • opengraph-xyz/trunk/src/Admin.php

    r3610433 r3616586  
    1717    add_action('admin_head', array($this, 'add_custom_button'));
    1818    add_action('admin_head', array($this, 'hide_add_new_button'));
     19    add_action('admin_head', array($this, 'hide_redundant_submenu_items'));
    1920    add_action('admin_init', array($this, 'register_plugin_settings'));
    2021
    … …  
    5758      null,
    5859      'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMjBweCIgaGVpZ2h0PSIxMXB4IiB2aWV3Qm94PSIwIDAgMjAgMTEiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8dGl0bGU+R3JvdXA8L3RpdGxlPgogICAgPGcgaWQ9IlBhZ2UtMSIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCI+CiAgICAgICAgPGcgaWQ9Ikdyb3VwIiBmaWxsPSIjMDAwMDAwIiBmaWxsLXJ1bGU9Im5vbnplcm8iPgogICAgICAgICAgICA8cGF0aCBkPSJNNS4wNjgwODY4NywwLjAxMzQ5NDY4NDkgQzMuNTkxODgzMjMsMC4xMTU0ODYyODcgMi4xNTQxMzkyOCwwLjg2MzYwODk3MSAxLjIyMTI4MzEyLDIuMDE0OTk5MjYgQy0wLjM2NDczOTE3OCwzLjk3Mjc0MDUxIC0wLjQxMDMzNDc3LDYuNzIzNDczMzcgMS4xMDk4ODkwMSw4LjczMzczMDYxIEMxLjk1NzQ4NTEyLDkuODU0NjI0NzcgMy4yNjQ3NDQxMiwxMC42Mjk5MjY4IDQuNjU3MzU1ODQsMTAuODM3ODcxNyBDNS4wMDQ3OTA1NSwxMC44ODk3NDI4IDYuMDMyMDgxNDksMTAuODgzMDE3MSA2LjM1MzQ3NDgxLDEwLjgyNjgxNTcgQzcuNTYzMzMzNDcsMTAuNjE1MDkzMyA4LjU2MTk4ODE1LDEwLjA5NDcyNDIgOS4zOTIzNDY5MSw5LjI0MzQxMjIzIEM5LjU1ODk3NDcsOS4wNzI1OTcwMiA5Ljc1OTcwNjUyLDguODQ2OTYyNDggOS44Mzg0NzkzOSw4Ljc0MjAyMjYxIEM5LjkxNzM0NDk0LDguNjM3MTc0ODggOS45OTM3MDgyOSw4LjU1MTMwNjYxIDEwLjAwODI1ODEsOC41NTEzMDY2MSBDMTAuMDIyODA3OSw4LjU1MTMwNjYxIDEwLjEwMTk1MTUsOC42NDQ2Mzc2OCAxMC4xODQxNTMzLDguNzU4NjA2NjEgQzEwLjQ5OTMzNzUsOS4xOTU1OTUwMiAxMS4xMjkyNDI0LDkuNzYwMDAzODQgMTEuNjkxOTU4OCwxMC4xMDk0NjU2IEMxMi4yMzQ1NjQ4LDEwLjQ0NjQ4OTMgMTMuMDQ0NzIwNywxMC43NDAyMTA0IDEzLjcwMTEzMDQsMTAuODM3OTYzOSBDMTQuMDY1NTI0NCwxMC44OTIyMzA0IDE1LjE0MTc0NzIsMTAuODgzMDE3MSAxNS40ODg5MDM5LDEwLjgyMjY2OTcgQzE3LjQ1MTM2NzksMTAuNDgxMzE1NyAxOS4wOTk2NjcxLDkuMDY4OTExNjkgMTkuNzMwMDM1NCw3LjE4ODU2MjQ1IEMxOS45MTIyMzI0LDYuNjQ0NzkxNSAxOS45OTY5MzY0LDYuMTU1ODM5ODkgMTkuOTk5NzE2Niw1LjYzMTY5MzM0IEMyMC4wMDE3NTU1LDUuMjMwOTEzMzQgMTkuOTk0MjQ4OSw1LjE2OTQ2MDQgMTkuOTI4NTQzLDUuMDQ3MTk5NDYgQzE5LjgwODkwMDksNC44MjQ4ODE3MyAxOS42OTQ1NDEzLDQuNzEyNjYzMzIgMTkuNDc4MDU0OSw0LjYwNTE0MzcyIEwxOS4yNzM4OTQxLDQuNTAzNzA0OTIgTDE2Ljg0ODk4NzEsNC41MDM3MDQ5MiBDMTQuMDc1OTAzOSw0LjUwMzcwNDkyIDE0LjIyMTY4MDEsNC40ODk3MDA2NSAxMy45MjYxNDI4LDQuNzgzNTEzODYgQzEzLjQ2NjAxNjUsNS4yNDA5NTU4NyAxMy41ODA0Njg5LDUuOTg1NzYxNzUgMTQuMTU3MzY0Myw2LjI4ODIzNTQ5IEwxNC4zMjg4MTEyLDYuMzc4MTU3NjMgTDE2LjE1NDc2NjQsNi4zODc1NTUyMyBMMTcuOTgwODE0Miw2LjM5Njk1MjgzIEwxNy44OTQzNDk0LDYuNjM2NDA3MzcgQzE3LjIzOTA1MTgsOC40NTE0MzQwNyAxNS4yMTM4NDc2LDkuNDQyMDUxNyAxMy40MTQwMjY0LDguODI3OTgzMDIgQzEyLjI2OTEzMjIsOC40Mzc0Mjk4MSAxMS40NTA5MTM4LDcuNTg2NjcwNTkgMTEuMDg2NTE5Nyw2LjQwODAwODgzIEMxMC45OTk5NjIyLDYuMTI4MTk5ODkgMTAuOTk1MTQzMiw2LjA3ODE3MTQ5IDEwLjk5NTE0MzIsNS40NDkxNzcyMSBDMTAuOTk1MTQzMiw0LjgyMzIyMzMzIDExLjAwMDMzMjksNC43Njg3NzI1MyAxMS4wODU1OTMsNC40ODcxMjA5MiBDMTEuNTk5NTYyOCwyLjc5MDM5MzQxIDEzLjE3MTY4NCwxLjczMzcxNjE5IDE0LjkxODQ5NTYsMS45MTA3MDQzMyBDMTUuMzcwODM3MywxLjk1NjU4NjczIDE1LjcwMDU3MTMsMi4wNDM4MzcgMTYuMDc0NTEwNywyLjIxNjU4NyBDMTYuNjA0MTQyNCwyLjQ2MTI5MzE0IDE2Ljk3MDAxOTMsMi43NDIxMTU1NSAxNy4zNTI1Nzc0LDMuMTk3NDM4NDkgQzE3LjY0MjY0NjksMy41NDI2NjIxIDE3LjgwODI1NTMsMy42NDQ1NjE1NyAxOC4xMTQ1NDI4LDMuNjY2Mzk3MTcgQzE4LjUyNTM2NjUsMy42OTU2MDM0MyAxOC44MzY2NTgzLDMuNTI4NDczNTYgMTkuMDM1MzUxMywzLjE3MTkxNzU2IEMxOS4xMjIwMDE1LDMuMDE2MzA0MzUgMTkuMTM0MzI3MSwyLjk2MDkzMjIyIDE5LjEzNDMyNzEsMi43Mjg2NjQwOCBDMTkuMTM0MzI3MSwyLjQ5NDI3Njg3IDE5LjEyMjY1MDIsMi40NDMwNTA3NCAxOS4wMzQyMzkyLDIuMjkwMzg1OCBDMTguNzk1Njk2NSwxLjg3ODU0OTc5IDE4LjE5ODY5MDcsMS4yOTQ2MDg3MSAxNy42MjYwNTgzLDAuOTEzMDg0NTcyIEMxNy4wMzQ3MDU3LDAuNTE5MTIyNDMgMTYuMjM1NzYzNCwwLjE5ODEyOTg4OSAxNS41MzAyMzY1LDAuMDcwOTg1ODg2MiBDMTUuMDk0NDgzNSwtMC4wMDc0MTk1ODIxNSAxNC4xMDU2NTIzLC0wLjAwODcwOTQ0ODg0IDEzLjY0NDMyMTIsMC4wNjg2ODI1NTI5IEMxMi43NjAxMTg5LDAuMjE2ODMyOTU2IDExLjkyNDAxNDQsMC41NzgwODc3NjQgMTEuMjAzODQ1LDEuMTIzMTQ4NTggQzEwLjg3NTEzMDQsMS4zNzE5MDg1OCAxMC4zOTk3MTI5LDEuODQzMzU0ODYgMTAuMTg2NTYyOCwyLjEzMjAwODYgQzEwLjA5OTE3MTMsMi4yNTAzMDc4IDEwLjAxNzM0MDEsMi4zNDcxMzk5NCAxMC4wMDQ3MzY1LDIuMzQ3MTM5OTQgQzkuOTkyMTMyODMsMi4zNDcxMzk5NCA5Ljg5OTQ1ODg2LDIuMjM4ODgzMjcgOS43OTg3MjIyNiwyLjEwNjU3OTggQzkuNTc2Mzk3NDEsMS44MTQ2MDkyNiA5LjA2Nzg5NTM0LDEuMzEyOTQzMjUgOC43NzIzNTgwNiwxLjA5NDAzNDQ0IEM3LjcwMjI1MTc0LDAuMzAxNDExMzU4IDYuMzk5OTA0NDcsLTAuMDc4NDU0MzgzOCA1LjA2ODA4Njg3LDAuMDEzNDk0Njg0OSBNNS45MDMyNjQ2NywxLjkxNzA2MTUzIEM2LjMxNzE0NjYxLDEuOTY3MzY2MzMgNi42NDMzNTg5OCwyLjA2MzU1MzUzIDcuMDI1MDgzMDYsMi4yNDc4MjAyIEM4LjI3MDQzNTg0LDIuODQ4OTkwMjIgOS4wMzkzNTE3Niw0LjA2ODQ2NzA0IDkuMDM5MzUxNzYsNS40NDI0NTE0NyBDOS4wMzkzNTE3Niw3LjI2NzI0NDMxIDcuNzI0OTU2ODcsOC43NDA1NDg0OCA1Ljg3ODQyODA1LDguOTg1NTMxMDIgQzQuODQ5MjgzNjMsOS4xMjIwNzI2MiAzLjcxMTg5NjAyLDguNzI0NDI1MTUgMi45NTQ4NDIzNyw3Ljk2MzIxOTUzIEMyLjUxNzIzNTg5LDcuNTIzMjgyODUgMi4yNzMwMzk5OCw3LjEyODIxNTExIDIuMDg0MjYzMTEsNi41NTUxNDU3NyBDMS4zMzQxNjAwMSw0LjI3NzYwOTcxIDMuMDA2MTgzNzUsMS45MzczMzA4NiA1LjQxOTQxMzg4LDEuODg2ODQxNzkgQzUuNTI5OTczOTMsMS44ODQ1Mzg0NiA1Ljc0Nzc1Nzc1LDEuODk4MTc0MTkgNS45MDMyNjQ2NywxLjkxNzA2MTUzIiBpZD0iU2hhcGUiPjwvcGF0aD4KICAgICAgICA8L2c+CiAgICA8L2c+Cjwvc3ZnPg=='
    59     );
    60 
    61     // Add the submenu item with a different name but same slug as the main menu item
    62     add_submenu_page(
    63       'edit.php?post_type=opengraph_template', // Parent slug
    64       'OG Manager',               // Page title
    65       'OG Manager',                   // Menu title
    66       'manage_options',                        // Capability
    67       'edit.php?post_type=opengraph_template', // Menu slug
    68       null                                     // Function (not needed as it's the same as the main menu)
    6960    );
    7061
    … …  
    150141
    151142    do_action('cloudpdf-xyz_save_metabox', $post_id);
     143
     144    wp_redirect(admin_url('edit.php?post_type=opengraph_template'));
     145    exit;
    152146  }
    153147
    154148  public function handle_template_creation()
    155149  {
    156     $templateId = isset($_POST['template_id']) ? sanitize_text_field($_POST['template_id']) : '';
    157     $templateName = isset($_POST['template_name']) ? sanitize_text_field($_POST['template_name']) : '';
    158     $templateVersion = isset($_POST['template_version']) ? sanitize_text_field($_POST['template_version']) : '';
     150    if (!current_user_can('manage_options')) {
     151      wp_die(__('You are not allowed to add Open Graph templates.', 'opengraph-xyz'));
     152    }
     153
     154    check_admin_referer('opengraph_xyz_select_template_action', 'opengraph_xyz_select_template_nonce');
     155
     156    $templateId = isset($_POST['template_id']) ? sanitize_text_field(wp_unslash($_POST['template_id'])) : '';
     157    $templateName = isset($_POST['template_name']) ? sanitize_text_field(wp_unslash($_POST['template_name'])) : '';
     158    $templateVersion = isset($_POST['template_version']) ? sanitize_text_field(wp_unslash($_POST['template_version'])) : '';
    159159
    160160    $new_post = array(
    … …  
    176176
    177177    if ($postId) {
    178       // Redirect to the edit post screen or a confirmation page
    179178      wp_redirect(admin_url('post.php?post=' . $postId . '&action=edit'));
    180179      exit;
    … …  
    254253  }
    255254
     255  /**
     256   * Display shared troubleshooting guidance.
     257   */
     258  public function display_troubleshooting()
     259  {
     260    include plugin_dir_path(__FILE__) . 'views/troubleshooting.php';
     261  }
     262
    256263  public function register_plugin_settings()
    257264  {
    … …  
    373380      'default'
    374381    );
     382
     383    add_meta_box(
     384      'opengraph_template-troubleshooting',
     385      __('Troubleshooting', 'opengraph-xyz'),
     386      array($this, 'display_troubleshooting'),
     387      null,
     388      'normal',
     389      'low'
     390    );
    375391  }
    376392
    … …  
    419435    global $submenu;
    420436
     437    $parent_slug = 'edit.php?post_type=opengraph_template';
     438
    421439    // Remove default "Add New" submenu
    422     if (isset($submenu['edit.php?post_type=opengraph_template'])) {
    423       foreach ($submenu['edit.php?post_type=opengraph_template'] as $key => $item) {
     440    if (isset($submenu[$parent_slug])) {
     441      foreach ($submenu[$parent_slug] as $key => $item) {
    424442        if ($item[2] === 'post-new.php?post_type=opengraph_template') {
    425           unset($submenu['edit.php?post_type=opengraph_template'][$key]);
     443          unset($submenu[$parent_slug][$key]);
    426444          break;
    427445        }
    … …  
    430448
    431449    add_submenu_page(
    432       'edit.php?post_type=opengraph_template',
    433       'Select OG Template',
    434       'Select OG Template',
     450      $parent_slug,
     451      'Add OG Template',
     452      'Add OG Template',
    435453      'manage_options', // Standard capability
    436454      'opengraph_template_selection',
    … …  
    438456      1
    439457    );
     458
     459  }
     460
     461  /**
     462   * Hide routing-only submenu rows while preserving WordPress page metadata.
     463   */
     464  public function hide_redundant_submenu_items()
     465  {
     466    echo '<style type="text/css">
     467            #adminmenu .wp-submenu a[href="edit.php?post_type=opengraph_template"],
     468            #adminmenu .wp-submenu a[href*="page=opengraph_template_selection"] { display: none; }
     469          </style>
     470          <script type="text/javascript">
     471            jQuery(document).ready(function($) {
     472              $("#adminmenu .wp-submenu a[href=\"edit.php?post_type=opengraph_template\"], #adminmenu .wp-submenu a[href*=\"page=opengraph_template_selection\"]").parent().remove();
     473            });
     474          </script>';
    440475  }
    441476
    … …  
    483518
    484519    $variables = $data['data']['variables'];
     520
     521    foreach ($variables as &$variable) {
     522      if (empty($variable['modifications']) || !is_array($variable['modifications'])) {
     523        continue;
     524      }
     525
     526      foreach ($variable['modifications'] as &$modification) {
     527        $property = isset($modification['property']) ? $modification['property'] : '';
     528        $modification['suggestedDynamicTag'] = opengraphxyz_get_suggested_dynamic_tag($variable, $property);
     529      }
     530      unset($modification);
     531    }
     532    unset($variable);
    485533
    486534    wp_send_json_success(array('variables' => $variables));
    … …  
    577625    global $pagenow, $typenow, $post;
    578626
     627    if ($this->is_opengraph_template_selection_page()) {
     628      return;
     629    }
     630
    579631    if (($pagenow == 'edit.php' || $pagenow == 'post.php') && $typenow == 'opengraph_template') {
    580       $customButton = '<a href="edit.php?post_type=opengraph_template&page=opengraph_template_selection" class="page-title-action title-new-template">Select OG Template</a>';
     632      $customButton = $pagenow == 'edit.php'
     633        ? '<a href="edit.php?post_type=opengraph_template&page=opengraph_template_selection" class="page-title-action title-new-template">Add OG Template</a>'
     634        : '';
    581635
    582636      // Add Edit on Open Graph button only on post edit page (post.php) and if post has a template
    … …  
    590644      }
    591645
    592       // Combine both buttons into one string (Edit on Open Graph first, then Select OG Template)
     646      // Show Edit on Open Graph on detail pages and Add OG Template on the overview.
    593647      $allButtons = $editButton . $customButton;
    594648
    … …  
    610664  {
    611665    global $pagenow, $typenow;
     666
     667    if ($this->is_opengraph_template_selection_page()) {
     668      return;
     669    }
    612670
    613671    if (($pagenow == 'edit.php' || $pagenow == 'post.php') && $typenow == 'opengraph_template') {
  • opengraph-xyz/trunk/src/Plugin.php

    r3342214 r3616586  
    131131      'name_admin_bar' => _x('OG Image Template', 'add new on admin bar', 'opengraph-xyz'),
    132132      'add_new' => _x('Add New', 'template', 'opengraph-xyz'),
    133       'add_new_item' => __('Select OG Template', 'opengraph-xyz'),
     133      'add_new_item' => __('Add OG Template', 'opengraph-xyz'),
    134134      'new_item' => __('New Template', 'opengraph-xyz'),
    135135      'edit_item' => __('Match Variables', 'opengraph-xyz'),
  • opengraph-xyz/trunk/src/functions.php

    r3473900 r3616586  
    1616function opengraphxyz_get_base_url()
    1717{
    18     return defined('OPENGRAPHXYZ_BASE_URL') ? OPENGRAPHXYZ_BASE_URL : 'https://dashboard.opengraph.xyz';
     18    return defined('OPENGRAPHXYZ_BASE_URL') ? OPENGRAPHXYZ_BASE_URL : 'https://www.opengraph.xyz';
     19}
     20
     21/**
     22 * Get the WordPress integration documentation URL.
     23 *
     24 * @param string $section Optional documentation section anchor.
     25 * @return string The WordPress documentation URL.
     26 */
     27function opengraphxyz_get_wordpress_docs_url($section = '')
     28{
     29    $url = opengraphxyz_get_base_url() . '/docs/wordpress';
     30
     31    return empty($section) ? $url : $url . '#' . sanitize_title($section);
     32}
     33
     34/**
     35 * Suggest a WordPress dynamic tag for a common template variable.
     36 *
     37 * @param array  $variable Template variable data.
     38 * @param string $property Modification property.
     39 * @return string Suggested dynamic tag, or an empty string when none applies.
     40 */
     41function opengraphxyz_get_suggested_dynamic_tag($variable, $property)
     42{
     43    $suggestions = array(
     44        'title' => array(
     45            'properties' => array('text'),
     46            'tag' => '{post_title}',
     47        ),
     48        'description' => array(
     49            'properties' => array('text'),
     50            'tag' => '{post_excerpt}',
     51        ),
     52        'image' => array(
     53            'properties' => array('src', 'url'),
     54            'tag' => '{featured_image}',
     55        ),
     56        'url' => array(
     57            'properties' => array('text', 'url'),
     58            'tag' => '{post_url}',
     59        ),
     60        'link' => array(
     61            'properties' => array('text', 'url'),
     62            'tag' => '{post_url}',
     63        ),
     64    );
     65
     66    $variable_names = array_filter(array($variable['name'] ?? '', $variable['id'] ?? ''));
     67
     68    foreach ($variable_names as $variable_name) {
     69        $variable_name = strtolower((string) $variable_name);
     70        $variable_name = preg_replace('/[^a-z0-9]+/', '_', $variable_name);
     71        $variable_name = trim($variable_name, '_');
     72
     73        if (preg_match('/^image_?\d+$/', $variable_name)) {
     74            $variable_name = 'image';
     75        }
     76
     77        if (!isset($suggestions[$variable_name])) {
     78            continue;
     79        }
     80
     81        $suggestion = $suggestions[$variable_name];
     82
     83        if (in_array(strtolower($property), $suggestion['properties'], true)) {
     84            return $suggestion['tag'];
     85        }
     86    }
     87
     88    return '';
    1989}
    2090
    … …  
    39109{
    40110    return defined('OPENGRAPHXYZ_BASE_IMAGE_URL') ? OPENGRAPHXYZ_BASE_IMAGE_URL : 'https://ogcdn.net';
    41 }
    42 
    43 /**
    44  * Get the create template base URL without URL encoding for JavaScript concatenation
    45  *
    46  * @return string The base URL for creating templates
    47  */
    48 function opengraphxyz_get_create_template_baseurl_raw()
    49 {
    50     $base_url = opengraphxyz_get_base_url();
    51     return $base_url . "/register?redirect=/org/[organizationId]/create-template/";
    52 }
    53 
    54 // /org/1/template-editor/c91f620c-b194-449e-86c6-f332e98caf2d
    55 
    56 /**
    57  * Get the OpenGraph.xyz settings URL with wp parameter
    58  *
    59  * @return string The settings URL for OpenGraph.xyz
    60  */
    61 function opengraphxyz_get_settings_url()
    62 {
    63     $base_url = opengraphxyz_get_base_url();
    64     $current_domain = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https://' : 'http://') . ($_SERVER['HTTP_HOST'] ?? '');
    65 
    66     return $base_url . "/register?redirect=/org/[organizationId]/settings/api-keys?wp=" . urlencode($current_domain);
    67111}
    68112
    … …  
    179223{
    180224    $base_url = opengraphxyz_get_base_url();
    181     return $base_url . "/register?redirect=/org/[organizationId]/template-editor/" . $template_id;
    182 }
     225    return $base_url . "/generate/" . $template_id;
     226}
  • opengraph-xyz/trunk/src/templates/admin.php

    r3390572 r3616586  
    1010}
    1111
    12 // Get the settings URL using the helper function
    13 $settings_url = opengraphxyz_get_settings_url();
     12$settings_url = opengraphxyz_get_base_url() . '/settings/api-keys';
    1413
    1514// Check if user was redirected from OpenGraph.xyz
    … …  
    5958    <?php if ($redirected_from_opengraphxyz): ?>
    6059        <!-- Message for users redirected from OpenGraph.xyz -->
    61         <div class="api-key-info-banner" style="margin-top: 10px; max-width: 700px; border: 1px solid #007cba; background-color: #eef5fa; color: #007cba; padding: 15px; margin-bottom: 20px; border-radius: 5px;">
     60        <div class="api-key-info-banner"
     61            style="margin-top: 10px; max-width: 700px; border: 1px solid #007cba; background-color: #eef5fa; color: #007cba; padding: 15px; margin-bottom: 20px; border-radius: 5px;">
    6262            <strong>Paste your API key from OpenGraph.xyz in the box below and click save</strong>
    6363        </div>
    6464    <?php else: ?>
    6565        <!-- Banner for API Key information -->
    66         <div class="api-key-info-banner" style="margin-top: 10px; max-width: 700px; border: 1px solid #007cba; background-color: #eef5fa; color: #007cba; padding: 15px; margin-bottom: 20px; border-radius: 5px;">
    67             <strong>Need an API Key?</strong> Obtain your API key from your OpenGraph.xyz account by clicking the button below. In the OpenGraph.xyz dashboard, go to <em>Settings > API Keys</em> to find your existing keys or create a new one by clicking on <em>Create new API key</em>.
     66        <div class="api-key-info-banner"
     67            style="margin-top: 10px; max-width: 700px; border: 1px solid #007cba; background-color: #eef5fa; color: #007cba; padding: 15px; margin-bottom: 20px; border-radius: 5px;">
     68            <strong>Need an API Key?</strong> Get your API key from your OpenGraph.xyz API Key Settings page.
    6869
    6970            <div style="margin-top:20px;">
    70                 <a href="<?php echo esc_url($settings_url); ?>" target="_blank" class="button button-primary" style="background: #0073aa; border-color: #0073aa; color: white; padding: 8px 16px; font-size: 14px; line-height: 1.4; border-radius: 4px; cursor: pointer; text-decoration: none; display: inline-block;">
    71                     <span class="dashicons dashicons-external" style="margin-right: 5px;"></span>
    72                     Go to OpenGraph.xyz Settings
     71                <a href="<?php echo esc_url($settings_url); ?>" target="_blank" class="button button-primary"
     72                    style="background: #0073aa; border-color: #0073aa; color: white; padding: 8px 16px; font-size: 14px; line-height: 1.4; border-radius: 4px; cursor: pointer; text-decoration: none; display: inline-flex; align-items: center; gap: 6px;">
     73                    <span class="dashicons dashicons-external" style="margin: 0; line-height: 1;"></span>
     74                    OpenGraph API Key Settings
    7375                </a>
    7476            </div>
    … …  
    8991                    <th scope="row">API Key</th>
    9092                    <td>
    91                         <textarea
    92                             name="opengraph_xyz_api_key"
     93                        <textarea name="opengraph_xyz_api_key"
    9394                            style="width: 100%; min-height: 100px; font-family: 'Courier New', monospace; font-size: 13px; padding: 8px; border: 1px solid #ddd; border-radius: 4px; resize: vertical;"
    94                             placeholder="Paste your OpenGraph.xyz API key here..."
    95                         ><?php echo esc_textarea(get_option('opengraph_xyz_api_key')); ?></textarea>
    96                         <p class="description">Your API key will be securely stored and used to connect to OpenGraph.xyz services.</p>
     95                            placeholder="Paste your OpenGraph.xyz API key here..."><?php echo esc_textarea(get_option('opengraph_xyz_api_key')); ?></textarea>
     96                        <p class="description">Your API key will be securely stored and used to connect to OpenGraph.xyz
     97                            services.</p>
    9798                    </td>
    9899                </tr>
    … …  
    204205
    205206    // Auto-hide toast after 5 seconds
    206     document.addEventListener('DOMContentLoaded', function() {
     207    document.addEventListener('DOMContentLoaded', function () {
    207208        const toast = document.getElementById('opengraph-xyz-toast');
    208209        if (toast) {
    … …  
    221222    }
    222223
    223     document.addEventListener('DOMContentLoaded', function() {
     224    document.addEventListener('DOMContentLoaded', function () {
    224225        const errorToast = document.getElementById('opengraph-xyz-error-toast');
    225226        if (errorToast) {
    … …  
    231232
    232233    // Show loading overlay when form is submitted
    233     document.addEventListener('DOMContentLoaded', function() {
     234    document.addEventListener('DOMContentLoaded', function () {
    234235        const form = document.querySelector('form[action="options.php"]');
    235236        if (form) {
    236             form.addEventListener('submit', function() {
     237            form.addEventListener('submit', function () {
    237238                showLoadingOverlay();
    238239            });
  • opengraph-xyz/trunk/src/templates/template_selection.php

    r3342214 r3616586  
    22
    33// Exit if accessed directly.
    4 defined( 'ABSPATH' ) || exit;
     4defined('ABSPATH') || exit;
    55
    66// Check user capabilities
    7 if ( ! current_user_can( 'manage_options' ) ) {
     7if (!current_user_can('manage_options')) {
    88    return;
    99}
    1010
    11 // Get the create template base URL
    12 $create_template_base_url = opengraphxyz_get_create_template_baseurl_raw();
     11$create_template_url = opengraphxyz_get_base_url() . '/generate';
    1312
    1413$apiKey = get_option('opengraph_xyz_api_key'); // Assuming the API key is stored with this name
    … …  
    1817$hasApiKey = !empty($apiKey);
    1918
    20 // Split templates into user templates and stock templates
    2119$userTemplates = array();
    22 $stockTemplates = array();
    2320
    24 if ( isset( $templates['edges'] ) && is_array( $templates['edges'] ) ) {
    25     foreach ( $templates['edges'] as $edge ) {
     21if (isset($templates['edges']) && is_array($templates['edges'])) {
     22    foreach ($templates['edges'] as $edge) {
    2623        $template = $edge['node'];
    27         if ( isset( $template['organizationId'] ) && !empty( $template['organizationId'] ) ) {
     24        if (isset($template['organizationId']) && !empty($template['organizationId'])) {
    2825            $userTemplates[] = $edge;
    29         } else {
    30             $stockTemplates[] = $edge;
    3126        }
    3227    }
    3328}
    34 
    35 // Determine default tab - if user has templates, default to "Your Templates", otherwise "Stock Templates"
    36 $defaultTab = !empty($userTemplates) ? 'your-templates' : 'stock-templates';
    3729
    3830// Template selection view
    … …  
    4032
    4133<div class="wrap">
    42     <h1 style="margin-bottom: 20px">Select OG Image Template</h1>
     34    <h1 class="wp-heading-inline">Select OG Image Template</h1>
     35    <a href="<?php echo esc_url($create_template_url); ?>" target="_blank" rel="noopener noreferrer"
     36        class="page-title-action">Add new template</a>
     37    <hr class="wp-header-end">
    4338
    44     <?php if ( isset( $templates['authenticated'] ) && ! $templates['authenticated'] ) : ?>
     39    <?php if (isset($templates['authenticated']) && !$templates['authenticated']): ?>
    4540        <!-- Banner for unauthenticated users -->
    46         <div class="unauthenticated-banner" style="border: 1px solid #eab308; color: #854d0e; background-color: #ffffcc; padding: 20px; margin-bottom: 20px; border-radius: 6px; display: flex; align-items: center; gap: 10px;">
    47             <svg style="width: 1.5rem; height: 1.5rem; fill: #eab308; flex-shrink: 0;" width="24" height="24" fill="currentColor" viewBox="0 0 24 24">
    48               <path d="M5 16L3 5L8.5 10L12 4L15.5 10L21 5L19 16H5M19 19C19 19.6 18.6 20 18 20H6C5.4 20 5 19.6 5 19V18H19V19Z"></path>
     41        <div class="unauthenticated-banner"
     42            style="border: 1px solid #eab308; color: #854d0e; background-color: #ffffcc; padding: 20px; margin-bottom: 20px; border-radius: 6px; display: flex; align-items: center; gap: 10px;">
     43            <svg style="width: 1.5rem; height: 1.5rem; fill: #eab308; flex-shrink: 0;" width="24" height="24"
     44                fill="currentColor" viewBox="0 0 24 24">
     45                <path
     46                    d="M5 16L3 5L8.5 10L12 4L15.5 10L21 5L19 16H5M19 19C19 19.6 18.6 20 18 20H6C5.4 20 5 19.6 5 19V18H19V19Z">
     47                </path>
    4948            </svg>
    50             <p style="margin: 0; font-size: 1.2em;">Create unique, custom Open Graph image templates that truly represent your brand's identity.</p>
    51             <a href="https://www.opengraph.xyz/get-started" target="_blank" style="text-decoration: underline; font-weight: bold; color: #854d0e; flex-shrink: 0;">Learn More</a>
     49            <p style="margin: 0; font-size: 1.2em;">Create unique, custom Open Graph image templates that truly represent
     50                your brand's identity.</p>
     51            <a href="https://www.opengraph.xyz/get-started" target="_blank"
     52                style="text-decoration: underline; font-weight: bold; color: #854d0e; flex-shrink: 0;">Learn More</a>
    5253        </div>
    5354    <?php endif; ?>
    5455
    55     <!-- Tab Navigation -->
    56     <div class="tab-navigation" style="margin-bottom: 0; border-bottom: 1px solid #dcdcde;">
    57         <button class="tab-button <?php echo $defaultTab === 'your-templates' ? 'active' : ''; ?>" data-tab="your-templates" style="padding: 12px 24px; margin-right: 0; border: 1px solid #dcdcde; border-bottom: none; background: <?php echo $defaultTab === 'your-templates' ? '#fff' : '#f9f9f9'; ?>; cursor: pointer; border-radius: 4px 4px 0 0; font-weight: 500; color: <?php echo $defaultTab === 'your-templates' ? '#1d2327' : '#646970'; ?>; position: relative; top: 1px;">
    58             Your Templates (<?php echo count($userTemplates); ?>)
    59         </button>
    60         <button class="tab-button <?php echo $defaultTab === 'stock-templates' ? 'active' : ''; ?>" data-tab="stock-templates" style="padding: 12px 24px; margin-right: 0; border: 1px solid #dcdcde; border-bottom: none; background: <?php echo $defaultTab === 'stock-templates' ? '#fff' : '#f9f9f9'; ?>; cursor: pointer; border-radius: 4px 4px 0 0; font-weight: 500; color: <?php echo $defaultTab === 'stock-templates' ? '#1d2327' : '#646970'; ?>; position: relative; top: 1px;">
    61             Stock Templates (<?php echo count($stockTemplates); ?>)
    62         </button>
     56    <div
     57        style="margin-top: 20px; margin-bottom: 20px; border: 1px solid #007cba; background-color: #eef5fa; color: #007cba; padding: 15px; border-radius: 5px;">
     58        <strong>Choose one of your templates to add it to WordPress.</strong>
    6359    </div>
     60    <?php if (!empty($userTemplates)): ?>
     61        <div class="template-grid"
     62            style="display: grid; grid-template-columns: repeat(auto-fill, minmax(500px, 1fr)); gap: 20px;">
     63            <?php foreach ($userTemplates as $edge):
     64                $template = $edge['node'];
     65                $name = $template['name'];
     66                $id = $template['id'];
     67                $version = $template['activeVersion'];
     68                $versionNumber = $version['versionNumber'];
    6469
    65     <!-- Your Templates Tab -->
    66     <div id="your-templates" class="tab-content" style="display: <?php echo $defaultTab === 'your-templates' ? 'block' : 'none'; ?>;">
    67         <div style="margin-top: 20px; margin-bottom: 20px; border: 1px solid #007cba; background-color: #eef5fa; color: #007cba; padding: 15px; border-radius: 5px;">
    68             <strong>Click a template card to create a dynamic Open Graph image template.</strong>
    69         </div>
    70         <?php if ( !empty($userTemplates) ) : ?>
    71             <div class="template-grid" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(500px, 1fr)); gap: 20px;">
    72                 <?php foreach ( $userTemplates as $edge ) :
    73                     $template       = $edge['node'];
    74                     $name           = $template['name'];
    75                     $id             = $template['id'];
    76                     $premium        = $template['isPremium'];
    77                     $organizationId = $template['organizationId'];
    78                     $version        = $template['activeVersion'];
    79                     $versionNumber  = $version['versionNumber'];
    80                    
    81                     // Generate image URL
    82                     $imageUrl = opengraphxyz_generate_image_url($id, $versionNumber, $version['data']['variables']);
    83                     ?>
    84                     <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" class="template-form" id="template-form-<?php echo esc_attr( $id ); ?>">
    85                         <?php wp_nonce_field( 'opengraph_xyz_select_template_action', 'opengraph_xyz_select_template_nonce' ); ?>
     70                // Generate image URL
     71                $imageUrl = opengraphxyz_generate_image_url($id, $versionNumber, $version['data']['variables']);
     72                ?>
     73                <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" class="template-form"
     74                    id="template-form-<?php echo esc_attr($id); ?>">
     75                    <?php wp_nonce_field('opengraph_xyz_select_template_action', 'opengraph_xyz_select_template_nonce'); ?>
    8676
    87                         <input type="hidden" name="action" value="create_opengraph_template">
    88                         <input type="hidden" name="template_id" value="<?php echo esc_attr( $id ); ?>">
    89                         <input type="hidden" name="template_name" value="<?php echo esc_attr( $name ); ?>">
    90                         <input type="hidden" name="template_version" value="<?php echo esc_attr( $versionNumber ); ?>">
    91                        
    92                         <div onclick="handleTemplateClick('<?php echo esc_attr( $id ); ?>', 'user')" style="cursor: pointer; border-radius: 6px; overflow: hidden; box-shadow: 0 1px 1px -1px rgba(0,0,0,.1); border: 1px solid #dcdcde;">
    93                             <div class="template-card" style="position: relative; padding-top: 52.5%; background-color: #fff">
    94                                 <img src="<?php echo esc_url( $imageUrl ); ?>" alt="<?php echo esc_attr( $name ); ?>" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover;">
    95                             </div>
    96                             <div class="template-details" style="width: 100%; background: rgba(255,255,255,.65); color: #000; text-align: center; font-size: 16px;">
    97                                 <div style="padding: 1rem; display: flex; align-items: center; justify-content: center; gap: .5rem; border-top: 1px solid #dcdcde;">
    98                                     <?php echo esc_html( $name ); ?>
    99                                 </div>
     77                    <input type="hidden" name="action" value="create_opengraph_template">
     78                    <input type="hidden" name="template_id" value="<?php echo esc_attr($id); ?>">
     79                    <input type="hidden" name="template_name" value="<?php echo esc_attr($name); ?>">
     80                    <input type="hidden" name="template_version" value="<?php echo esc_attr($versionNumber); ?>">
     81
     82                    <div onclick="handleTemplateClick('<?php echo esc_attr($id); ?>')"
     83                        style="cursor: pointer; border-radius: 6px; overflow: hidden; box-shadow: 0 1px 1px -1px rgba(0,0,0,.1); border: 1px solid #dcdcde;">
     84                        <div class="template-card" style="position: relative; padding-top: 52.5%; background-color: #fff">
     85                            <img src="<?php echo esc_url($imageUrl); ?>" alt="<?php echo esc_attr($name); ?>"
     86                                style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover;">
     87                        </div>
     88                        <div class="template-details"
     89                            style="width: 100%; background: rgba(255,255,255,.65); color: #000; text-align: center; font-size: 16px;">
     90                            <div
     91                                style="padding: 1rem; display: flex; align-items: center; justify-content: center; gap: .5rem; border-top: 1px solid #dcdcde;">
     92                                <?php echo esc_html($name); ?>
    10093                            </div>
    10194                        </div>
    102                     </form>
    103                 <?php endforeach; ?>
    104             </div>
    105         <?php elseif ( !$hasApiKey ) : ?>
    106             <div style="text-align: center; padding: 40px; background: #f9f9f9; border-radius: 6px;">
    107                 <p style="font-size: 1.2em; color: #666; margin-bottom: 20px;">Connect your Open Graph account with an API Key to see your custom templates.</p>
    108                 <a href="<?php echo esc_url( admin_url( 'edit.php?post_type=opengraph_template&page=og-xyz-settings' ) ); ?>" style="background: #0073aa; color: white; padding: 10px 20px; text-decoration: none; border-radius: 4px;">Add an API Key</a>
    109             </div>
    110         <?php else : ?>
    111             <div style="text-align: center; padding: 40px; background: #f9f9f9; border-radius: 6px;">
    112                 <p style="font-size: 1.2em; color: #666; margin-bottom: 20px;">You don't have any custom templates yet.</p>
    113                 <a href="https://www.opengraph.xyz/get-started" target="_blank" style="background: #0073aa; color: white; padding: 10px 20px; text-decoration: none; border-radius: 4px;">Create Your First Template</a>
    114             </div>
    115         <?php endif; ?>
    116     </div>
    117 
    118     <!-- Stock Templates Tab -->
    119     <div id="stock-templates" class="tab-content" style="display: <?php echo $defaultTab === 'stock-templates' ? 'block' : 'none'; ?>;">
    120         <div style="margin-top: 20px; margin-bottom: 20px; border: 1px solid #007cba; background-color: #eef5fa; color: #007cba; padding: 15px; border-radius: 5px;">
    121             <strong>Click a card to create a template based on the example image. (Redirects to Open Graph.xyz). <br/><br/>When you're done, return here and refresh the page to start matching your variables.</strong>
     95                    </div>
     96                </form>
     97            <?php endforeach; ?>
    12298        </div>
    123         <?php if ( !empty($stockTemplates) ) : ?>
    124             <div class="template-grid" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(500px, 1fr)); gap: 20px;">
    125                 <?php foreach ( $stockTemplates as $edge ) :
    126                     $template       = $edge['node'];
    127                     $name           = $template['name'];
    128                     $id             = $template['id'];
    129                     $premium        = $template['isPremium'];
    130                     $organizationId = $template['organizationId'];
    131                     $version        = $template['activeVersion'];
    132                     $versionNumber  = $version['versionNumber'];
    133                    
    134                     // Generate image URL
    135                     $imageUrl = opengraphxyz_generate_image_url($id, $versionNumber, $version['data']['variables']);
    136                     ?>
    137                     <?php if ( $premium ) : ?>
    138                         <!-- Premium template -->
    139                         <a href="https://www.opengraph.xyz/get-started" target="_blank" class="template-card" style="text-decoration: none">
    140                     <?php else : ?>
    141                         <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" class="template-form" id="template-form-<?php echo esc_attr( $id ); ?>">
    142                             <?php wp_nonce_field( 'opengraph_xyz_select_template_action', 'opengraph_xyz_select_template_nonce' ); ?>
    143 
    144                             <input type="hidden" name="action" value="create_opengraph_template">
    145                             <input type="hidden" name="template_id" value="<?php echo esc_attr( $id ); ?>">
    146                             <input type="hidden" name="template_name" value="<?php echo esc_attr( $name ); ?>">
    147                             <input type="hidden" name="template_version" value="<?php echo esc_attr( $versionNumber ); ?>">
    148                     <?php endif; ?>
    149                         <div onclick="handleTemplateClick('<?php echo esc_attr( $id ); ?>', 'stock')" style="cursor: pointer; border-radius: 6px; overflow: hidden; box-shadow: 0 1px 1px -1px rgba(0,0,0,.1); border: 1px solid #dcdcde;">
    150                             <div class="template-card" style="position: relative; padding-top: 52.5%; background-color: #fff">
    151                                 <img src="<?php echo esc_url( $imageUrl ); ?>" alt="<?php echo esc_attr( $name ); ?>" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover;">
    152                             </div>
    153                             <div class="template-details" style="width: 100%; background: rgba(255,255,255,.65); color: #000; text-align: center; font-size: 16px;">
    154                                 <div style="padding: 1rem; display: flex; align-items: center; justify-content: center; gap: .5rem; border-top: 1px solid #dcdcde;">
    155                                     <?php echo esc_html( $name ); ?>
    156                                     <?php if ( isset( $premium ) ) : ?>
    157                                         <span style="font-size: .75rem; line-height: 1rem; padding: .25rem .5rem; border-radius: 9999px; background-color: #ffffcc; color: #854d0e; display: inline-flex; -moz-column-gap: .375rem; column-gap: 0.375rem; align-items: center;">
    158                                             <svg style="width: 1rem; height: 1rem; fill: #eab308;" width="24" height="24" fill="currentColor" viewBox="0 0 24 24">
    159                                                 <path d="M5 16L3 5L8.5 10L12 4L15.5 10L21 5L19 16H5M19 19C19 19.6 18.6 20 18 20H6C5.4 20 5 19.6 5 19V18H19V19Z"></path>
    160                                             </svg>
    161                                             Premium
    162                                         </span>
    163                                     <?php endif; ?>
    164                                 </div>
    165                             </div>
    166                         </div>
    167                     <?php if ( $premium ) : ?>
    168                         </a>
    169                     <?php else : ?>
    170                         </form>
    171                     <?php endif; ?>
    172                 <?php endforeach; ?>
    173             </div>
    174         <?php else : ?>
    175             <p>No stock templates available.</p>
    176         <?php endif; ?>
    177     </div>
     99    <?php elseif (!$hasApiKey): ?>
     100        <div style="text-align: center; padding: 40px; background: #f9f9f9; border-radius: 6px;">
     101            <p style="font-size: 1.2em; color: #666; margin-bottom: 20px;">Connect your Open Graph account with an API
     102                Key to see your custom templates.</p>
     103            <a href="<?php echo esc_url(admin_url('edit.php?post_type=opengraph_template&page=og-xyz-settings')); ?>"
     104                style="background: #0073aa; color: white; padding: 10px 20px; text-decoration: none; border-radius: 4px;">Add
     105                an API Key</a>
     106        </div>
     107    <?php else: ?>
     108        <div style="text-align: center; padding: 40px; background: #f9f9f9; border-radius: 6px;">
     109            <p style="font-size: 1.2em; color: #666; margin-bottom: 20px;">You don't have any custom templates yet.</p>
     110            <a href="<?php echo esc_url($create_template_url); ?>" target="_blank"
     111                style="background: #0073aa; color: white; padding: 10px 20px; text-decoration: none; border-radius: 4px;">Create
     112                Your First Template</a>
     113        </div>
     114    <?php endif; ?>
    178115</div>
    179116
    … …  
    182119
    183120<script>
    184 // Check if user has API key
    185 const hasApiKey = <?php echo $hasApiKey ? 'true' : 'false'; ?>;
     121    // Check if user has API key
     122    const hasApiKey = <?php echo $hasApiKey ? 'true' : 'false'; ?>;
    186123
    187 // Get the create template base URL from PHP
    188 const createTemplateBaseUrl = '<?php echo esc_js($create_template_base_url); ?>';
     124    // Debug: Log template data
     125    <?php if (isset($templates['edges']) && is_array($templates['edges'])): ?>
     126        console.log('Template data:', <?php echo json_encode($templates['edges']); ?>);
     127    <?php endif; ?>
    189128
    190 // Debug: Log template data
    191 <?php if ( isset( $templates['edges'] ) && is_array( $templates['edges'] ) ) : ?>
    192 console.log('Template data:', <?php echo json_encode($templates['edges']); ?>);
    193 <?php endif; ?>
     129    // Handle template click - check for API key first
     130    function handleTemplateClick(templateId) {
     131        if (!hasApiKey) {
     132            // Show API key modal if no API key
     133            showApiKeyModal();
     134            return;
     135        }
    194136
    195 // Tab functionality
    196 document.addEventListener('DOMContentLoaded', function() {
    197     const tabButtons = document.querySelectorAll('.tab-button');
    198     const tabContents = document.querySelectorAll('.tab-content');
    199 
    200     tabButtons.forEach(button => {
    201         button.addEventListener('click', function() {
    202             const targetTab = this.getAttribute('data-tab');
    203            
    204             // Update button styles
    205             tabButtons.forEach(btn => {
    206                 btn.style.background = '#f9f9f9';
    207                 btn.style.color = '#646970';
    208                 btn.classList.remove('active');
    209             });
    210             this.style.background = '#fff';
    211             this.style.color = '#1d2327';
    212             this.classList.add('active');
    213            
    214             // Show/hide tab content
    215             tabContents.forEach(content => {
    216                 content.style.display = 'none';
    217             });
    218             document.getElementById(targetTab).style.display = 'block';
    219         });
    220     });
    221 });
    222 
    223 // Handle template click - check for API key first
    224 function handleTemplateClick(templateId, templateType) {
    225     if (!hasApiKey) {
    226         // Show API key modal if no API key
    227         showApiKeyModal();
    228         return;
    229     }
    230    
    231     if (templateType === 'user') {
    232         // This is a user template - submit the form
    233137        var formId = "template-form-" + templateId;
    234138        const form = document.getElementById(formId);
    … …  
    238142            form.submit();
    239143        }
    240     } else {
    241         // This is a stock template - use the existing behavior
    242         submitTemplateForm(templateId);
    243144    }
    244 }
    245 
    246 // Prevent multiple template creations when choosing a template
    247 function submitTemplateForm(templateId) {
    248     const createTemplateUrl = createTemplateBaseUrl + templateId;
    249     console.log(createTemplateUrl);
    250     window.open(createTemplateUrl, '_blank');
    251 }
    252145</script>
  • opengraph-xyz/trunk/src/ui/api-key-modal.php

    r3342214 r3616586  
    11<?php
    22// Exit if accessed directly.
    3 defined( 'ABSPATH' ) || exit;
     3defined('ABSPATH') || exit;
    44
    5 // Get the settings URL using the helper function
    6 $settings_url = opengraphxyz_get_settings_url();
     5$settings_url = opengraphxyz_get_base_url() . '/settings/api-keys';
    76?>
    87
    9 <div id="api-key-modal" class="api-key-modal" style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.5); z-index: 9999; align-items: center; justify-content: center;">
    10     <div class="modal-content" style="background: white; padding: 2rem; border-radius: 8px; max-width: 500px; width: 90%; text-align: center; box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);">
     8<div id="api-key-modal" class="api-key-modal"
     9    style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.5); z-index: 9999; align-items: center; justify-content: center;">
     10    <div class="modal-content"
     11        style="background: white; padding: 2rem; border-radius: 8px; max-width: 500px; width: 90%; text-align: center; box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);">
    1112        <div style="margin-bottom: 1rem;">
    12             <img src="<?php echo esc_url(plugin_dir_url(__FILE__) . '../../assets/icon-128x128.png'); ?>" alt="OpenGraph Logo" style="width: 3rem; height: 3rem; margin: 0 auto 1rem; display: block;">
     13            <img src="<?php echo esc_url(plugin_dir_url(__FILE__) . '../../assets/icon-128x128.png'); ?>"
     14                alt="OpenGraph Logo" style="width: 3rem; height: 3rem; margin: 0 auto 1rem; display: block;">
    1315        </div>
    14        
     16
    1517        <div class="modal-header" style="margin-bottom: 1rem;">
    1618            <h2 style="margin: 0; color: #333; font-size: 1.5rem;">API Key Required</h2>
    1719        </div>
    18        
     20
    1921        <div class="modal-body" style="margin-bottom: 2rem;">
    2022            <p style="margin: 0; color: #666; font-size: 1.1rem; line-height: 1.5;">
    … …  
    2224            </p>
    2325        </div>
    24        
     26
    2527        <div class="modal-footer" style="display: flex; gap: 1rem; justify-content: center;">
    26             <button type="button" class="button button-secondary" onclick="closeApiKeyModal()" style="padding: 0.5rem 1rem; border: 1px solid #ddd; background: #f9f9f9; border-radius: 4px; cursor: pointer;">
     28            <button type="button" class="button button-secondary" onclick="closeApiKeyModal()"
     29                style="padding: 0.5rem 1rem; border: 1px solid #ddd; background: #f9f9f9; border-radius: 4px; cursor: pointer;">
    2730                Cancel
    2831            </button>
    29             <a id="register-link" href="<?php echo esc_url($settings_url); ?>" target="_blank" class="button button-primary" style="padding: 0.5rem 1rem; background: #0073aa; color: white; text-decoration: none; border-radius: 4px; display: inline-block;">
     32            <a id="register-link" href="<?php echo esc_url($settings_url); ?>" target="_blank"
     33                class="button button-primary"
     34                style="padding: 0.5rem 1rem; background: #0073aa; color: white; text-decoration: none; border-radius: 4px; display: inline-block;">
    3035                Get API Key
    3136            </a>
    … …  
    3540
    3641<script>
    37 function showApiKeyModal() {
    38     const modal = document.getElementById('api-key-modal');
    39     modal.style.display = 'flex';
    40 }
     42    function showApiKeyModal() {
     43        const modal = document.getElementById('api-key-modal');
     44        modal.style.display = 'flex';
     45    }
    4146
    42 function closeApiKeyModal() {
    43     const modal = document.getElementById('api-key-modal');
    44     modal.style.display = 'none';
    45 }
     47    function closeApiKeyModal() {
     48        const modal = document.getElementById('api-key-modal');
     49        modal.style.display = 'none';
     50    }
    4651
    47 // Close modal when clicking outside
    48 document.addEventListener('DOMContentLoaded', function() {
    49     const modal = document.getElementById('api-key-modal');
    50     modal.addEventListener('click', function(e) {
    51         if (e.target === modal) {
    52             closeApiKeyModal();
    53         }
     52    // Close modal when clicking outside
     53    document.addEventListener('DOMContentLoaded', function () {
     54        const modal = document.getElementById('api-key-modal');
     55        modal.addEventListener('click', function (e) {
     56            if (e.target === modal) {
     57                closeApiKeyModal();
     58            }
     59        });
    5460    });
    55 });
    56 </script>
     61</script>
  • opengraph-xyz/trunk/src/views/modifications.php

    r3487287 r3616586  
    99$custom_fields = empty($opengraphxyz['custom_fields']) ? array() : $opengraphxyz['custom_fields'];
    1010$dynamic_tags = wp_list_pluck(opengraphxyz_init()->get_tags(), 'description');
     11$variable_mapping_docs_url = opengraphxyz_get_wordpress_docs_url('variable-mapping');
    1112
    1213wp_nonce_field('opengraph-xyz', 'opengraph-xyz-nonce');
    … …  
    3940</style>
    4041
     42<div class="notice notice-info inline" style="margin: 0 0 20px;">
     43  <p>
     44    <strong><?php esc_html_e('Choose which WordPress content should appear in your Open Graph image.', 'opengraph-xyz'); ?></strong>
     45  </p>
     46  <p>
     47    <?php esc_html_e('First, select the template version you want to use. Then use the dropdowns below to connect the template\'s text and images to details from each WordPress post, such as its title, excerpt, or featured image. Choose Default to keep the text or image already saved in your OpenGraph.xyz template.', 'opengraph-xyz'); ?>
     48    <a href="<?php echo esc_url($variable_mapping_docs_url); ?>" target="_blank" rel="noopener noreferrer"><?php esc_html_e('Learn about variable mapping', 'opengraph-xyz'); ?></a>.
     49  </p>
     50</div>
     51
    4152<?php if (!empty($thumbnailUrl)): ?>
    4253<div style="margin-bottom: 20px; padding: 15px; background: #f9f9f9; border: 1px solid #ddd; border-radius: 4px;">
    … …  
    7081            <select name="opengraph[modifications][<?php echo esc_attr($variable['id']); ?>][<?php echo esc_attr($modification['property']); ?>]" id="opengraph-modification-<?php echo esc_attr($variable['id']); ?>__<?php echo esc_attr($modification['property']); ?>" class="regular-text">
    7182              <?php
    72               $current_value = isset($current_modifications[$variable['id']][$modification['property']]) ? $current_modifications[$variable['id']][$modification['property']] : '';
     83              $has_saved_mapping = isset($current_modifications[$variable['id']]) && array_key_exists($modification['property'], $current_modifications[$variable['id']]);
     84              $current_value = $has_saved_mapping ? $current_modifications[$variable['id']][$modification['property']] : opengraphxyz_get_suggested_dynamic_tag($variable, $modification['property']);
    7385              $custom_field = isset($custom_fields[$variable['id']][$modification['property']]) ? $custom_fields[$variable['id']][$modification['property']] : '';
    7486              ?>
    75               <option value="_" <?php selected($current_value, ''); ?>><?php esc_html_e('Default', 'opengraph-xyz'); ?></option>
     87              <option value="_" <?php selected($current_value, '_'); ?>><?php esc_html_e('Default', 'opengraph-xyz'); ?></option>
    7688              <?php foreach ($dynamic_tags as $dynamic_tag => $description): ?>
    7789                                <option value="{<?php echo esc_attr($dynamic_tag); ?>}" <?php selected($current_value, '{' . $dynamic_tag . '}'); ?>>
    … …  
    309321
    310322                // Add default option
    311                 var defaultOption = $('<option></option>').attr({value: ''}).text('Default');
     323                var defaultOption = $('<option></option>').attr({value: '_'}).text('Default');
    312324                select.append(defaultOption);
    313325
    … …  
    353365                  select.val(currentSelections[selectId]);
    354366                  toggleCustomFieldInput(select);
    355                 } else {
     367                } else if (modification.suggestedDynamicTag) {
     368                  select.val(modification.suggestedDynamicTag);
    356369                }
    357370
Note: See TracChangeset for help on using the changeset viewer.