Ok, here you go.
I made a wireframe for you to use, which saves links to a custom table and adds a form in the admin page.
Again. I think its wayyyyy overkill. Doing it ‘the wordpress way’ is a safer bet. But, it was a fun little excersise that I don’t get to do often!
I’ll copy paste the code below. You’ll need to save it to a file in wp-content
and activate the plugin.
Here is what the admin will look like after the plugin is activated:
To use it on the front end, you’ll have to get the global class and call read_links_archive( $args )
like so:
global $customlinks;
$links = $customlinks->get_links_archive();
foreach ( $links as $link ) { ... }
Also, note the code is very much incomplete! But I’ve anotated with links whenver possible so it should get you started very well!
It works like this:
- There is a CustomLinks class that houses all the CRUD functions ( minus delete, that one’s for you to have some fun) and admin rendering magic
- The database is installed when the plugin is activated through a hook
- On construct, it adds the actions to create the database schema and register menu page
- Menu page loads a ‘router’ that looks for an ‘action’ post variable, which calls methods accordingly
- At the very end, the class is instantiated into the
$customlinks
variable which you can access with theglobal
keyword.
You’ll have to fill in the gaps:
- Delete method doesn’t exist
- There is no interface for the update method
- The save action is unprotected, either by Nonces or capability checks
read_links_archive
is doesn’t filter by date or has pagination (but its setup to receive arguments)- You’ll need pagination in the admin page
- Make it better all around!
Play around with the code and have fun. If you have any questions feel free to ask.
Cheers!
The code:
<?php
/**
* Custom links
*
* Plugin Name: Custom links
* Version: 0.1
*
*/
class CustomLinks {
/**
* Constructor
*/
function __construct() {
// add actions
// install database on activation
register_activation_hook( __FILE__, array( $this, 'setup_database') );
// menu items
add_action( 'admin_menu', array( $this, 'add_menu_item' ) );
}
/*****************************
Setup database
*****************************/
/**
* Creates the database schema
*
* Hook onto plugin initialize
*
* @link https://codex.wordpress.org/Creating_Tables_with_Plugins
*/
public function setup_database() {
// get the wordpress database helper
global $wpdb;
// table name
$table_name = $wpdb->prefix . 'custom_links';
// get colation
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE $table_name (
ID mediumint(9) NOT NULL AUTO_INCREMENT,
time datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
link text NOT NULL,
PRIMARY KEY (ID)
) $charset_collate;";
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
dbDelta( $sql );
}
/*****************************
CRUD functions
*****************************/
/**
* Returns a single link
*
* @param int $id The link ID
* @return string|bool The link or false
*/
public function read_link_single( $id ) {
global $wpdb;
$sql = $wpdb->prepare( "
SELECT link
FROM {$wpdb->prefix}custom_links
WHERE ID = %d
LIMIT 1
", $id );
$result = $wpdb->get_results( $sql );
// databse error, return false
if ( ! $result ) { return false; }
// return first result
return $result[0];
}
/**
* Returns all links
*
* @param array $args Optional arguments to pass, such as limit or date
* @return string[]|bool The links or false
*/
public function read_link_archive( $args = array() ) {
global $wpdb;
// default values
$default = array(
'limit' => 10
);
// parses default values
$args = wp_parse_args( $args, $default );
$sql = $wpdb->prepare( "
SELECT *
FROM {$wpdb->prefix}custom_links
LIMIT %d
", $args[ 'limit' ] );
return $wpdb->get_results( $sql );
// TODO: Pagination, filtering ETC
}
/**
* Creates link, returns ID
*
* @link https://codex.wordpress.org/Class_Reference/wpdb#INSERT_row
* @param string $link The link URL
* @return int|bool Link unique ID, or false
*/
public function create_link( $link ) {
global $wpdb;
// sanitize link
$link = esc_url( $link );
// try to insert
$result = $wpdb->insert(
$wpdb->prefix . 'custom_links',
array(
'time' => current_time( 'mysql' ),
'link' => $link
)
);
// return error
if ( ! $result ) { return false; }
// otherwise return id of new row
return $wpdb->insert_id;
}
/**
* Updates the selected links
*
* @link https://codex.wordpress.org/Class_Reference/wpdb#UPDATE_rows
* @param int $id The id to update
* @param string $link The link URL
* @return bool Update sucessful?
*/
public function update_link( $id, $link ) {
global $wpdb;
$result = $wpdb->update(
$wpdb->prefix . 'custom_links',
array(
'link' => $link, // new value string
),
array( 'ID' => $id ) // condition
);
// return update status
return $result !== false;
}
/*****************************
Display functions for admin
******************************/
/**
* Adds a menu item for links
*
* Hook into admin_menu
*
* @link https://developer.wordpress.org/reference/functions/add_menu_page/
*/
public function add_menu_item() {
add_menu_page(
'Custom Links',
'Custom Links',
'manage_options',
'custom_links',
array( $this, 'route_links_page' )
);
}
/**
* "Route links page"
*/
public function route_links_page() {
// check 'action'
$action = $_POST[ 'action' ] || '';
// switch here for more pages in the future
switch ( $action ) {
case 'save':
// save action
$this->save_link();
$this->render_links_page();
break;
default:
// by default, render links
$this->render_links_page();
break;
}
}
/**
* Renders the link page
*
* @param int $page The paginations current page to show
*/
private function render_links_page( $page = 0 ) {
// get all links ( 10 by default )
$links = $this->read_link_archive();
?>
<div class="wrap">
<h1>Custom Links</h1>
</div>
<!-- links -->
<table class="wp-list-table widefat fixed striped posts">
<tbody id="">
<?php foreach ( $links as $link ) : ?>
<tr>
<td><? echo $link->link ?></td>
<td><? echo $link->time ?></td>
</tr>
<?php endforeach; ?>
</tbody>
<?php // TODO: Edit and delete link ?>
</table>
<!-- add new link -->
<h2>Add New Link</h2>
<form action="<?php menu_page_url( 'custom_links' ); ?>" method="post">
<input type="hidden" name="action" value="save">
<label for="link">Link: </label>
<input type="text" name="link">
<?php submit_button( 'Save Link' ); ?>
<?php // TODO: Protect with Nonce ?>
</form>
<?php }
/**
* Saves the links and outputs message
*/
private function save_link() {
if ( isset( $_POST[ 'link' ] ) ) {
$result = $this->create_link( esc_url( $_POST[ 'link' ] ) );
}
if ( $result ) : ?>
<div class="notice notice-success">
<p>Link ID <?php echo $result; ?> saved.</p>
</div>
<? else : ?>
<div class="notice notice-error">
<p>There was a problem saving the link</p>
</div>
<?php endif;
}
}
/*****************************
Instantiate
******************************/
$customlinks = new CustomLinks();