Plugin Directory

Changeset 2386570


Ignore:
Timestamp:
09/22/2020 05:49:38 PM (6 years ago)
Author:
nilsnolde
Message:

v1.1.0: implement static caching

Location:
documents-from-git/trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • documents-from-git/trunk/documents-git.php

    r2319715 r2386570  
    33 * Plugin Name: Documents from Git
    44 * Plugin URI: https://github.com/gis-ops/wordpress-markdown-git
    5  * Description: Render various document formats in any post/page directly from a remote Git repository of your favorite platform via shortcodes. Currently supported: Markdown, Jupyter Notebooks.
    6  * Version:     1.0.2
     5 * Description: Render and cache various document formats in any post/page directly from a remote Git repository of your favorite platform via shortcodes. Currently supported: Markdown, Jupyter Notebooks.
     6 * Version:     1.1.0
    77 * Author:      GIS-OPS UG
    88 * Author URI:  https://gis-ops.com
  • documents-from-git/trunk/includes/config.json

    r2274745 r2386570  
    11{
    22  "limit": 5,
     3  "cache_strategy": "static",
     4  "cache_ttl": 3600,
    35  "classes": "",
    46  "Github": {
  • documents-from-git/trunk/includes/providers/class-base-loader.php

    r2319715 r2386570  
    22
    33abstract class BaseLoader {
    4     protected static $GITHUB_MARKDOWN_API = 'https://api.github.com/markdown';
     4    private static $NAMESPACE = 'markdown-git';
     5    private static $GITHUB_MARKDOWN_API = 'https://api.github.com/markdown';
    56    protected static $PROVIDER;  # Needs to be set for every subclass
    67
     
    1516    protected $user;
    1617    protected $token;
     18    protected $limit;
     19    protected $cache_ttl;
     20    protected $cache_strategy;
     21    /**
     22     * @var mixed
     23     */
    1724
    1825    public function __construct() {
     
    5764     * @return mixed array of name, date and message
    5865     */
    59     abstract protected function extract_history_from_commit_json(&$commit);
     66    abstract protected function extract_history_from_commit_json(array &$commit);
    6067
    6168    /**
     
    7279     * @param $sc_attrs array Shortcode attributes
    7380     * @return string HTML of the whole Jupyter notebook processed by nbviewer.jupyter.org
    74      *
    75      */
    76     public function doJupyter($sc_attrs)
     81     */
     82    public function doJupyter(array $sc_attrs)
    7783    {
    7884        $input_url = $this->extract_attributes($sc_attrs);
     85
     86        if ($this->is_static_cache() && $cached_response = $this->get_cached_content($input_url, 'jupyter')) {
     87            return $cached_response;
     88        }
     89
    7990        $this->set_repo_details($input_url);
    8091
     
    110121        }
    111122
    112         return '<div class="nbconvert">' . $inner_html . '</div>';
     123        $output = '<div class="nbconvert">' . $inner_html . '</div>';
     124
     125        if ($this->is_static_cache() && $response_code == 200) {
     126            $this->set_content_cache($input_url,'jupyter', $output);
     127        }
     128
     129        return $output;
    113130    }
    114131
     
    116133     * The callback function for the "markdown" shortcode action.
    117134     *
    118      * @param $sc_attrs array Shortcode attributes
     135     * @param array $sc_attrs Shortcode attributes
    119136     * @return string HTML of the whole Markdown document processed by Github's markdown endpoint
    120      *
    121      */
    122     public function doMarkdown($sc_attrs)
    123     {
    124         list($raw_markdown, $response_code) = $this->get_raw_document($sc_attrs);
     137     */
     138    public function doMarkdown(array $sc_attrs)
     139    {
     140        $url = $this->extract_attributes($sc_attrs);
     141
     142        if ($this->is_static_cache() && $cached_response = $this->get_cached_content($url, 'markdown')) {
     143            return $cached_response;
     144        }
     145
     146        $this->set_repo_details($url);
     147        list($raw_markdown, $response_code) = $this->get_document();
    125148
    126149        switch ($response_code) {
     
    159182        $html_body = wp_remote_retrieve_body($response);
    160183
    161         return '<div class="markdown-body">' . $html_body . '</div>';
     184        $html_string = '<div class="markdown-body">' . $html_body . '</div>';
     185
     186        if ($this->is_static_cache() && $response_code == 200) {
     187            $this->set_content_cache($url,'markdown', $html_string);
     188        }
     189
     190        return $html_string;
    162191    }
    163192
     
    170199     * @return string HTML for the checkout span
    171200     */
    172     public function doCheckout($sc_attrs)
     201    public function doCheckout(array $sc_attrs)
    173202    {
    174203        $url = $this->extract_attributes($sc_attrs);
     204
     205        if ($this->is_static_cache() && $cached_response = $this->get_cached_content($url, 'checkout')) {
     206            return $cached_response;
     207        }
     208
    175209        $this->set_repo_details($url);
    176210
     
    189223        }
    190224
    191         return '
     225        $html_string = '
    192226        <div class="markdown-github">
    193227          <div class="markdown-github-labels">
     
    198232          </div>
    199233        </div>';
     234
     235        if ($this->is_static_cache() && $response_code == 200) {
     236            $this->set_content_cache($url, 'checkout', $html_string);
     237        }
     238
     239        return $html_string;
    200240    }
    201241
     
    206246     * @return string HTML for the Last X commits section
    207247     */
    208     public function doHistory($sc_attrs)
     248    public function doHistory(array $sc_attrs)
    209249    {
    210250        $url = $this->extract_attributes($sc_attrs);
     251
     252        if ($this->is_static_cache() && $cached_response = $this->get_cached_content($url, 'history')) {
     253            return $cached_response;
     254        }
     255
    211256        if (empty($this->limit)) {
    212257            $this->limit = 5;
     
    230275        $html_string .= '</article>';
    231276
     277        if ($this->is_static_cache()) {
     278            $this->set_content_cache($url, 'history', $html_string);
     279        }
     280
    232281        return $html_string;
    233282    }
     
    238287     * @return string Base64 encoded Basic Authorization header
    239288     */
    240     protected function get_auth_header(){
     289    protected function get_auth_header()
     290    {
    241291        return 'Basic ' . base64_encode($this->user . ':' . $this->token);
    242292    }
     
    248298     * @param $url string URL of the file to be rendered
    249299     */
    250     protected function set_repo_details($url)
     300    protected function set_repo_details(string $url)
    251301    {
    252302        $url_parsed = parse_url($url);
     
    265315        $this->branch = $branch;
    266316        $this->file_path = $file_path;
    267 
    268     }
    269 
    270     private function get_raw_document($sc_attrs)
    271     {
    272         $url = $this->extract_attributes($sc_attrs);
    273         $this->set_repo_details($url);
    274         list($raw_document, $response_code) = $this->get_document();
    275 
    276         return array($raw_document, $response_code);
    277317    }
    278318
     
    281321     * but not necessarily passed, so they default to an empty string.
    282322     *
    283      * It also sets the class attributes "user", "token" and "limit" from config.json or shortcode attribute.
     323     * It also sets the class attributes "user", "token", "cache_ttl" and "limit" from config.json or shortcode attribute.
    284324     *
    285325     * @param $attrs array Attributes of the shortcode
    286326     * @return string parsed url
    287327     */
    288     private function extract_attributes($attrs) {
    289 
     328    private function extract_attributes(array $attrs)
     329    {
    290330        $attrs = array_change_key_case((array)$attrs, CASE_LOWER);
    291331        extract(shortcode_atts(array(
     
    293333                'user' => "",
    294334                'token' => "",
    295                 'limit' => ""
     335                'limit' => "",
     336                'cache_ttl' => "",
     337                'cache_strategy' => "",
    296338            ), $attrs
    297339            )
     
    301343        $this->token = ($token === '') ? (MARKDOWNGIT_CONFIG[static::$PROVIDER]["token"]) : ($token);
    302344        $this->limit = ($limit === '') ? (MARKDOWNGIT_CONFIG["limit"]) : ($limit);
     345        $this->cache_ttl = ($cache_ttl === '') ? (MARKDOWNGIT_CONFIG["cache_ttl"]) : ($cache_ttl);
     346        $this->cache_strategy = ($cache_strategy === '') ? (MARKDOWNGIT_CONFIG["cache_strategy"]) : ($cache_strategy);
    303347
    304348        return $url;
    305349    }
     350
     351    /**
     352     * Get cached content when cache is enabled.
     353     *
     354     * @param string $url cache key to be serialized.
     355     * @param string $group group where content was stored.
     356     * @return mixed
     357     *
     358     * @since 1.1.0
     359     */
     360    private function get_cached_content(string $url, string $group)
     361    {
     362        return get_transient($this->get_cache_key($url, $group));
     363    }
     364
     365    /**
     366     * Caches content using a cache key
     367     *
     368     * @param string $url cache key.
     369     * @param string $group group where content was stored.
     370     * @param mixed $content content to cache.
     371     *
     372     * @since 1.1.0
     373     */
     374    private function set_content_cache(string $url, string $group, $content)
     375    {
     376        set_transient($this->get_cache_key($url, $group), $content, (int) $this->cache_ttl);
     377    }
     378
     379    /**
     380     * Constructs the cache key from the attributes.
     381     *
     382     * @param string $url The URL of the document
     383     * @param string $group The cache group
     384     *
     385     * @since 1.1.0
     386     */
     387    private function get_cache_key(string $url, string $group)
     388    {
     389        return md5(self::$NAMESPACE . $group . $url . strval($this->cache_ttl) . strval($this->limit));
     390    }
     391
     392    /**
     393     * True if cache strategy is static, false if it's dynamic.
     394     *
     395     * @return boolean
     396     *
     397     * @since 1.1.0
     398     */
     399    private function is_static_cache()
     400    {
     401        return $this->cache_strategy === 'static';;
     402    }
    306403}
  • documents-from-git/trunk/includes/providers/class-bitbucket-loader.php

    r2274745 r2386570  
    55    protected static $PROVIDER = 'Bitbucket';
    66
    7     protected function extract_history_from_commit_json(&$commit) {
     7    protected function extract_history_from_commit_json(array &$commit) {
    88        return array(
    99            $commit['author']['raw'],
  • documents-from-git/trunk/includes/providers/class-github-loader.php

    r2274745 r2386570  
    55    protected static $PROVIDER = 'Github';
    66
    7     protected function extract_history_from_commit_json(&$commit) {
     7    protected function extract_history_from_commit_json(array &$commit) {
    88        return array(
    99            $commit['commit']['author']['name'],
  • documents-from-git/trunk/includes/providers/class-gitlab-loader.php

    r2274745 r2386570  
    55    protected static $PROVIDER = 'Gitlab';
    66
    7     protected function extract_history_from_commit_json(&$commit) {
     7    protected function extract_history_from_commit_json(array &$commit) {
    88        return array(
    99            $commit['author_name'],
     
    5656    }
    5757
    58     protected function set_repo_details($url)
     58    protected function set_repo_details(string $url)
    5959    {
    6060        $url_parsed = parse_url($url);
  • documents-from-git/trunk/readme.txt

    r2319715 r2386570  
    11=== Documents from Git ===
    2 Contributors: nilsnolde
     2Contributors: nilsnolde,danilopinotti
    33Plugin Name: Documents from Git
    44Plugin URI: https://github.com/gis-ops/wordpress-markdown-git
     
    77Author: GIS-OPS UG
    88Requires at least: 5.0.0
    9 Tested up to: 5.4.1
     9Tested up to: 5.5.1
    1010Requires PHP: 7.0
    11 Stable tag: 1.0.2
    12 Version: 1.0.2
     11Stable tag: 1.1.0
     12Version: 1.1.0
    1313License: GPLv3
    1414License URI: https://github.com/gis-ops/wordpress-markdown-git/blob/master/LICENSE
     
    4747**Note**, this plugin uses Github's wonderful [`/markdown` API](https://developer.github.com/v3/markdown/) to render to HTML. This comes with 2 caveats:
    4848
    49 1. Unless authenticated, the rate limit is set at 60 requests per minute. It's **strongly recommended** to create a Github access token and register it with the plugin. Then the rate limit will be set to 5000 requests per hour. See [Global attributes section](#global-attributes) for details on how to do that.
     491. Unless authenticated, the rate limit is set at 60 requests per minute. Since v1.1.0 the plugin is capable of statically [caching content](#caching). In case that's not dynamic enough for you, your only option currently is to not use any cache in which case every document will be pulled from your provider every time someone opens it on your site. Then it's **strongly recommended** to create a Github access token and register it with the plugin. Then the rate limit will be set to 5000 requests per hour. See [Global attributes section](#global-attributes) for details on how to do that.
    50502. The Markdown content cannot exceed 400 KB, so roughly 400 000 characters incl whitespace. If not a monographic dissertation, this should not be an applicable limit though.
    5151
     
    9393| `user`      | all except `git-add-css` | :negative_squared_cross_mark: | :ballot_box_with_check:       | string  | The **user name** (not email) of an authorized user                                                           |
    9494| `token`     | all except `git-add-css` | :negative_squared_cross_mark: | :ballot_box_with_check:       | string  | The access token/app password for the authorized user                                                         |
    95 | `limit`     | `history`                | :negative_squared_cross_mark: | :negative_squared_cross_mark: | integer | Limits the history of commits to this number. Default 5.                                                                |
     95| `cache_ttl` | all except `git-add-css` | :negative_squared_cross_mark:       | :negative_squared_cross_mark:       | integer | The time in seconds that the plugin will cache, **only for `cache_strategy=static`**.           |
     96| `cache_strategy` | all except `git-add-css` | :negative_squared_cross_mark:       | :negative_squared_cross_mark:       | integer | Only `static` caching is implemented so far. `dynamic` caching is on the way!                   |
     97| `limit`     | `history`                | :negative_squared_cross_mark: | :negative_squared_cross_mark: | integer | Limits the history of commits to this number. Default 5.                                                      |
    9698| `classes`   | `git-add-css`            | :ballot_box_with_check:       | :ballot_box_with_check:       | string  | The additional CSS classes to render the content with                                                         |
    9799
     
    104106**Note**, setting the attributes manually in the shortcode has always precedence over any settings in `includes/config.json`.
    105107
     108#### Caching
     109
     110Often we need to prioritize speed when loading content and, in addition, it is very costly to fetch, load and format the content every time we need to read the content of the post.
     111
     112This plugin soon offers 2 methods for caching, `static` and `dynamic` which can be set via the `cache_strategy` property.
     113
     114##### Static caching (`cache_strategy=static`)
     115
     116This is the default strategy, as it doesn't require any user action.
     117
     118The property `cache_ttl` sets how many **seconds** the content cache will keep alive.
     119
     120Currently there's no way to flush the cache manually. However, changing `cache_ttl` or the history `limit` will create a new cache.
     121
     122##### Dynamic caching (`cache_strategy=dynamic`)
     123
     124**This is not implemented yet**. See [#20](https://github.com/gis-ops/wordpress-markdown-git/issues/20) for details.
     125
    106126#### `Token` authorization
    107127
    108128You **need to** authorize via `user` and `token` if you intend to publish from a private repository. You **don't need to** authorize if the repository is open.
    109129
    110 However, keep in mind that some platforms have stricter API limits for anonymous requests which are greatly extended if you provide your credentials. So even for public repos it could make sense. And it's strongly recommended to register a Github access token regardless of the VCS hosting platform, see the [beginning of the chapter](#usage).
     130However, keep in mind that some platforms have stricter API limits for anonymous requests which are greatly extended if you provide your credentials. So even for public repos it could make sense. And unless you use this plugin's [caching capabilities](#caching), it's strongly recommended to register a Github access token regardless of the VCS hosting platform, see the [beginning of the chapter](#usage).
    111131
    112132How to generate the `token` depends on your platform:
     
    125145
    126146`[git-github-markdown url="https://github.com/gis-ops/tutorials/blob/master/qgis/QGIS_SimplePlugin.md"]`
     147
     148#### Publish Markdown from Github with 1 hour cache
     149
     150`[git-github-markdown url="https://github.com/gis-ops/tutorials/blob/master/qgis/QGIS_SimplePlugin.md" cache_ttl="3600" cache_strategy="static"]`
    127151
    128152#### Publish Jupyter notebook from Github
     
    181205== Frequently Asked Questions ==
    182206
     207= Does the plugin support caching? =
     208
     209Yes, since v1.1.0 the plugin supports static caching of all relevant information. See the ["Caching" section](https://github.com/gis-ops/wordpress-markdown-git#caching) for details.
     210
    183211= Are relative links supported? =
    184212
     
    200228== Changelog ==
    201229
     230= v1.1.0 =
     231* implement static caching
     232
    202233= v1.0.2 =
    203234* Fixed rate limiting for unauthenticated `/markdown` requests
Note: See TracChangeset for help on using the changeset viewer.