Add files via upload
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
# Vincent's Shortner
|
||||
|
||||
A simple URL shortener plugin for WordPress with usage statistics.
|
||||
|
||||
## Description
|
||||
|
||||
Vincent's Shortner is a lightweight WordPress plugin that allows you to create and manage short URLs directly from your WordPress admin panel. It includes features like custom short codes, usage tracking, and a frontend shortcode for public use.
|
||||
|
||||
## Features
|
||||
|
||||
- Create short URLs with custom or auto-generated short codes
|
||||
- Track usage statistics (number of clicks) for each short URL
|
||||
- Admin panel interface for managing short URLs
|
||||
- Frontend shortcode for public URL shortening
|
||||
- Checks for URL conflicts with existing WordPress permalinks
|
||||
- Easy copying of short URLs to clipboard
|
||||
- Responsive design with Bootstrap integration for the frontend
|
||||
|
||||
## Installation
|
||||
|
||||
1. Upload the `vincents-shortner` folder to the `/wp-content/plugins/` directory
|
||||
2. Activate the plugin through the 'Plugins' menu in WordPress
|
||||
3. Access the plugin via the 'Vincent's Shortner' menu item in the WordPress admin panel
|
||||
|
||||
## Usage
|
||||
|
||||
### Admin Panel
|
||||
|
||||
1. Navigate to the 'Vincent's Shortner' menu item in your WordPress admin panel
|
||||
2. Enter a long URL and an optional custom short code
|
||||
3. Click 'Create Short URL' to generate a new short URL
|
||||
4. Manage existing short URLs using the table below the form
|
||||
|
||||
### Frontend Shortcode
|
||||
|
||||
Use the `[vincent-short]` shortcode in any post or page to display the URL shortener form and table on the frontend.
|
||||
|
||||
## Database
|
||||
|
||||
The plugin creates a custom table in your WordPress database to store short URL data:
|
||||
|
||||
- `id`: Unique identifier for each entry
|
||||
- `long_url`: The original long URL
|
||||
- `short_code`: The generated or custom short code
|
||||
- `created_at`: Timestamp of when the short URL was created
|
||||
- `usage_count`: Number of times the short URL has been accessed
|
||||
|
||||
## Author
|
||||
|
||||
Vincent Rozenberg
|
||||
- Website: [https://vincentrozenberg.com](https://vincentrozenberg.com)
|
||||
|
||||
## Version
|
||||
|
||||
1.5
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the MIT License.
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome. Please feel free to submit a Pull Request.
|
||||
|
||||
@@ -0,0 +1,260 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin Name: Vincent's Shortner
|
||||
* Description: A simple URL shortener plugin with usage statistics
|
||||
* Version: 1.5
|
||||
* Author: Vincent Rozenberg
|
||||
* Author URI: https://vincentrozenberg.com
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Create or update the database table
|
||||
function vincent_shortner_install_or_upgrade() {
|
||||
global $wpdb;
|
||||
$table_name = $wpdb->prefix . 'vincent_shortner';
|
||||
$charset_collate = $wpdb->get_charset_collate();
|
||||
|
||||
$sql = "CREATE TABLE $table_name (
|
||||
id mediumint(9) NOT NULL AUTO_INCREMENT,
|
||||
long_url text NOT NULL,
|
||||
short_code varchar(10) NOT NULL,
|
||||
created_at datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
usage_count int DEFAULT 0 NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY short_code (short_code)
|
||||
) $charset_collate;";
|
||||
|
||||
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
|
||||
dbDelta($sql);
|
||||
|
||||
// Check if usage_count column exists, if not, add it
|
||||
$row = $wpdb->get_results("SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '" . DB_NAME . "' AND TABLE_NAME = '$table_name' AND COLUMN_NAME = 'usage_count'");
|
||||
if (empty($row)) {
|
||||
$wpdb->query("ALTER TABLE $table_name ADD usage_count int DEFAULT 0 NOT NULL");
|
||||
}
|
||||
}
|
||||
register_activation_hook(__FILE__, 'vincent_shortner_install_or_upgrade');
|
||||
add_action('plugins_loaded', 'vincent_shortner_install_or_upgrade');
|
||||
|
||||
// Add menu item to the admin panel
|
||||
function vincent_shortner_menu() {
|
||||
add_menu_page('Vincent Shortner', 'Vincent Shortner', 'manage_options', 'vincent-shortner', 'vincent_shortner_page', 'dashicons-admin-links');
|
||||
}
|
||||
add_action('admin_menu', 'vincent_shortner_menu');
|
||||
|
||||
// Check if URL already exists or conflicts with WordPress permalinks
|
||||
function vincent_shortner_url_exists($long_url, $short_code) {
|
||||
global $wpdb;
|
||||
$table_name = $wpdb->prefix . 'vincent_shortner';
|
||||
|
||||
// Check if the long URL already exists
|
||||
$existing_url = $wpdb->get_var($wpdb->prepare("SELECT id FROM $table_name WHERE long_url = %s", $long_url));
|
||||
if ($existing_url) {
|
||||
return 'The long URL already exists in the system.';
|
||||
}
|
||||
|
||||
// Check if the short code conflicts with WordPress permalinks
|
||||
$page = get_page_by_path($short_code);
|
||||
if ($page) {
|
||||
return 'The short code conflicts with an existing url.';
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Admin page content
|
||||
function vincent_shortner_page() {
|
||||
global $wpdb;
|
||||
$table_name = $wpdb->prefix . 'vincent_shortner';
|
||||
$message = '';
|
||||
|
||||
// Handle form submission
|
||||
if (isset($_POST['vincent_shortner_submit'])) {
|
||||
$long_url = esc_url_raw($_POST['long_url']);
|
||||
$short_code = sanitize_text_field($_POST['short_code']);
|
||||
|
||||
if (empty($short_code)) {
|
||||
$short_code = substr(md5(uniqid()), 0, 6);
|
||||
}
|
||||
|
||||
$url_exists = vincent_shortner_url_exists($long_url, $short_code);
|
||||
if ($url_exists) {
|
||||
$message = '<div class="error"><p>' . $url_exists . '</p></div>';
|
||||
} else {
|
||||
$wpdb->insert(
|
||||
$table_name,
|
||||
array(
|
||||
'long_url' => $long_url,
|
||||
'short_code' => $short_code,
|
||||
'usage_count' => 0
|
||||
)
|
||||
);
|
||||
$message = '<div class="updated"><p>Short URL created successfully.</p></div>';
|
||||
}
|
||||
}
|
||||
|
||||
// Handle delete action
|
||||
if (isset($_GET['action']) && $_GET['action'] == 'delete' && isset($_GET['id'])) {
|
||||
$id = intval($_GET['id']);
|
||||
$wpdb->delete($table_name, array('id' => $id));
|
||||
$message = '<div class="updated"><p>Short URL deleted successfully.</p></div>';
|
||||
}
|
||||
|
||||
// Fetch all short URLs
|
||||
$short_urls = $wpdb->get_results("SELECT * FROM $table_name ORDER BY created_at DESC");
|
||||
|
||||
// Display the admin page
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h3>Vincent Shortner</h3>
|
||||
<?php echo $message; ?>
|
||||
<form method="post" action="">
|
||||
<table class="form-table">
|
||||
<tr>
|
||||
<th><label for="long_url">Long URL</label></th>
|
||||
<td><input type="url" name="long_url" id="long_url" class="regular-text" required></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><label for="short_code">Short Code (optional)</label></th>
|
||||
<td><input type="text" name="short_code" id="short_code" class="regular-text"></td>
|
||||
</tr>
|
||||
</table>
|
||||
<p class="submit">
|
||||
<input type="submit" name="vincent_shortner_submit" value="Create Short URL">
|
||||
</p>
|
||||
</form>
|
||||
|
||||
<h3>Existing Short URLs</h3>
|
||||
<table class="wp-list-table widefat fixed striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Long</th>
|
||||
<th>Short</th>
|
||||
<th>Date</th>
|
||||
<th>Clicks</th>
|
||||
<th>Copy</th>
|
||||
<th>Delete</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($short_urls as $url): ?>
|
||||
<tr>
|
||||
<td style="max-width: 300px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
|
||||
<?php echo esc_url($url->long_url); ?>
|
||||
</td>
|
||||
<td style="max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
|
||||
<?php
|
||||
$short_url = home_url('/' . $url->short_code);
|
||||
echo '<a href="' . esc_url($short_url) . '" target="_blank">/' . esc_html($url->short_code) . '</a>';
|
||||
?>
|
||||
</td>
|
||||
<td><?php echo esc_html($url->created_at); ?></td>
|
||||
<td><?php echo esc_html($url->usage_count); ?></td>
|
||||
<td>
|
||||
<button onclick="copyToClipboard('<?php echo esc_js($short_url); ?>')">Copy</button>
|
||||
</td>
|
||||
<td>
|
||||
<a href="?page=vincent-shortner&action=delete&id=<?php echo $url->id; ?>" onclick="return confirm('Are you sure you want to delete this short URL?')">Delete</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function copyToClipboard(text) {
|
||||
navigator.clipboard.writeText(text).then(function() {
|
||||
alert('Short URL copied to clipboard!');
|
||||
}, function(err) {
|
||||
console.error('Could not copy text: ', err);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
// Shortcode to display the form and table on frontend
|
||||
function vincent_shortner_shortcode() {
|
||||
ob_start();
|
||||
|
||||
// Enqueue Bootstrap CSS
|
||||
wp_enqueue_style('bootstrap', 'https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css');
|
||||
|
||||
// Display form and table
|
||||
?>
|
||||
<div class="vincent-shortner-frontend">
|
||||
<?php
|
||||
vincent_shortner_page();
|
||||
?>
|
||||
</div>
|
||||
<style>
|
||||
.vincent-shortner-frontend .wrap {
|
||||
margin: 0;
|
||||
}
|
||||
.vincent-shortner-frontend .wp-list-table {
|
||||
width: 100%;
|
||||
}
|
||||
.vincent-shortner-frontend td {
|
||||
max-width: 200px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.vincent-shortner-frontend th,
|
||||
.vincent-shortner-frontend td {
|
||||
padding: 8px;
|
||||
}
|
||||
.vincent-shortner-frontend .button {
|
||||
padding: 4px 8px;
|
||||
font-size: 12px;
|
||||
text-decoration: none;
|
||||
color: #0071a1;
|
||||
border: 1px solid #0071a1;
|
||||
border-radius: 2px;
|
||||
background: #f3f5f6;
|
||||
text-shadow: none;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
.vincent-shortner-frontend .button:hover {
|
||||
background: #f1f1f1;
|
||||
border-color: #016087;
|
||||
color: #016087;
|
||||
}
|
||||
</style>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
add_shortcode('vincent-short', 'vincent_shortner_shortcode');
|
||||
|
||||
// Handle short URL redirects and update usage count
|
||||
function vincent_shortner_redirect() {
|
||||
global $wpdb;
|
||||
$table_name = $wpdb->prefix . 'vincent_shortner';
|
||||
|
||||
$request_uri = trim($_SERVER['REQUEST_URI'], '/');
|
||||
|
||||
if (!empty($request_uri)) {
|
||||
$short_code = sanitize_text_field($request_uri);
|
||||
$result = $wpdb->get_row($wpdb->prepare("SELECT id, long_url, usage_count FROM $table_name WHERE short_code = %s", $short_code));
|
||||
|
||||
if ($result) {
|
||||
// Update usage count
|
||||
$wpdb->update(
|
||||
$table_name,
|
||||
array('usage_count' => $result->usage_count + 1),
|
||||
array('id' => $result->id)
|
||||
);
|
||||
|
||||
// Redirect to the long URL
|
||||
wp_redirect(esc_url_raw($result->long_url));
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
add_action('init', 'vincent_shortner_redirect');
|
||||
Reference in New Issue
Block a user