WP
WordPress Integration
Add beautiful calligraphy to your WordPress site
CMS PlatformPHP & JavaScriptPlugin Ready
Quick Start
1. Custom Plugin Structure
text
Click to copy
calligraphy-api/
├── calligraphy-api.php # Main plugin file
├── includes/
│ ├── class-calligraphy-api.php # Core API class
│ ├── class-shortcodes.php # Shortcode handlers
│ └── class-admin.php # Admin interface
├── assets/
│ ├── css/
│ │ └── calligraphy-styles.css
│ └── js/
│ └── calligraphy-frontend.js
└── templates/
└── calligraphy-generator.php2. Main Plugin File
php
Click to copy
<?php
/**
* Plugin Name: Calligraphy API Integration
* Description: Integrate beautiful calligraphy generation into your WordPress site
* Version: 1.0.0
* Author: Your Name
* Text Domain: calligraphy-api
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
// Define plugin constants
define('CALLIGRAPHY_API_VERSION', '1.0.0');
define('CALLIGRAPHY_API_PLUGIN_URL', plugin_dir_url(__FILE__));
define('CALLIGRAPHY_API_PLUGIN_PATH', plugin_dir_path(__FILE__));
// Include required files
require_once CALLIGRAPHY_API_PLUGIN_PATH . 'includes/class-calligraphy-api.php';
require_once CALLIGRAPHY_API_PLUGIN_PATH . 'includes/class-shortcodes.php';
require_once CALLIGRAPHY_API_PLUGIN_PATH . 'includes/class-admin.php';
// Initialize the plugin
function calligraphy_api_init() {
$calligraphy_api = new Calligraphy_API();
$calligraphy_shortcodes = new Calligraphy_Shortcodes();
if (is_admin()) {
$calligraphy_admin = new Calligraphy_Admin();
}
}
add_action('plugins_loaded', 'calligraphy_api_init');
// Activation hook
register_activation_hook(__FILE__, 'calligraphy_api_activate');
function calligraphy_api_activate() {
// Create database table for storing generations if needed
global $wpdb;
$table_name = $wpdb->prefix . 'calligraphy_generations';
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
user_id bigint(20) NOT NULL,
text text NOT NULL,
language varchar(50) NOT NULL,
font_style varchar(100) NOT NULL,
image_url varchar(255) NOT NULL,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}
// Enqueue scripts and styles
function calligraphy_api_enqueue_scripts() {
wp_enqueue_style(
'calligraphy-api-styles',
CALLIGRAPHY_API_PLUGIN_URL . 'assets/css/calligraphy-styles.css',
array(),
CALLIGRAPHY_API_VERSION
);
wp_enqueue_script(
'calligraphy-api-frontend',
CALLIGRAPHY_API_PLUGIN_URL . 'assets/js/calligraphy-frontend.js',
array('jquery'),
CALLIGRAPHY_API_VERSION,
true
);
// Localize script for AJAX
wp_localize_script('calligraphy-api-frontend', 'calligraphy_ajax', array(
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('calligraphy_nonce')
));
}
add_action('wp_enqueue_scripts', 'calligraphy_api_enqueue_scripts');Core API Integration
API Handler Class
php
Click to copy
<?php
// includes/class-calligraphy-api.php
class Calligraphy_API {
private $api_base_url = 'https://api.calligraphymaker.com/api/v2';
private $api_key;
public function __construct() {
$this->api_key = get_option('calligraphy_api_key', '');
// Register AJAX handlers
add_action('wp_ajax_generate_calligraphy', array($this, 'handle_generate_request'));
add_action('wp_ajax_nopriv_generate_calligraphy', array($this, 'handle_generate_request'));
add_action('wp_ajax_download_svg', array($this, 'handle_download_svg'));
add_action('wp_ajax_nopriv_download_svg', array($this, 'handle_download_svg'));
}
/**
* Generate calligraphy via API
*/
public function generate_calligraphy($text, $language = 'hindi', $font_style = 'calligraphy', $count = 1) {
if (empty($this->api_key)) {
return new WP_Error('no_api_key', 'API key not configured');
}
$request_data = array(
'text' => sanitize_text_field($text),
'language' => sanitize_text_field($language),
'fontStyle' => sanitize_text_field($font_style),
'count' => intval($count),
'imageFormat' => 'png'
);
$response = wp_remote_post($this->api_base_url . '/generate', array(
'headers' => array(
'Content-Type' => 'application/json',
'x-api-key' => $this->api_key
),
'body' => json_encode($request_data),
'timeout' => 30
));
if (is_wp_error($response)) {
return $response;
}
$body = wp_remote_retrieve_body($response);
$data = json_decode($body, true);
$status_code = wp_remote_retrieve_response_code($response);
if ($status_code !== 200) {
return new WP_Error('api_error', $data['error'] ?? 'API request failed');
}
if ($data['success'] && !empty($data['data']['results'])) {
// Optionally save to database
$this->save_generation_to_db($text, $language, $font_style, $data['data']['results']);
return $data['data']['results'];
}
return new WP_Error('no_results', 'No calligraphy results generated');
}
/**
* Download SVG format
*/
public function download_svg($result_text, $font_name) {
if (empty($this->api_key)) {
return new WP_Error('no_api_key', 'API key not configured');
}
$request_data = array(
'resultText' => sanitize_text_field($result_text),
'fontName' => sanitize_text_field($font_name)
);
$response = wp_remote_post($this->api_base_url . '/download-svg', array(
'headers' => array(
'Content-Type' => 'application/json',
'x-api-key' => $this->api_key
),
'body' => json_encode($request_data),
'timeout' => 30
));
if (is_wp_error($response)) {
return $response;
}
$body = wp_remote_retrieve_body($response);
$data = json_decode($body, true);
$status_code = wp_remote_retrieve_response_code($response);
if ($status_code !== 200) {
return new WP_Error('api_error', $data['error'] ?? 'SVG download failed');
}
return $data;
}
/**
* Handle AJAX generate request
*/
public function handle_generate_request() {
// Verify nonce
if (!wp_verify_nonce($_POST['nonce'], 'calligraphy_nonce')) {
wp_die('Security check failed');
}
$text = $_POST['text'] ?? '';
$language = $_POST['language'] ?? 'hindi';
$font_style = $_POST['font_style'] ?? 'calligraphy';
$count = intval($_POST['count'] ?? 1);
if (empty($text)) {
wp_send_json_error('Text is required');
}
$results = $this->generate_calligraphy($text, $language, $font_style, $count);
if (is_wp_error($results)) {
wp_send_json_error($results->get_error_message());
}
wp_send_json_success($results);
}
/**
* Handle AJAX SVG download request
*/
public function handle_download_svg() {
// Verify nonce
if (!wp_verify_nonce($_POST['nonce'], 'calligraphy_nonce')) {
wp_die('Security check failed');
}
$result_text = $_POST['result_text'] ?? '';
$font_name = $_POST['font_name'] ?? '';
if (empty($result_text) || empty($font_name)) {
wp_send_json_error('Result text and font name are required');
}
$svg_data = $this->download_svg($result_text, $font_name);
if (is_wp_error($svg_data)) {
wp_send_json_error($svg_data->get_error_message());
}
wp_send_json_success($svg_data);
}
/**
* Save generation to database
*/
private function save_generation_to_db($text, $language, $font_style, $results) {
global $wpdb;
$table_name = $wpdb->prefix . 'calligraphy_generations';
$user_id = get_current_user_id();
foreach ($results as $result) {
$wpdb->insert(
$table_name,
array(
'user_id' => $user_id,
'text' => $text,
'language' => $language,
'font_style' => $font_style,
'image_url' => $result['cdnUrl']
),
array('%d', '%s', '%s', '%s', '%s')
);
}
}
}Shortcodes & Frontend
Shortcode Handler
php
Click to copy
<?php
// includes/class-shortcodes.php
class Calligraphy_Shortcodes {
public function __construct() {
add_shortcode('calligraphy_generator', array($this, 'generator_shortcode'));
add_shortcode('calligraphy_display', array($this, 'display_shortcode'));
}
/**
* Generator shortcode: [calligraphy_generator]
*/
public function generator_shortcode($atts) {
$atts = shortcode_atts(array(
'language' => 'hindi',
'font_style' => 'calligraphy',
'count' => '1',
'width' => '100%',
'height' => '400px'
), $atts);
ob_start();
include CALLIGRAPHY_API_PLUGIN_PATH . 'templates/calligraphy-generator.php';
return ob_get_clean();
}
/**
* Display shortcode: [calligraphy_display text="नमस्ते"]
*/
public function display_shortcode($atts) {
$atts = shortcode_atts(array(
'text' => '',
'language' => 'hindi',
'font_style' => 'calligraphy',
'width' => '300px',
'height' => '150px'
), $atts);
if (empty($atts['text'])) {
return '<p>Error: Text attribute is required for calligraphy display.</p>';
}
// Generate unique ID for caching
$cache_key = 'calligraphy_' . md5($atts['text'] . $atts['language'] . $atts['font_style']);
$cached_result = get_transient($cache_key);
if ($cached_result) {
$image_url = $cached_result;
} else {
$api = new Calligraphy_API();
$results = $api->generate_calligraphy($atts['text'], $atts['language'], $atts['font_style'], 1);
if (is_wp_error($results)) {
return '<p>Error: ' . $results->get_error_message() . '</p>';
}
if (empty($results)) {
return '<p>Error: No calligraphy generated.</p>';
}
$image_url = $results[0]['cdnUrl'];
// Cache for 1 hour
set_transient($cache_key, $image_url, HOUR_IN_SECONDS);
}
return sprintf(
'<div class="calligraphy-display" style="width: %s; height: %s;">
<img src="%s" alt="%s" style="max-width: 100%%; height: auto;" />
</div>',
esc_attr($atts['width']),
esc_attr($atts['height']),
esc_url($image_url),
esc_attr($atts['text'])
);
}
}Frontend Template
php
Click to copy
<?php
// templates/calligraphy-generator.php
?>
<div class="calligraphy-generator-container" style="width: <?php echo esc_attr($atts['width']); ?>; height: <?php echo esc_attr($atts['height']); ?>;">
<div class="calligraphy-form">
<div class="form-group">
<label for="calligraphy-text">Enter Text:</label>
<textarea
id="calligraphy-text"
placeholder="Enter text to convert to calligraphy..."
rows="3"
>नमस्ते दुनिया</textarea>
</div>
<div class="form-row">
<div class="form-group">
<label for="calligraphy-language">Language:</label>
<select id="calligraphy-language">
<option value="hindi" <?php selected($atts['language'], 'hindi'); ?>>Hindi</option>
<option value="english" <?php selected($atts['language'], 'english'); ?>>English</option>
<option value="marathi" <?php selected($atts['language'], 'marathi'); ?>>Marathi</option>
<option value="gujarati" <?php selected($atts['language'], 'gujarati'); ?>>Gujarati</option>
</select>
</div>
<div class="form-group">
<label for="calligraphy-style">Font Style:</label>
<select id="calligraphy-style">
<option value="calligraphy" <?php selected($atts['font_style'], 'calligraphy'); ?>>Calligraphy</option>
<option value="modern" <?php selected($atts['font_style'], 'modern'); ?>>Modern</option>
<option value="traditional" <?php selected($atts['font_style'], 'traditional'); ?>>Traditional</option>
</select>
</div>
</div>
<div class="form-actions">
<button type="button" id="generate-calligraphy" class="btn btn-primary">
<span class="btn-text">Generate Calligraphy</span>
<span class="btn-loading" style="display: none;">Generating...</span>
</button>
</div>
</div>
<div class="calligraphy-results" id="calligraphy-results" style="display: none;">
<h4>Generated Calligraphy:</h4>
<div class="results-grid" id="results-grid"></div>
<div class="results-actions">
<button type="button" id="download-svg" class="btn btn-secondary" style="display: none;">
Download SVG
</button>
</div>
</div>
<div class="calligraphy-error" id="calligraphy-error" style="display: none;">
<div class="error-message"></div>
</div>
</div>Frontend JavaScript
javascript
Click to copy
// assets/js/calligraphy-frontend.js
jQuery(document).ready(function($) {
let currentResults = [];
// Generate calligraphy
$('#generate-calligraphy').on('click', function() {
const text = $('#calligraphy-text').val().trim();
const language = $('#calligraphy-language').val();
const fontStyle = $('#calligraphy-style').val();
if (!text) {
showError('Please enter some text to generate calligraphy.');
return;
}
showLoading(true);
hideError();
hideResults();
$.ajax({
url: calligraphy_ajax.ajax_url,
type: 'POST',
data: {
action: 'generate_calligraphy',
text: text,
language: language,
font_style: fontStyle,
count: 3,
nonce: calligraphy_ajax.nonce
},
success: function(response) {
showLoading(false);
if (response.success) {
currentResults = response.data;
displayResults(response.data);
} else {
showError(response.data || 'Failed to generate calligraphy.');
}
},
error: function() {
showLoading(false);
showError('Network error occurred. Please try again.');
}
});
});
// Download SVG
$('#download-svg').on('click', function() {
if (currentResults.length === 0) {
showError('No results to download.');
return;
}
const firstResult = currentResults[0];
$.ajax({
url: calligraphy_ajax.ajax_url,
type: 'POST',
data: {
action: 'download_svg',
result_text: firstResult.resultText,
font_name: firstResult.fontName,
nonce: calligraphy_ajax.nonce
},
success: function(response) {
if (response.success && response.data.svgContent) {
// Create download link
const blob = new Blob([response.data.svgContent], { type: 'image/svg+xml' });
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'calligraphy.svg';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
} else {
showError(response.data || 'Failed to download SVG.');
}
},
error: function() {
showError('Network error occurred while downloading.');
}
});
});
// Helper functions
function showLoading(show) {
const btn = $('#generate-calligraphy');
if (show) {
btn.prop('disabled', true);
btn.find('.btn-text').hide();
btn.find('.btn-loading').show();
} else {
btn.prop('disabled', false);
btn.find('.btn-text').show();
btn.find('.btn-loading').hide();
}
}
function displayResults(results) {
const grid = $('#results-grid');
grid.empty();
results.forEach(function(result, index) {
const resultItem = $(`
<div class="result-item">
<img src="${result.cdnUrl}" alt="Calligraphy result ${index + 1}" />
<div class="result-info">
<p><strong>Font:</strong> ${result.fontName}</p>
<p><strong>Text:</strong> ${result.resultText}</p>
</div>
</div>
`);
grid.append(resultItem);
});
$('#calligraphy-results').show();
$('#download-svg').show();
}
function showError(message) {
$('#calligraphy-error .error-message').text(message);
$('#calligraphy-error').show();
}
function hideError() {
$('#calligraphy-error').hide();
}
function hideResults() {
$('#calligraphy-results').hide();
$('#download-svg').hide();
}
});Admin Panel & Usage
Admin Settings Page
php
Click to copy
<?php
// includes/class-admin.php
class Calligraphy_Admin {
public function __construct() {
add_action('admin_menu', array($this, 'add_admin_menu'));
add_action('admin_init', array($this, 'init_settings'));
}
public function add_admin_menu() {
add_options_page(
'Calligraphy API Settings',
'Calligraphy API',
'manage_options',
'calligraphy-api-settings',
array($this, 'settings_page')
);
}
public function init_settings() {
register_setting('calligraphy_api_settings', 'calligraphy_api_key');
add_settings_section(
'calligraphy_api_main',
'API Configuration',
array($this, 'main_section_callback'),
'calligraphy-api-settings'
);
add_settings_field(
'calligraphy_api_key',
'API Key',
array($this, 'api_key_callback'),
'calligraphy-api-settings',
'calligraphy_api_main'
);
}
public function main_section_callback() {
echo '<p>Configure your Calligraphy API settings below.</p>';
}
public function api_key_callback() {
$api_key = get_option('calligraphy_api_key', '');
echo '<input type="text" id="calligraphy_api_key" name="calligraphy_api_key" value="' . esc_attr($api_key) . '" class="regular-text" />';
echo '<p class="description">Enter your Calligraphy API key. <a href="https://api.calligraphymaker.com/auth/signin" target="_blank">Get your API key here</a></p>';
}
public function settings_page() {
?>
<div class="wrap">
<h1>Calligraphy API Settings</h1>
<div class="notice notice-info">
<p><strong>Shortcodes Available:</strong></p>
<ul>
<li><code>[calligraphy_generator]</code> - Interactive calligraphy generator</li>
<li><code>[calligraphy_display text="Your Text" language="hindi"]</code> - Display pre-generated calligraphy</li>
</ul>
</div>
<form method="post" action="options.php">
<?php
settings_fields('calligraphy_api_settings');
do_settings_sections('calligraphy-api-settings');
submit_button();
?>
</form>
<div class="card">
<h2>Usage Examples</h2>
<h3>In Posts/Pages:</h3>
<pre><code>[calligraphy_generator language="hindi" font_style="calligraphy"]</code></pre>
<h3>In Theme Files:</h3>
<pre><code><?php echo do_shortcode('[calligraphy_display text="नमस्ते" language="hindi"]'); ?></code></pre>
<h3>Block Editor:</h3>
<p>Add a "Shortcode" block and use the shortcodes above.</p>
</div>
</div>
<?php
}
}CSS Styles
css
Click to copy
/* assets/css/calligraphy-styles.css */
.calligraphy-generator-container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
background: #f9f9f9;
border-radius: 8px;
border: 1px solid #e1e1e1;
}
.calligraphy-form {
margin-bottom: 30px;
}
.form-group {
margin-bottom: 15px;
}
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: 600;
color: #333;
}
.form-group textarea,
.form-group select {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
}
.form-row {
display: flex;
gap: 15px;
}
.form-row .form-group {
flex: 1;
}
.form-actions {
margin-top: 20px;
}
.btn {
display: inline-block;
padding: 12px 24px;
background: #0073aa;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
text-decoration: none;
transition: background-color 0.3s;
}
.btn:hover {
background: #005a87;
}
.btn:disabled {
background: #ccc;
cursor: not-allowed;
}
.btn-secondary {
background: #666;
}
.btn-secondary:hover {
background: #555;
}
.calligraphy-results {
margin-top: 30px;
padding: 20px;
background: white;
border-radius: 8px;
border: 1px solid #e1e1e1;
}
.results-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
margin: 20px 0;
}
.result-item {
text-align: center;
padding: 15px;
background: #f9f9f9;
border-radius: 8px;
border: 1px solid #e1e1e1;
}
.result-item img {
max-width: 100%;
height: auto;
border-radius: 4px;
margin-bottom: 10px;
}
.result-info p {
margin: 5px 0;
font-size: 12px;
color: #666;
}
.calligraphy-error {
margin-top: 20px;
padding: 15px;
background: #fff2f2;
border: 1px solid #f5c6cb;
border-radius: 4px;
color: #721c24;
}
.calligraphy-display {
text-align: center;
margin: 20px 0;
}
.calligraphy-display img {
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
@media (max-width: 768px) {
.form-row {
flex-direction: column;
}
.results-grid {
grid-template-columns: 1fr;
}
}What You'll Build
WordPress Plugin
Complete plugin with admin settings
Shortcode Support
Easy integration in posts and pages
AJAX Integration
Smooth user experience without page reloads
Caching System
Optimized performance with transients
Requirements
WordPress 5.0+
PHP 7.4+
API Key from Calligraphy API
Basic WordPress development knowledge