how to add active entries to static page

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:

enter image description here

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 the globalkeyword.

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();