Plugin Directory

Changeset 1713007


Ignore:
Timestamp:
08/14/2017 08:18:41 AM (8 years ago)
Author:
litefeel
Message:

auto deploy from deploy2wp:https://github.com/litefeel/deploy2wp

Location:
writing-on-github/trunk
Files:
39 added
8 deleted
19 edited

Legend:

Unmodified
Added
Removed
  • writing-on-github/trunk/lib/admin.php

    r1709881 r1713007  
    1010class Writing_On_GitHub_Admin {
    1111
    12     /**
    13      * Hook into GitHub API
    14      */
    15     public function __construct() {
    16         add_action( 'admin_menu', array( $this, 'add_admin_menu' ) );
    17         add_action( 'admin_init', array( $this, 'register_settings' ) );
    18         add_action( 'current_screen', array( $this, 'trigger_cron' ) );
    19     }
    20 
    21     /**
    22      * Callback to render the settings page view
    23      */
    24     public function settings_page() {
    25         include dirname( dirname( __FILE__ ) ) . '/views/options.php';
    26     }
    27 
    28     /**
    29      * Callback to register the plugin's options
    30      */
    31     public function register_settings() {
    32         add_settings_section(
    33             'general',
    34             'General Settings',
    35             array( $this, 'section_callback' ),
    36             Writing_On_GitHub::$text_domain
    37         );
    38 
    39         register_setting( Writing_On_GitHub::$text_domain, 'wogh_host' );
    40         add_settings_field( 'wogh_host', __( 'GitHub hostname', 'writing-on-github' ), array( $this, 'field_callback' ), Writing_On_GitHub::$text_domain, 'general', array(
    41                 'default'   => 'https://api.github.com',
    42                 'name'      => 'wogh_host',
    43                 'help_text' => __( 'The GitHub host to use. This only needs to be changed to support a GitHub Enterprise installation.', 'writing-on-github' ),
    44             )
    45         );
    46 
    47         register_setting( Writing_On_GitHub::$text_domain, 'wogh_repository' );
    48         add_settings_field( 'wogh_repository', __( 'Repository', 'writing-on-github' ), array( $this, 'field_callback' ), Writing_On_GitHub::$text_domain, 'general', array(
    49                 'default'   => '',
    50                 'name'      => 'wogh_repository',
    51                 'help_text' => __( 'The GitHub repository to commit to, with owner (<code>[OWNER]/[REPOSITORY]</code>), e.g., <code>github/hubot.github.com</code>. The repository should contain an initial commit, which is satisfied by including a README when you create the repository on GitHub.', 'writing-on-github' ),
    52             )
    53         );
    54 
    55         register_setting( Writing_On_GitHub::$text_domain, 'wogh_branch' );
    56         add_settings_field( 'wogh_branch', __( 'Branch', 'writing-on-github' ), array( $this, 'field_callback' ), Writing_On_GitHub::$text_domain, 'general', array(
    57                 'default'   => 'master',
    58                 'name'      => 'wogh_branch',
    59                 'help_text' => __( 'The GitHub branch to commit to, default is master.', 'writing-on-github' ),
    60             )
    61         );
    62 
    63         register_setting( Writing_On_GitHub::$text_domain, 'wogh_oauth_token' );
    64         add_settings_field( 'wogh_oauth_token', __( 'Oauth Token', 'writing-on-github' ), array( $this, 'field_callback' ), Writing_On_GitHub::$text_domain, 'general', array(
    65                 'default'   => '',
    66                 'name'      => 'wogh_oauth_token',
    67                 'help_text' => __( "A <a href='https://github.com/settings/tokens/new'>personal oauth token</a> with <code>public_repo</code> scope.", 'writing-on-github' ),
    68             )
    69         );
    70 
    71         register_setting( Writing_On_GitHub::$text_domain, 'wogh_secret' );
    72         add_settings_field( 'wogh_secret', __( 'Webhook Secret', 'writing-on-github' ), array( $this, 'field_callback' ), Writing_On_GitHub::$text_domain, 'general', array(
    73                 'default'   => '',
    74                 'name'      => 'wogh_secret',
    75                 'help_text' => __( "The webhook's secret phrase. This should be password strength, as it is used to verify the webhook's payload.", 'writing-on-github' ),
    76             )
    77         );
    78 
    79         register_setting( Writing_On_GitHub::$text_domain, 'wogh_default_user' );
    80         add_settings_field( 'wogh_default_user', __( 'Default Import User', 'writing-on-github' ), array( &$this, 'user_field_callback' ), Writing_On_GitHub::$text_domain, 'general', array(
    81                 'default'   => '',
    82                 'name'      => 'wogh_default_user',
    83                 'help_text' => __( 'The fallback user for import, in case Writing On GitHub cannot find the committer in the database.', 'writing-on-github' ),
    84             )
    85         );
     12    /**
     13     * plugin file name rel plugin dir.
     14     * @var string
     15     */
     16    protected $plugin_file;
     17
     18    /**
     19     * Hook into GitHub API
     20     */
     21    public function __construct( $plugin_file ) {
     22        $this->plugin_file = $plugin_file;
     23
     24        add_action( 'admin_menu', array( $this, 'add_admin_menu' ) );
     25        add_action( 'admin_init', array( $this, 'register_settings' ) );
     26        add_action( 'current_screen', array( $this, 'trigger_cron' ) );
     27        add_filter( 'plugin_action_links', array($this, 'settings_links'), 10, 2 );
     28    }
     29
     30    /**
     31     * settings link
     32     * @param  string[] $links
     33     * @param  string $file
     34     * @return string[]
     35     */
     36    public function settings_links( $links, $file ) {
     37        if ( $file != $this->plugin_file ) {
     38            return $links;
     39        }
     40
     41        $settings_link = '<a href="options-general.php?page=' .
     42        Writing_On_GitHub::$text_domain . '">' . __( 'Settings', 'writing-on-github' ) . '</a>';
     43
     44        array_push( $links, $settings_link );
     45
     46        return $links;
     47    }
     48
     49    /**
     50     * Callback to render the settings page view
     51     */
     52    public function settings_page() {
     53        include dirname( dirname( __FILE__ ) ) . '/views/options.php';
     54    }
     55
     56    /**
     57     * Callback to register the plugin's options
     58     */
     59    public function register_settings() {
     60        add_settings_section(
     61            'general',
     62            'General Settings',
     63            array( $this, 'section_callback' ),
     64            Writing_On_GitHub::$text_domain
     65        );
     66
     67        register_setting( Writing_On_GitHub::$text_domain, 'wogh_host' );
     68        add_settings_field( 'wogh_host', __( 'GitHub hostname', 'writing-on-github' ), array( $this, 'field_callback' ), Writing_On_GitHub::$text_domain, 'general', array(
     69                'default'   => 'https://api.github.com',
     70                'name'      => 'wogh_host',
     71                'help_text' => __( 'The GitHub host to use. This only needs to be changed to support a GitHub Enterprise installation.', 'writing-on-github' ),
     72            )
     73        );
     74
     75        register_setting( Writing_On_GitHub::$text_domain, 'wogh_repository' );
     76        add_settings_field( 'wogh_repository', __( 'Repository', 'writing-on-github' ), array( $this, 'field_callback' ), Writing_On_GitHub::$text_domain, 'general', array(
     77                'default'   => '',
     78                'name'      => 'wogh_repository',
     79                'help_text' => __( 'The GitHub repository to commit to, with owner (<code>[OWNER]/[REPOSITORY]</code>), e.g., <code>github/hubot.github.com</code>. The repository should contain an initial commit, which is satisfied by including a README when you create the repository on GitHub.', 'writing-on-github' ),
     80            )
     81        );
     82
     83        register_setting( Writing_On_GitHub::$text_domain, 'wogh_branch' );
     84        add_settings_field( 'wogh_branch', __( 'Branch', 'writing-on-github' ), array( $this, 'field_callback' ), Writing_On_GitHub::$text_domain, 'general', array(
     85                'default'   => 'master',
     86                'name'      => 'wogh_branch',
     87                'help_text' => __( 'The GitHub branch to commit to, default is master.', 'writing-on-github' ),
     88            )
     89        );
     90
     91        register_setting( Writing_On_GitHub::$text_domain, 'wogh_oauth_token' );
     92        add_settings_field( 'wogh_oauth_token', __( 'Oauth Token', 'writing-on-github' ), array( $this, 'field_callback' ), Writing_On_GitHub::$text_domain, 'general', array(
     93                'default'   => '',
     94                'name'      => 'wogh_oauth_token',
     95                'help_text' => __( "A <a href='https://github.com/settings/tokens/new'>personal oauth token</a> with <code>public_repo</code> scope.", 'writing-on-github' ),
     96            )
     97        );
     98
     99        register_setting( Writing_On_GitHub::$text_domain, 'wogh_secret' );
     100        add_settings_field( 'wogh_secret', __( 'Webhook Secret', 'writing-on-github' ), array( $this, 'field_callback' ), Writing_On_GitHub::$text_domain, 'general', array(
     101                'default'   => '',
     102                'name'      => 'wogh_secret',
     103                'help_text' => __( "The webhook's secret phrase. This should be password strength, as it is used to verify the webhook's payload.", 'writing-on-github' ),
     104            )
     105        );
     106
     107        register_setting( Writing_On_GitHub::$text_domain, 'wogh_default_user' );
     108        add_settings_field( 'wogh_default_user', __( 'Default Import User', 'writing-on-github' ), array( &$this, 'user_field_callback' ), Writing_On_GitHub::$text_domain, 'general', array(
     109                'default'   => '',
     110                'name'      => 'wogh_default_user',
     111                'help_text' => __( 'The fallback user for import, in case Writing On GitHub cannot find the committer in the database.', 'writing-on-github' ),
     112            )
     113        );
    86114
    87115        register_setting( Writing_On_GitHub::$text_domain, 'wogh_ignore_author' );
     
    93121        );
    94122
    95         // register_setting( Writing_On_GitHub::$text_domain, 'wogh_ignore_metas' );
    96         // add_settings_field( 'wogh_ignore_metas', __( 'Ignore post metas', 'writing-on-github' ), array( &$this, 'textarea_field_callback' ), Writing_On_GitHub::$text_domain, 'general', array(
    97         //      'default'   => '',
    98         //      'name'      => 'wogh_ignore_metas',
    99         //      'help_text' => __( 'These meta keys will be ignored and cannot be imported and exported. One meta key per line.', 'writing-on-github' ),
    100         //  )
    101         // );
    102     }
    103 
    104     /**
    105      * Callback to render an individual options field
    106      *
    107      * @param array $args Field arguments.
    108      */
    109     public function field_callback( $args ) {
    110         include dirname( dirname( __FILE__ ) ) . '/views/setting-field.php';
    111     }
    112 
    113     /**
    114      * Callback to render the default import user field.
    115      *
    116      * @param array $args Field arguments.
    117      */
    118     public function user_field_callback( $args ) {
    119         include dirname( dirname( __FILE__ ) ) . '/views/user-setting-field.php';
    120     }
    121 
    122     /**
    123      * Callback to render the textarea field.
    124      *
    125      * @param array $args Field arguments.
    126      */
    127     public function textarea_field_callback( $args ) {
    128         include dirname( dirname( __FILE__ ) ) . '/views/textarea-setting-field.php';
    129     }
     123        register_setting( Writing_On_GitHub::$text_domain, 'wogh_dont_export_content' );
     124        add_settings_field( 'wogh_dont_export_content', __( 'Don\'t export content', 'writing-on-github' ), array( &$this, 'checkbox_field_callback' ), Writing_On_GitHub::$text_domain, 'general', array(
     125                'default'   => '',
     126                'name'      => 'wogh_dont_export_content',
     127                'help_text' => __( 'Do not export post content to github, only export meta.', 'writing-on-github' ),
     128            )
     129        );
     130
     131        // register_setting( Writing_On_GitHub::$text_domain, 'wogh_ignore_metas' );
     132        // add_settings_field( 'wogh_ignore_metas', __( 'Ignore post metas', 'writing-on-github' ), array( &$this, 'textarea_field_callback' ), Writing_On_GitHub::$text_domain, 'general', array(
     133        //      'default'   => '',
     134        //      'name'      => 'wogh_ignore_metas',
     135        //      'help_text' => __( 'These meta keys will be ignored and cannot be imported and exported. One meta key per line.', 'writing-on-github' ),
     136        //  )
     137        // );
     138    }
     139
     140    /**
     141     * Callback to render an individual options field
     142     *
     143     * @param array $args Field arguments.
     144     */
     145    public function field_callback( $args ) {
     146        include dirname( dirname( __FILE__ ) ) . '/views/setting-field.php';
     147    }
     148
     149    /**
     150     * Callback to render the default import user field.
     151     *
     152     * @param array $args Field arguments.
     153     */
     154    public function user_field_callback( $args ) {
     155        include dirname( dirname( __FILE__ ) ) . '/views/user-setting-field.php';
     156    }
     157
     158    /**
     159     * Callback to render the textarea field.
     160     *
     161     * @param array $args Field arguments.
     162     */
     163    public function textarea_field_callback( $args ) {
     164        include dirname( dirname( __FILE__ ) ) . '/views/textarea-setting-field.php';
     165    }
    130166
    131167    /**
     
    138174    }
    139175
    140     /**
    141     * Displays settings messages from background processes
    142     */
    143     public function section_callback() {
    144         if ( get_current_screen()->id !== 'settings_page_' . Writing_On_GitHub::$text_domain ) {
    145             return;
    146         }
    147 
    148         if ( 'yes' === get_option( '_wogh_export_started' ) ) { ?>
    149             <div class="updated">
    150                 <p><?php esc_html_e( 'Export to GitHub started.', 'writing-on-github' ); ?></p>
    151             </div><?php
    152             delete_option( '_wogh_export_started' );
    153         }
    154 
    155         if ( $message = get_option( '_wogh_export_error' ) ) { ?>
    156             <div class="error">
    157                 <p><?php esc_html_e( 'Export to GitHub failed with error:', 'writing-on-github' ); ?> <?php echo esc_html( $message );?></p>
    158             </div><?php
    159             delete_option( '_wogh_export_error' );
    160         }
    161 
    162         if ( 'yes' === get_option( '_wogh_export_complete' ) ) { ?>
    163             <div class="updated">
    164                 <p><?php esc_html_e( 'Export to GitHub completed successfully.', 'writing-on-github' );?></p>
    165             </div><?php
    166             delete_option( '_wogh_export_complete' );
    167         }
    168 
    169         if ( 'yes' === get_option( '_wogh_import_started' ) ) { ?>
    170             <div class="updated">
    171             <p><?php esc_html_e( 'Import from GitHub started.', 'writing-on-github' ); ?></p>
    172             </div><?php
    173             delete_option( '_wogh_import_started' );
    174         }
    175 
    176         if ( $message = get_option( '_wogh_import_error' ) ) { ?>
    177             <div class="error">
    178             <p><?php esc_html_e( 'Import from GitHub failed with error:', 'writing-on-github' ); ?> <?php echo esc_html( $message );?></p>
    179             </div><?php
    180             delete_option( '_wogh_import_error' );
    181         }
    182 
    183         if ( 'yes' === get_option( '_wogh_import_complete' ) ) { ?>
    184             <div class="updated">
    185             <p><?php esc_html_e( 'Import from GitHub completed successfully.', 'writing-on-github' );?></p>
    186             </div><?php
    187             delete_option( '_wogh_import_complete' );
    188         }
    189     }
    190 
    191     /**
    192     * Add options menu to admin navbar
    193     */
    194     public function add_admin_menu() {
    195         add_options_page(
    196             __( 'Writing On GitHub', 'writing-on-github' ),
    197             __( 'Writing On GitHub', 'writing-on-github' ),
    198             'manage_options',
    199             Writing_On_GitHub::$text_domain,
    200             array( $this, 'settings_page' )
    201         );
    202     }
    203 
    204     /**
    205     * Admin callback to trigger import/export because WordPress admin routing lol
    206     */
    207     public function trigger_cron() {
    208         if ( ! current_user_can( 'manage_options' ) ) {
    209             return;
    210         }
    211 
    212         if ( get_current_screen()->id !== 'settings_page_' . Writing_On_GitHub::$text_domain ) {
    213             return;
    214         }
    215 
    216         if ( ! isset( $_GET['action'] ) ) {
    217             return;
    218         }
    219 
    220         if ( 'export' === $_GET['action'] ) {
    221             Writing_On_GitHub::$instance->start_export();
    222         }
     176    /**
     177    * Displays settings messages from background processes
     178    */
     179    public function section_callback() {
     180        if ( get_current_screen()->id !== 'settings_page_' . Writing_On_GitHub::$text_domain ) {
     181            return;
     182        }
     183
     184        if ( 'yes' === get_option( '_wogh_export_started' ) ) { ?>
     185            <div class="updated">
     186                <p><?php esc_html_e( 'Export to GitHub started.', 'writing-on-github' ); ?></p>
     187            </div><?php
     188            delete_option( '_wogh_export_started' );
     189        }
     190
     191        if ( $message = get_option( '_wogh_export_error' ) ) { ?>
     192            <div class="error">
     193                <p><?php esc_html_e( 'Export to GitHub failed with error:', 'writing-on-github' ); ?> <?php echo esc_html( $message );?></p>
     194            </div><?php
     195            delete_option( '_wogh_export_error' );
     196        }
     197
     198        if ( 'yes' === get_option( '_wogh_export_complete' ) ) { ?>
     199            <div class="updated">
     200                <p><?php esc_html_e( 'Export to GitHub completed successfully.', 'writing-on-github' );?></p>
     201            </div><?php
     202            delete_option( '_wogh_export_complete' );
     203        }
     204
     205        if ( 'yes' === get_option( '_wogh_import_started' ) ) { ?>
     206            <div class="updated">
     207            <p><?php esc_html_e( 'Import from GitHub started.', 'writing-on-github' ); ?></p>
     208            </div><?php
     209            delete_option( '_wogh_import_started' );
     210        }
     211
     212        if ( $message = get_option( '_wogh_import_error' ) ) { ?>
     213            <div class="error">
     214            <p><?php esc_html_e( 'Import from GitHub failed with error:', 'writing-on-github' ); ?> <?php echo esc_html( $message );?></p>
     215            </div><?php
     216            delete_option( '_wogh_import_error' );
     217        }
     218
     219        if ( 'yes' === get_option( '_wogh_import_complete' ) ) { ?>
     220            <div class="updated">
     221            <p><?php esc_html_e( 'Import from GitHub completed successfully.', 'writing-on-github' );?></p>
     222            </div><?php
     223            delete_option( '_wogh_import_complete' );
     224        }
     225    }
     226
     227    /**
     228    * Add options menu to admin navbar
     229    */
     230    public function add_admin_menu() {
     231        add_options_page(
     232            __( 'Writing On GitHub', 'writing-on-github' ),
     233            __( 'Writing On GitHub', 'writing-on-github' ),
     234            'manage_options',
     235            Writing_On_GitHub::$text_domain,
     236            array( $this, 'settings_page' )
     237        );
     238    }
     239
     240    /**
     241    * Admin callback to trigger import/export because WordPress admin routing lol
     242    */
     243    public function trigger_cron() {
     244        if ( ! current_user_can( 'manage_options' ) ) {
     245            return;
     246        }
     247
     248        if ( get_current_screen()->id !== 'settings_page_' . Writing_On_GitHub::$text_domain ) {
     249            return;
     250        }
     251
     252        if ( ! isset( $_GET['action'] ) ) {
     253            return;
     254        }
     255
     256        if ( 'export' === $_GET['action'] ) {
     257            Writing_On_GitHub::$instance->start_export();
     258        }
    223259
    224260        if ( 'force_export' === $_GET['action'] ) {
     
    226262        }
    227263
    228         if ( 'import' === $_GET['action'] ) {
    229             Writing_On_GitHub::$instance->start_import();
    230         }
    231 
    232         wp_redirect( admin_url( 'options-general.php?page=writing-on-github' ) );
    233         die;
    234     }
     264        if ( 'import' === $_GET['action'] ) {
     265            Writing_On_GitHub::$instance->start_import();
     266        }
     267
     268        wp_redirect( admin_url( 'options-general.php?page=writing-on-github' ) );
     269        die;
     270    }
    235271}
  • writing-on-github/trunk/lib/api.php

    r1709881 r1713007  
    1010class Writing_On_GitHub_Api {
    1111
    12     /**
    13     * Application container.
    14     *
    15     * @var Writing_On_GitHub
    16     */
    17     protected $app;
     12    /**
     13    * Application container.
     14    *
     15    * @var Writing_On_GitHub
     16    */
     17    protected $app;
    1818
    19     /**
    20     * GitHub fetch client.
    21     *
    22     * @var Writing_On_GitHub_Fetch_Client
    23     */
    24     protected $fetch;
     19    /**
     20    * GitHub fetch client.
     21    *
     22    * @var Writing_On_GitHub_Fetch_Client
     23    */
     24    protected $fetch;
    2525
    26     /**
    27     * Github persist client.
    28     *
    29     * @var Writing_On_GitHub_Persist_Client
    30     */
    31     protected $persist;
     26    /**
     27    * Github persist client.
     28    *
     29    * @var Writing_On_GitHub_Persist_Client
     30    */
     31    protected $persist;
    3232
    33     /**
    34     * Instantiates a new Api object.
    35     *
    36     * @param Writing_On_GitHub $app Application container.
    37     */
    38     public function __construct( Writing_On_GitHub $app ) {
    39         $this->app = $app;
    40     }
     33    /**
     34    * Instantiates a new Api object.
     35    *
     36    * @param Writing_On_GitHub $app Application container.
     37    */
     38    public function __construct( Writing_On_GitHub $app ) {
     39        $this->app = $app;
     40    }
    4141
    42     /**
    43     * Lazy-load fetch client.
    44     *
    45     * @return Writing_On_GitHub_Fetch_Client
    46     */
    47     public function fetch() {
    48         if ( ! $this->fetch ) {
    49             $this->fetch = new Writing_On_GitHub_Fetch_Client( $this->app );
    50         }
     42    /**
     43    * Lazy-load fetch client.
     44    *
     45    * @return Writing_On_GitHub_Fetch_Client
     46    */
     47    public function fetch() {
     48        if ( ! $this->fetch ) {
     49            $this->fetch = new Writing_On_GitHub_Fetch_Client( $this->app );
     50        }
    5151
    52         return $this->fetch;
    53     }
     52        return $this->fetch;
     53    }
    5454
    55     /**
    56     * Lazy-load persist client.
    57     *
    58     * @return Writing_On_GitHub_Persist_Client
    59     */
    60     public function persist() {
    61         if ( ! $this->persist ) {
    62             $this->persist = new Writing_On_GitHub_Persist_Client( $this->app );
    63         }
     55    /**
     56    * Lazy-load persist client.
     57    *
     58    * @return Writing_On_GitHub_Persist_Client
     59    */
     60    public function persist() {
     61        if ( ! $this->persist ) {
     62            $this->persist = new Writing_On_GitHub_Persist_Client( $this->app );
     63        }
    6464
    65         return $this->persist;
    66     }
     65        return $this->persist;
     66    }
    6767}
  • writing-on-github/trunk/lib/blob.php

    r1709881 r1713007  
    1010class Writing_On_GitHub_Blob {
    1111
    12     /**
    13      * Complete blob content.
    14      *
    15      * @var string
    16      */
    17     protected $content;
    18 
    19     /**
    20      * Blob sha.
    21      *
    22      * @var string
    23      */
    24     protected $sha;
    25 
    26     /**
    27      * Blob path.
    28      *
    29      * @var string
    30      */
    31     protected $path;
    32 
    33     /**
    34      * Post id.
    35      *
    36      * @var int
    37      */
    38     protected $id;
    39 
    40     /**
    41      * Whether the blob has frontmatter.
    42      *
    43      * @var boolean
    44      */
    45     protected $frontmatter = false;
    46 
    47     /**
    48      * Instantiates a new Blob object.
    49      *
    50      * @param stdClass $data Raw blob data.
    51      */
    52     public function __construct( stdClass $data ) {
    53         $this->interpret_data( $data );
    54     }
    55 
    56     public function id() {
    57         return $this->id;
    58     }
    59 
    60     public function set_id($id) {
    61         $this->id = $id;
    62     }
    63 
    64     /**
    65      * Returns the raw blob content.
    66      *
    67      * @return string
    68      */
    69     public function content() {
    70         return $this->content;
    71     }
    72 
    73     /**
    74      * Set's the blob's content.
    75      *
    76      * @param string $content Raw blob content.
    77      * @param bool   $base64 Whether the content is base64 encoded.
    78      *
    79      * @return $this
    80      */
    81     public function set_content( $content, $base64 = false ) {
    82         if ( $base64 ) {
    83             $content = base64_decode( $content );
    84         }
    85 
    86         $this->frontmatter = '---' === substr( $this->content = $content, 0, 3 ) ? true : false;
    87 
    88         return $this;
    89     }
    90     /**
    91      * Returns the blob sha.
    92      *
    93      * @return string
    94      */
    95     public function sha() {
    96         return $this->sha;
    97     }
    98 
    99     /**
    100      * Return's the blob path.
    101      *
    102      * @return string
    103      */
    104     public function path() {
    105         return $this->path;
    106     }
    107 
    108     /**
    109      * Whether the blob has frontmatter.
    110      *
    111      * @return bool
    112      */
    113     public function has_frontmatter() {
    114         return $this->frontmatter;
    115     }
    116 
    117     /**
    118      * Returns the formatted/filtered blob content used for import.
    119      *
    120      * @return string
    121      */
    122     public function content_import() {
    123         $content = $this->content();
    124 
    125         if ( $this->has_frontmatter() ) {
    126             // Break out content.
    127             preg_match( '/(^---(.*?)---$)?(.*)/ms', $content, $matches );
    128             $content = array_pop( $matches );
    129         }
    130 
    131         if ( function_exists( 'wpmarkdown_markdown_to_html' ) ) {
    132             $content = wpmarkdown_markdown_to_html( $content );
    133         }
    134 
    135         /**
    136          * Filters the content for import.
    137          */
    138         return apply_filters( 'wogh_content_import', trim( $content ) );
    139     }
    140 
    141     /**
    142      * Returns the blob meta.
    143      *
    144      * @return array
    145      */
    146     public function meta() {
    147         $meta = array();
    148 
    149         if ( $this->has_frontmatter() ) {
    150             // Break out meta, if present.
    151             preg_match( '/(^---(.*?)---$)?(.*)/ms', $this->content(), $matches );
    152             array_pop( $matches );
    153 
    154             $meta = spyc_load( $matches[2] );
     12    /**
     13     * Complete blob content.
     14     *
     15     * @var string
     16     */
     17    protected $content;
     18
     19    /**
     20     * Blob sha.
     21     *
     22     * @var string
     23     */
     24    protected $sha;
     25
     26    /**
     27     * Blob path.
     28     *
     29     * @var string
     30     */
     31    protected $path;
     32
     33    /**
     34     * Post id.
     35     *
     36     * @var int
     37     */
     38    protected $id;
     39
     40    /**
     41     * Whether the blob has frontmatter.
     42     *
     43     * @var boolean
     44     */
     45    protected $frontmatter = false;
     46
     47    /**
     48     * The front matter of github post
     49     * @var string
     50     */
     51    protected $front_matter = '';
     52
     53    /**
     54     * Content without front matter
     55     * @var string
     56     */
     57    protected $post_content;
     58
     59    /**
     60     * Instantiates a new Blob object.
     61     *
     62     * @param stdClass $data Raw blob data.
     63     */
     64    public function __construct( stdClass $data ) {
     65        $this->interpret_data( $data );
     66    }
     67
     68    public function id() {
     69        return $this->id;
     70    }
     71
     72    public function set_id($id) {
     73        $this->id = $id;
     74    }
     75
     76    /**
     77     * Returns the raw blob content.
     78     *
     79     * @return string
     80     */
     81    public function content() {
     82        return $this->content;
     83    }
     84
     85    /**
     86     * Set's the blob's content.
     87     *
     88     * @param string $content Raw blob content.
     89     * @param bool   $base64 Whether the content is base64 encoded.
     90     *
     91     * @return $this
     92     */
     93    public function set_content( $content, $base64 = false ) {
     94        if ( $base64 ) {
     95            $content = base64_decode( $content );
     96        }
     97
     98        // remove whitespace from the beginning of content,
     99        // To prevent blank lines before yml
     100        $this->content = ltrim( $content );
     101
     102        $this->frontmatter = '---' === substr( $this->content, 0, 3 );
     103
     104        return $this;
     105    }
     106    /**
     107     * Returns the blob sha.
     108     *
     109     * @return string
     110     */
     111    public function sha() {
     112        return $this->sha;
     113    }
     114
     115    /**
     116     * Return's the blob path.
     117     *
     118     * @return string
     119     */
     120    public function path() {
     121        return $this->path;
     122    }
     123
     124    /**
     125     * Whether the blob has frontmatter.
     126     *
     127     * @return bool
     128     */
     129    public function has_frontmatter() {
     130        return $this->frontmatter;
     131    }
     132
     133    /**
     134     * The front matter of github post
     135     * @return string
     136     */
     137    public function front_matter() {
     138        return $this->front_matter;
     139    }
     140
     141    /**
     142     * Content without front matter
     143     * @return string
     144     */
     145    public function post_content() {
     146        if ( ! $this->post_content ) {
     147            $this->content_import();
     148        }
     149        return $this->post_content;
     150    }
     151
     152    /**
     153     * Returns the formatted/filtered blob content used for import.
     154     *
     155     * @return string
     156     */
     157    public function content_import() {
     158        $this->post_content = $content = $this->content();
     159
     160        if ( $this->has_frontmatter() ) {
     161            // Break out content.
     162            preg_match( '/(^---(.*?)---$(\r\n|\n|\r)?)?(.*)/ms', $content, $matches );
     163            $this->front_matter = $matches[1];
     164            $this->post_content = $content = array_pop( $matches );
     165        }
     166
     167        if ( function_exists( 'wpmarkdown_markdown_to_html' ) ) {
     168            $content = wpmarkdown_markdown_to_html( $content );
     169        }
     170
     171        /**
     172         * Filters the content for import.
     173         */
     174        return apply_filters( 'wogh_content_import', trim( $content ) );
     175    }
     176
     177    /**
     178     * Returns the blob meta.
     179     *
     180     * @return array
     181     */
     182    public function meta() {
     183        $meta = array();
     184
     185        if ( $this->has_frontmatter() ) {
     186            // Break out meta, if present.
     187            preg_match( '/(^---(.*?)---$)?(.*)/ms', $this->content(), $matches );
     188            array_pop( $matches );
     189
     190            $meta = spyc_load( $matches[2] );
    155191            if ( 'yes' == get_option('wogh_ignore_author') ) {
    156192                unset($meta['author']);
    157193            }
    158             // if ( isset( $meta['link'] ) ) {
    159             //  $meta['link'] = str_replace( home_url(), '', $meta['link'] );
    160             // }
    161         }
    162 
    163         return $meta;
    164     }
    165 
    166     /**
    167     * Formats the blob into an API call body.
    168     *
    169     * @return stdClass
    170     */
    171     // public function to_body() {
    172     //  $data = new stdClass;
    173 
    174     //  $data->mode = '100644';
    175     //  $data->type = 'blob';
    176 
    177     //  $data->path = $this->path();
    178 
    179     //  if ( $this->sha() ) {
    180     //      $data->sha = $this->sha();
    181     //  } else {
    182     //      $data->content = $this->content();
    183     //  }
    184 
    185     //  return $data;
    186     // }
    187 
    188 
    189     /**
    190     * Formats the blob into an API call body.
    191     *
    192     * @return stdClass
    193     */
    194     public function to_body() {
    195         $data = new stdClass;
    196 
    197         // $data->mode = '100644';
    198         // $data->type = 'blob';
    199 
    200         $data->path = $this->path();
    201         $data->content = base64_encode( $this->content() );
    202         $data->sha = $this->sha;
    203 
    204         return $data;
    205     }
    206 
    207     /**
    208     * Interprets the blob's data into properties.
    209     */
    210     protected function interpret_data( $data ) {
    211         $this->sha  = isset( $data->sha  ) ? $data->sha  : '';
    212         $this->path = isset( $data->path ) ? $data->path : '';
    213 
    214         $this->set_content(
    215             isset( $data->content ) ? trim( $data->content ) : '',
    216             isset( $data->encoding ) && 'base64' === $data->encoding ? true : false
    217         );
    218     }
     194            // if ( isset( $meta['link'] ) ) {
     195            //  $meta['link'] = str_replace( home_url(), '', $meta['link'] );
     196            // }
     197        }
     198
     199        return $meta;
     200    }
     201
     202    /**
     203    * Formats the blob into an API call body.
     204    *
     205    * @return stdClass
     206    */
     207    // public function to_body() {
     208    //  $data = new stdClass;
     209
     210    //  $data->mode = '100644';
     211    //  $data->type = 'blob';
     212
     213    //  $data->path = $this->path();
     214
     215    //  if ( $this->sha() ) {
     216    //      $data->sha = $this->sha();
     217    //  } else {
     218    //      $data->content = $this->content();
     219    //  }
     220
     221    //  return $data;
     222    // }
     223
     224
     225    /**
     226    * Formats the blob into an API call body.
     227    *
     228    * @return stdClass
     229    */
     230    public function to_body() {
     231        $data = new stdClass;
     232
     233        // $data->mode = '100644';
     234        // $data->type = 'blob';
     235
     236        $data->path = $this->path();
     237        $data->content = base64_encode( $this->content() );
     238        $data->sha = $this->sha;
     239
     240        return $data;
     241    }
     242
     243    /**
     244    * Interprets the blob's data into properties.
     245    */
     246    protected function interpret_data( $data ) {
     247        $this->sha  = isset( $data->sha  ) ? $data->sha  : '';
     248        $this->path = isset( $data->path ) ? $data->path : '';
     249
     250        $this->set_content(
     251            isset( $data->content ) ? $data->content : '',
     252            isset( $data->encoding ) && 'base64' === $data->encoding ? true : false
     253        );
     254    }
    219255}
  • writing-on-github/trunk/lib/cli.php

    r1709881 r1713007  
    1010class Writing_On_GitHub_CLI extends WP_CLI_Command {
    1111
    12     /**
    13     * Application container.
    14     *
    15     * @var Writing_On_GitHub
    16     */
    17     protected $app;
     12    /**
     13    * Application container.
     14    *
     15    * @var Writing_On_GitHub
     16    */
     17    protected $app;
    1818
    19     /**
    20     * Grab the Application container on instantiation.
    21     */
    22     public function __construct() {
    23         $this->app = Writing_On_GitHub::$instance;
    24     }
     19    /**
     20    * Grab the Application container on instantiation.
     21    */
     22    public function __construct() {
     23        $this->app = Writing_On_GitHub::$instance;
     24    }
    2525
    26     /**
    27     * Exports an individual post
    28     * all your posts to GitHub
    29     *
    30     * ## OPTIONS
    31     *
    32     * <post_id|all>
    33     * : The post ID to export or 'all' for full site
    34     *
    35     * <user_id>
    36     * : The user ID you'd like to save the commit as
    37     *
    38     * ## EXAMPLES
    39     *
    40     *     wp wogh export all 1
    41     *     wp wogh export 1 1
    42     *
    43     * @synopsis <post_id|all> <user_id>
    44     *
    45     * @param array $args Command arguments.
    46     */
    47     public function export( $args ) {
    48         list( $post_id, $user_id ) = $args;
     26    /**
     27    * Exports an individual post
     28    * all your posts to GitHub
     29    *
     30    * ## OPTIONS
     31    *
     32    * <post_id|all>
     33    * : The post ID to export or 'all' for full site
     34    *
     35    * <user_id>
     36    * : The user ID you'd like to save the commit as
     37    *
     38    * ## EXAMPLES
     39    *
     40    *     wp wogh export all 1
     41    *     wp wogh export 1 1
     42    *
     43    * @synopsis <post_id|all> <user_id>
     44    *
     45    * @param array $args Command arguments.
     46    */
     47    public function export( $args ) {
     48        list( $post_id, $user_id ) = $args;
    4949
    50         if ( ! is_numeric( $user_id ) ) {
    51             WP_CLI::error( __( 'Invalid user ID', 'writing-on-github' ) );
    52         }
     50        if ( ! is_numeric( $user_id ) ) {
     51            WP_CLI::error( __( 'Invalid user ID', 'writing-on-github' ) );
     52        }
    5353
    54         $this->app->export()->set_user( $user_id );
     54        $this->app->export()->set_user( $user_id );
    5555
    56         if ( 'all' === $post_id ) {
    57             WP_CLI::line( __( 'Starting full export to GitHub.', 'writing-on-github' ) );
    58             $this->app->controller()->export_all();
    59         } elseif ( is_numeric( $post_id ) ) {
    60             WP_CLI::line(
    61                 sprintf(
    62                     __( 'Exporting post ID to GitHub: %d', 'writing-on-github' ),
    63                     $post_id
    64                 )
    65             );
    66             $this->app->controller()->export_post( (int) $post_id );
    67         } else {
    68             WP_CLI::error( __( 'Invalid post ID', 'writing-on-github' ) );
    69         }
    70     }
     56        if ( 'all' === $post_id ) {
     57            WP_CLI::line( __( 'Starting full export to GitHub.', 'writing-on-github' ) );
     58            $this->app->controller()->export_all();
     59        } elseif ( is_numeric( $post_id ) ) {
     60            WP_CLI::line(
     61                sprintf(
     62                    __( 'Exporting post ID to GitHub: %d', 'writing-on-github' ),
     63                    $post_id
     64                )
     65            );
     66            $this->app->controller()->export_post( (int) $post_id );
     67        } else {
     68            WP_CLI::error( __( 'Invalid post ID', 'writing-on-github' ) );
     69        }
     70    }
    7171
    72     /**
    73     * Imports the post in your GitHub repo
    74     * into your WordPress blog
    75     *
    76     * ## OPTIONS
    77     *
    78     * <user_id>
    79     * : The user ID you'd like to save the commit as
    80     *
    81     * ## EXAMPLES
    82     *
    83     *     wp wogh import 1
    84     *
    85     * @synopsis <user_id>
    86     *
    87     * @param array $args Command arguments.
    88     */
    89     public function import( $args ) {
    90         list( $user_id ) = $args;
     72    /**
     73    * Imports the post in your GitHub repo
     74    * into your WordPress blog
     75    *
     76    * ## OPTIONS
     77    *
     78    * <user_id>
     79    * : The user ID you'd like to save the commit as
     80    *
     81    * ## EXAMPLES
     82    *
     83    *     wp wogh import 1
     84    *
     85    * @synopsis <user_id>
     86    *
     87    * @param array $args Command arguments.
     88    */
     89    public function import( $args ) {
     90        list( $user_id ) = $args;
    9191
    92         if ( ! is_numeric( $user_id ) ) {
    93             WP_CLI::error( __( 'Invalid user ID', 'writing-on-github' ) );
    94         }
     92        if ( ! is_numeric( $user_id ) ) {
     93            WP_CLI::error( __( 'Invalid user ID', 'writing-on-github' ) );
     94        }
    9595
    96         update_option( '_wogh_export_user_id', (int) $user_id );
     96        update_option( '_wogh_export_user_id', (int) $user_id );
    9797
    98         WP_CLI::line( __( 'Starting import from GitHub.', 'writing-on-github' ) );
     98        WP_CLI::line( __( 'Starting import from GitHub.', 'writing-on-github' ) );
    9999
    100         $this->app->controller()->import_master();
    101     }
     100        $this->app->controller()->import_master();
     101    }
    102102
    103     /**
    104     * Fetches the provided sha or the repository's
    105     * master branch and caches it.
    106     *
    107     * ## OPTIONS
    108     *
    109     * <user_id>
    110     * : The user ID you'd like to save the commit as
    111     *
    112     * ## EXAMPLES
    113     *
    114     *     wp wogh prime --branch=master
    115     *     wp wogh prime --sha=<commit_sha>
    116     *
    117     * @synopsis [--sha=<commit_sha>] [--branch]
    118     *
    119     * @param array $args Command arguments.
    120     * @param array $assoc_args Command associated arguments.
    121     */
    122     public function prime( $args, $assoc_args ) {
    123         if ( isset( $assoc_args['branch'] ) ) {
    124             WP_CLI::line( __( 'Starting branch import.', 'writing-on-github' ) );
     103    /**
     104    * Fetches the provided sha or the repository's
     105    * master branch and caches it.
     106    *
     107    * ## OPTIONS
     108    *
     109    * <user_id>
     110    * : The user ID you'd like to save the commit as
     111    *
     112    * ## EXAMPLES
     113    *
     114    *     wp wogh prime --branch=master
     115    *     wp wogh prime --sha=<commit_sha>
     116    *
     117    * @synopsis [--sha=<commit_sha>] [--branch]
     118    *
     119    * @param array $args Command arguments.
     120    * @param array $assoc_args Command associated arguments.
     121    */
     122    public function prime( $args, $assoc_args ) {
     123        if ( isset( $assoc_args['branch'] ) ) {
     124            WP_CLI::line( __( 'Starting branch import.', 'writing-on-github' ) );
    125125
    126             $commit = $this->app->api()->fetch()->master();
     126            $commit = $this->app->api()->fetch()->master();
    127127
    128             if ( is_wp_error( $commit ) ) {
    129                 WP_CLI::error(
    130                     sprintf(
    131                         __( 'Failed to import and cache branch with error: %s', 'writing-on-github' ),
    132                         $commit->get_error_message()
    133                     )
    134                 );
    135             } else {
    136                 WP_CLI::success(
    137                     sprintf(
    138                         __( 'Successfully imported and cached commit %s from branch.', 'writing-on-github' ),
    139                         $commit->sha()
    140                     )
    141                 );
    142             }
    143         } else if ( isset( $assoc_args['sha'] ) ) {
    144             WP_CLI::line( 'Starting sha import.' );
     128            if ( is_wp_error( $commit ) ) {
     129                WP_CLI::error(
     130                    sprintf(
     131                        __( 'Failed to import and cache branch with error: %s', 'writing-on-github' ),
     132                        $commit->get_error_message()
     133                    )
     134                );
     135            } else {
     136                WP_CLI::success(
     137                    sprintf(
     138                        __( 'Successfully imported and cached commit %s from branch.', 'writing-on-github' ),
     139                        $commit->sha()
     140                    )
     141                );
     142            }
     143        } else if ( isset( $assoc_args['sha'] ) ) {
     144            WP_CLI::line( 'Starting sha import.' );
    145145
    146             $commit = $this->app->api()->fetch()->commit( $assoc_args['sha'] );
     146            $commit = $this->app->api()->fetch()->commit( $assoc_args['sha'] );
    147147
    148             WP_CLI::success(
    149                 sprintf(
    150                     __( 'Successfully imported and cached commit %s.', 'writing-on-github' ),
    151                     $commit->sha()
    152                 )
    153             );
    154         } else {
    155             WP_CLI::error( 'Invalid fetch.' );
    156         }
    157     }
     148            WP_CLI::success(
     149                sprintf(
     150                    __( 'Successfully imported and cached commit %s.', 'writing-on-github' ),
     151                    $commit->sha()
     152                )
     153            );
     154        } else {
     155            WP_CLI::error( 'Invalid fetch.' );
     156        }
     157    }
    158158}
  • writing-on-github/trunk/lib/client/base.php

    r1709881 r1713007  
    1010class Writing_On_GitHub_Base_Client {
    1111
    12     const HOST_OPTION_KEY   = 'wogh_host';
    13     const TOKEN_OPTION_KEY  = 'wogh_oauth_token';
    14     const REPO_OPTION_KEY   = 'wogh_repository';
    15     const BRANCH_OPTION_KEY = 'wogh_branch';
    16 
    17     /**
    18      * Application container.
    19      *
    20      * @var Writing_On_GitHub
    21      */
    22     protected $app;
    23 
    24     /**
    25      * Instantiates a new Api object.
    26      *
    27      * @param Writing_On_GitHub $app Application container.
    28      */
    29     public function __construct( Writing_On_GitHub $app ) {
    30         $this->app = $app;
    31     }
    32 
    33     /**
    34      * Generic GitHub API interface and response handler
    35      *
    36      * @param string $method HTTP method.
    37      * @param string $endpoint API endpoint.
    38      * @param array  $body Request body.
    39      *
    40      * @return stdClass|WP_Error
    41      */
    42     protected function call( $method, $endpoint, $body = array() ) {
    43         if ( is_wp_error( $error = $this->can_call() ) ) {
    44             return $error;
    45         }
    46 
    47         $args = array(
    48             'method'  => $method,
    49             'headers' => array(
    50                 'Authorization' => 'token ' . $this->oauth_token(),
    51             ),
    52         );
    53 
    54         if ( 'GET' !== $method ) {
    55             $args['body'] = function_exists( 'wp_json_encode' ) ?
    56                 wp_json_encode( $body ) :
    57                 json_encode( $body );
    58         }
    59 
    60         $tmpbody = isset($args['body']) ? $args['body'] : '';
    61         error_log("writing-on-github-call $method $endpoint $tmpbody");
    62 
    63         $response = wp_remote_request( $endpoint, $args );
    64         $status   = wp_remote_retrieve_header( $response, 'status' );
    65         $body     = json_decode( wp_remote_retrieve_body( $response ) );
    66 
    67         if ( '2' !== substr( $status, 0, 1 ) && '3' !== substr( $status, 0, 1 ) ) {
    68             return new WP_Error(
    69                 strtolower( str_replace( ' ', '_', $status ) ),
    70                 sprintf(
    71                     __( 'Method %s to endpoint %s failed with error: %s', 'writing-on-github' ),
    72                     $method,
    73                     $endpoint,
    74                     $body && $body->message ? $body->message : 'Unknown error'
    75                 )
    76             );
    77         }
    78 
    79         return $body;
    80     }
    81 
    82     /**
    83      * Validates whether the Api object can make a call.
    84      *
    85      * @return true|WP_Error
    86      */
    87     protected function can_call() {
    88         if ( ! $this->oauth_token() ) {
    89             return new WP_Error(
    90                 'missing_token',
    91                 __( 'Writing On GitHub needs an auth token. Please update your settings.', 'writing-on-github' )
    92             );
    93         }
    94 
    95         $repo = $this->repository();
    96 
    97         if ( ! $repo ) {
    98             return new WP_Error(
    99                 'missing_repository',
    100                 __( 'Writing On GitHub needs a repository. Please update your settings.', 'writing-on-github' )
    101             );
    102         }
    103 
    104         $parts = explode( '/', $repo );
    105 
    106         if ( 2 !== count( $parts ) ) {
    107             return new WP_Error(
    108                 'malformed_repository',
    109                 __( 'Writing On GitHub needs a properly formed repository. Please update your settings.', 'writing-on-github' )
    110             );
    111         }
    112 
    113         return true;
    114     }
    115 
    116     /**
    117      * Returns the repository to sync with
    118      *
    119      * @return string
    120      */
    121     public function repository() {
    122         return (string) get_option( self::REPO_OPTION_KEY );
    123     }
    124 
    125     /**
    126      * Returns the user's oauth token
    127      *
    128      * @return string
    129      */
    130     public function oauth_token() {
    131         return (string) get_option( self::TOKEN_OPTION_KEY );
    132     }
    133 
    134     /**
    135      * Returns the GitHub host to sync with (for GitHub Enterprise support)
    136      */
    137     public function api_base() {
    138         return get_option( self::HOST_OPTION_KEY );
    139     }
    140 
    141     public function branch() {
    142         $branch = get_option( self::BRANCH_OPTION_KEY );
    143         return $branch ? $branch : 'master';
    144     }
    145 
    146     /**
    147      * API endpoint for the master branch reference
    148      */
    149     public function reference_endpoint() {
    150         $url = $this->api_base() . '/repos/';
    151         $url = $url . $this->repository() . '/git/refs/heads/' . $this->branch();
    152 
    153         return $url;
    154     }
    155 
    156     /**
    157      * Api to get and create commits
    158      */
    159     public function commit_endpoint() {
    160         $url = $this->api_base() . '/repos/';
    161         $url = $url . $this->repository() . '/git/commits';
    162 
    163         return $url;
    164     }
    165 
    166     /**
    167      * Api to compare commits
    168      */
    169     public function compare_endpoint() {
    170         $url = $this->api_base() . '/repos/';
    171         $url = $url . $this->repository() . '/compare';
    172 
    173         return $url;
    174     }
    175 
    176     /**
    177      * Api to get and create trees
    178      */
    179     public function tree_endpoint() {
    180         $url = $this->api_base() . '/repos/';
    181         $url = $url . $this->repository() . '/git/trees';
    182 
    183         return $url;
    184     }
    185 
    186     /**
    187      * Builds the proper blob API endpoint for a given post
    188      *
    189      * Returns String the relative API call path
    190      */
    191     public function blob_endpoint() {
    192         $url = $this->api_base() . '/repos/';
    193         $url = $url . $this->repository() . '/git/blobs';
    194 
    195         return $url;
    196     }
    197 
    198     /**
    199      * Builds the proper content API endpoint for a given post
    200      *
    201      * Returns String the relative API call path
    202      */
    203     public function content_endpoint( $path = false ) {
    204         $url = $this->api_base() . '/repos/';
    205         $url = $url . $this->repository() . '/contents';
    206 
    207         if ( ! empty($path) ) {
    208             $url .= '/' . $path;
    209         }
    210 
    211         return $url;
    212     }
     12    const HOST_OPTION_KEY   = 'wogh_host';
     13    const TOKEN_OPTION_KEY  = 'wogh_oauth_token';
     14    const REPO_OPTION_KEY   = 'wogh_repository';
     15    const BRANCH_OPTION_KEY = 'wogh_branch';
     16
     17    /**
     18     * Application container.
     19     *
     20     * @var Writing_On_GitHub
     21     */
     22    protected $app;
     23
     24    /**
     25     * Instantiates a new Api object.
     26     *
     27     * @param Writing_On_GitHub $app Application container.
     28     */
     29    public function __construct( Writing_On_GitHub $app ) {
     30        $this->app = $app;
     31    }
     32
     33    /**
     34     * Generic GitHub API interface and response handler
     35     *
     36     * @param string $method HTTP method.
     37     * @param string $endpoint API endpoint.
     38     * @param array  $body Request body.
     39     *
     40     * @return stdClass|WP_Error
     41     */
     42    protected function call( $method, $endpoint, $body = array() ) {
     43        if ( is_wp_error( $error = $this->can_call() ) ) {
     44            /* @var WP_Error $error */
     45            return $error;
     46        }
     47
     48        $args = array(
     49            'method'  => $method,
     50            'headers' => array(
     51                'Authorization' => 'token ' . $this->oauth_token(),
     52            ),
     53        );
     54
     55        if ( 'GET' !== $method ) {
     56            $args['body'] = json_encode( $body );
     57        }
     58
     59        // $tmpbody = isset( $args['body'] ) ? $args['body'] : '';
     60        // error_log( "writing-on-github-call $method $endpoint $tmpbody" );
     61
     62        $response = wp_remote_request( $endpoint, $args );
     63        $status   = wp_remote_retrieve_header( $response, 'status' );
     64        $body     = json_decode( wp_remote_retrieve_body( $response ) );
     65
     66        if ( '2' !== substr( $status, 0, 1 ) && '3' !== substr( $status, 0, 1 ) ) {
     67            return new WP_Error(
     68                strtolower( str_replace( ' ', '_', $status ) ),
     69                sprintf(
     70                    __( 'Method %s to endpoint %s failed with error: %s', 'writing-on-github' ),
     71                    $method,
     72                    $endpoint,
     73                    ( $body && $body->message ) ? $body->message : 'Unknown error'
     74                )
     75            );
     76        }
     77
     78        return $body;
     79    }
     80
     81    /**
     82     * Validates whether the Api object can make a call.
     83     *
     84     * @return true|WP_Error
     85     */
     86    protected function can_call() {
     87        if ( ! $this->oauth_token() ) {
     88            return new WP_Error(
     89                'missing_token',
     90                __( 'Writing On GitHub needs an auth token. Please update your settings.', 'writing-on-github' )
     91            );
     92        }
     93
     94        $repo = $this->repository();
     95
     96        if ( ! $repo ) {
     97            return new WP_Error(
     98                'missing_repository',
     99                __( 'Writing On GitHub needs a repository. Please update your settings.', 'writing-on-github' )
     100            );
     101        }
     102
     103        $parts = explode( '/', $repo );
     104
     105        if ( 2 !== count( $parts ) ) {
     106            return new WP_Error(
     107                'malformed_repository',
     108                __( 'Writing On GitHub needs a properly formed repository. Please update your settings.', 'writing-on-github' )
     109            );
     110        }
     111
     112        return true;
     113    }
     114
     115    /**
     116     * Returns the repository to sync with
     117     *
     118     * @return string
     119     */
     120    public function repository() {
     121        return (string) get_option( self::REPO_OPTION_KEY );
     122    }
     123
     124    /**
     125     * Returns the user's oauth token
     126     *
     127     * @return string
     128     */
     129    public function oauth_token() {
     130        return (string) get_option( self::TOKEN_OPTION_KEY );
     131    }
     132
     133    /**
     134     * Returns the GitHub host to sync with (for GitHub Enterprise support)
     135     */
     136    public function api_base() {
     137        return get_option( self::HOST_OPTION_KEY );
     138    }
     139
     140    public function branch() {
     141        $branch = get_option( self::BRANCH_OPTION_KEY );
     142        return $branch ? $branch : 'master';
     143    }
     144
     145    /**
     146     * API endpoint for the master branch reference
     147     */
     148    public function reference_endpoint() {
     149        $url = $this->api_base() . '/repos/';
     150        $url = $url . $this->repository() . '/git/refs/heads/' . $this->branch();
     151
     152        return $url;
     153    }
     154
     155    /**
     156     * Api to get and create commits
     157     */
     158    public function commit_endpoint() {
     159        $url = $this->api_base() . '/repos/';
     160        $url = $url . $this->repository() . '/git/commits';
     161
     162        return $url;
     163    }
     164
     165    /**
     166     * Api to compare commits
     167     */
     168    public function compare_endpoint() {
     169        $url = $this->api_base() . '/repos/';
     170        $url = $url . $this->repository() . '/compare';
     171
     172        return $url;
     173    }
     174
     175    /**
     176     * Api to get and create trees
     177     */
     178    public function tree_endpoint() {
     179        $url = $this->api_base() . '/repos/';
     180        $url = $url . $this->repository() . '/git/trees';
     181
     182        return $url;
     183    }
     184
     185    /**
     186     * Builds the proper blob API endpoint for a given post
     187     *
     188     * Returns String the relative API call path
     189     */
     190    public function blob_endpoint() {
     191        $url = $this->api_base() . '/repos/';
     192        $url = $url . $this->repository() . '/git/blobs';
     193
     194        return $url;
     195    }
     196
     197    /**
     198     * Builds the proper content API endpoint for a given post
     199     *
     200     * Returns String the relative API call path
     201     */
     202    public function content_endpoint( $path = false ) {
     203        $url = $this->api_base() . '/repos/';
     204        $url = $url . $this->repository() . '/contents';
     205
     206        if ( ! empty($path) ) {
     207            $url .= '/' . $path;
     208        }
     209
     210        return $url;
     211    }
    213212}
  • writing-on-github/trunk/lib/client/fetch.php

    r1709881 r1713007  
    1010class Writing_On_GitHub_Fetch_Client extends Writing_On_GitHub_Base_Client {
    1111
    12     /**
    13     * Compare a commit by sha with master from the GitHub API
    14     *
    15     * @param string $sha Sha for commit to retrieve.
    16     *
    17      * @return array[Writing_On_GitHub_File_Info]|WP_Error
    18     */
    19     public function compare( $sha ) {
    20         // https://api.github.com/repos/litefeel/testwpsync/compare/861f87e8851b8debb78db548269d29f8da4d94ac...master
    21         $endpoint = $this->compare_endpoint();
    22         $branch = $this->branch();
    23         $data = $this->call( 'GET', "$endpoint/$sha...$branch" );
     12    /**
     13    * Compare a commit by sha with master from the GitHub API
     14    *
     15    * @param string $sha Sha for commit to retrieve.
     16    *
     17     * @return Writing_On_GitHub_File_Info[]|WP_Error
     18    */
     19    public function compare( $sha ) {
     20        // https://api.github.com/repos/litefeel/testwpsync/compare/861f87e8851b8debb78db548269d29f8da4d94ac...master
     21        $endpoint = $this->compare_endpoint();
     22        $branch = $this->branch();
     23        $data = $this->call( 'GET', "$endpoint/$sha...$branch" );
    2424
    25         if ( is_wp_error( $data ) ) {
    26             return $data;
    27         }
     25        if ( is_wp_error( $data ) ) {
     26            return $data;
     27        }
    2828
    29         $files = array();
    30         foreach ($data->files as $file) {
    31             $file->path = $file->filename;
    32             $files[] = new Writing_On_GitHub_File_Info($file);
    33         }
     29        $files = array();
     30        foreach ($data->files as $file) {
     31            $file->path = $file->filename;
     32            $files[] = new Writing_On_GitHub_File_Info($file);
     33        }
    3434
    35         return $files;
    36     }
     35        return $files;
     36    }
    3737
    38     /**
    39     * Calls the content API to get the post's contents and metadata
    40     *
    41     * Returns Object the response from the API
    42     *
    43     * @param Writing_On_GitHub_Post $post Post to retrieve remote contents for.
    44     *
    45     * @return mixed
    46     */
    47     public function remote_contents( $post ) {
    48         return $this->call( 'GET', $this->content_endpoint( $post->github_path() ) );
    49     }
     38    /**
     39    * Calls the content API to get the post's contents and metadata
     40    *
     41    * Returns Object the response from the API
     42    *
     43    * @param Writing_On_GitHub_Post $post Post to retrieve remote contents for.
     44    *
     45    * @return mixed
     46    */
     47    public function remote_contents( $post ) {
     48        return $this->call( 'GET', $this->content_endpoint( $post->github_path() ) );
     49    }
    5050
    51     public function exists( $path ) {
    52         $result = $this->call( 'GET', $this->content_endpoint( $path ) );
    53         if ( is_wp_error( $result ) ) {
    54             return false;
    55         }
    56         return true;
    57     }
    5851
    59     /**
    60      * Retrieves a tree by sha recursively from the GitHub API
    61      *
    62      * @param string $sha Commit sha to retrieve tree from.
    63      *
    64      * @return Writing_On_GitHub_Tree|WP_Error
    65      */
    66     public function tree_recursive( $sha = '_default' ) {
    6752
    68         if ( '_default' === $sha ) {
    69             $sha = $this->branch();
    70         }
     53    public function exists( $path ) {
     54        $result = $this->call( 'GET', $this->content_endpoint( $path ) );
     55        if ( is_wp_error( $result ) ) {
     56            return false;
     57        }
     58        return true;
     59    }
    7160
    72         $data = $this->call( 'GET', $this->tree_endpoint() . '/' . $sha . '?recursive=1' );
     61    /**
     62     * Retrieves a tree by sha recursively from the GitHub API
     63     *
     64     * @param string $sha Commit sha to retrieve tree from.
     65     *
     66     * @return Writing_On_GitHub_File_Info[]|WP_Error
     67     */
     68    public function tree_recursive( $sha = '_default' ) {
    7369
    74         if ( is_wp_error( $data ) ) {
    75             return $data;
    76         }
     70        if ( '_default' === $sha ) {
     71            $sha = $this->branch();
     72        }
    7773
    78         $files = array();
     74        $data = $this->call( 'GET', $this->tree_endpoint() . '/' . $sha . '?recursive=1' );
    7975
    80         foreach ( $data->tree as $index => $thing ) {
    81             // We need to remove the trees because
    82             // the recursive tree includes both
    83             // the subtrees as well the subtrees' blobs.
    84             if ( 'blob' === $thing->type ) {
    85                 $thing->status = '';
    86                 $files[] = new Writing_On_GitHub_File_Info( $thing );
    87             }
    88         }
     76        if ( is_wp_error( $data ) ) {
     77            return $data;
     78        }
    8979
    90         return $files;
    91     }
     80        $files = array();
    9281
    93     /**
    94      * Retrieves the blob data for a given sha
    95      *
    96      * @param stdClass $blob Tree blob data.
    97      *
    98      * @return Writing_On_GitHub_Blob|WP_Error
    99      */
    100     public function blob( $blob ) {
    101         // if ( $cache = $this->app->cache()->fetch_blob( $blob->sha ) ) {
    102         //  return $cache;
    103         // }
     82        foreach ( $data->tree as $index => $thing ) {
     83            // We need to remove the trees because
     84            // the recursive tree includes both
     85            // the subtrees as well the subtrees' blobs.
     86            if ( 'blob' === $thing->type ) {
     87                $thing->status = '';
     88                $files[] = new Writing_On_GitHub_File_Info( $thing );
     89            }
     90        }
    10491
    105         $data = $this->call( 'GET', $this->blob_endpoint() . '/' . $blob->sha );
     92        return $files;
     93    }
    10694
    107         if ( is_wp_error( $data ) ) {
    108             return $data;
    109         }
     95    /**
     96     * Retrieves the blob data for a given sha
     97     *
     98     * @param Writing_On_GitHub_File_Info $fileinfo
     99     *
     100     * @return Writing_On_GitHub_Blob|WP_Error
     101     */
     102    public function blob( Writing_On_GitHub_File_Info $fileinfo ) {
     103        $data = $this->call( 'GET', $this->blob_endpoint() . '/' . $fileinfo->sha );
    110104
    111         $data->path = $blob->path;
    112         $obj = new Writing_On_GitHub_Blob( $data );
     105        if ( is_wp_error( $data ) ) {
     106            return $data;
     107        }
    113108
    114         return $obj;
    115         // return $this->app->cache()->set_blob( $obj->sha(), $obj );
    116     }
     109        $data->path = $fileinfo->path;
     110        return new Writing_On_GitHub_Blob( $data );
     111    }
     112
     113    /**
     114     * Get blob by path
     115     * @param  string $path
     116     * @return Writing_On_GitHub_Blob|WP_Error
     117     */
     118    public function blob_by_path( $path ) {
     119        $result = $this->call( 'GET', $this->content_endpoint( $path ) );
     120        if ( is_wp_error( $result ) ) {
     121            return $result;
     122        }
     123
     124        return new Writing_On_GitHub_Blob( $result );
     125    }
    117126}
  • writing-on-github/trunk/lib/client/persist.php

    r1709881 r1713007  
    1010class Writing_On_GitHub_Persist_Client extends Writing_On_GitHub_Base_Client {
    1111
    12     /**
    13     * Get the data for the current user.
    14     *
    15     * @return array
    16     */
    17     protected function export_user() {
    18         $user_id = get_current_user_id();
    19         $user = get_userdata( $user_id );
     12    /**
     13    * Get the data for the current user.
     14    *
     15    * @return array
     16    */
     17    protected function export_user() {
     18        $user_id = get_current_user_id();
     19        $user = get_userdata( $user_id );
    2020
    21         if ( $user ) {
    22             return array(
    23                 'name'  => $user->display_name,
    24                 'email' => $user->user_email,
    25             );
    26         }
     21        if ( $user ) {
     22            return array(
     23                'name'  => $user->display_name,
     24                'email' => $user->user_email,
     25            );
     26        }
    2727
    28         return false;
    29     }
     28        return false;
     29    }
    3030
    31     /**
    32     * Delete the file.
    33     *
    34     * @return array
    35     */
    36     public function delete_file( $path, $sha, $message ) {
    37         $body = new stdClass();
    38         $body->message = $message;
    39         $body->sha = $sha;
    40         $body->branch = $this->branch();
     31    /**
     32    * Delete the file.
     33    *
     34    * @return array
     35    */
     36    public function delete_file( $path, $sha, $message ) {
     37        $body = new stdClass();
     38        $body->message = $message;
     39        $body->sha = $sha;
     40        $body->branch = $this->branch();
    4141
    42         if ( $author = $this->export_user() ) {
    43             $body->author = $author;
    44         }
     42        if ( $author = $this->export_user() ) {
     43            $body->author = $author;
     44        }
    4545
    46         return $this->call( 'DELETE', $this->content_endpoint( $path ), $body );
    47     }
     46        return $this->call( 'DELETE', $this->content_endpoint( $path ), $body );
     47    }
    4848
    49     /**
    50     * Create the file.
    51     *
    52     * @return array
    53     */
    54     public function create_file( $blob, $message ) {
    55         $body = $blob->to_body();
    56         $body->message = $message;
    57         $body->branch = $this->branch();
    58         unset($body->sha);
     49    /**
     50    * Create the file.
     51    *
     52    * @return array
     53    */
     54    public function create_file( $blob, $message ) {
     55        $body = $blob->to_body();
     56        $body->message = $message;
     57        $body->branch = $this->branch();
     58        unset($body->sha);
    5959
    60         if ( $author = $this->export_user() ) {
    61             $body->author = $author;
    62         }
     60        if ( $author = $this->export_user() ) {
     61            $body->author = $author;
     62        }
    6363
    64         return $this->call( 'PUT', $this->content_endpoint( $blob->path() ), $body );
    65     }
     64        return $this->call( 'PUT', $this->content_endpoint( $blob->path() ), $body );
     65    }
    6666
    67     /**
    68     * Update the file.
    69     *
    70     * @return array
    71     */
    72     public function update_file( $blob, $message ) {
    73         $body = $blob->to_body();
    74         $body->message = $message;
    75         $body->branch = $this->branch();
     67    /**
     68    * Update the file.
     69    *
     70    * @return array
     71    */
     72    public function update_file( $blob, $message ) {
     73        $body = $blob->to_body();
     74        $body->message = $message;
     75        $body->branch = $this->branch();
    7676
    77         if ( $author = $this->export_user() ) {
    78             $body->author = $author;
    79         }
     77        if ( $author = $this->export_user() ) {
     78            $body->author = $author;
     79        }
    8080
    81         return $this->call( 'PUT', $this->content_endpoint( $blob->path() ), $body );
    82     }
     81        return $this->call( 'PUT', $this->content_endpoint( $blob->path() ), $body );
     82    }
    8383}
  • writing-on-github/trunk/lib/controller.php

    r1709881 r1713007  
    1010class Writing_On_GitHub_Controller {
    1111
    12     /**
    13      * Application container.
    14      *
    15      * @var Writing_On_GitHub
    16      */
    17     public $app;
    18 
    19     /**
    20      * Instantiates a new Controller object
    21      *
    22      * @param Writing_On_GitHub $app Applicatio container.
    23      */
    24     public function __construct( Writing_On_GitHub $app ) {
    25         $this->app = $app;
    26     }
    27 
    28     /**
    29      * Webhook callback as triggered from GitHub push.
    30      *
    31      * Reads the Webhook payload and syncs posts as necessary.
    32      *
    33      * @return boolean
    34      */
    35     public function pull_posts() {
    36         $this->set_ajax();
    37         if ( ! $this->app->semaphore()->is_open() ) {
    38             return $this->app->response()->error( new WP_Error(
    39                 'semaphore_locked',
    40                 sprintf( __( '%s : Semaphore is locked, import/export already in progress.', 'writing-on-github' ), 'Controller::pull_posts()' )
    41             ) );
    42         }
    43 
    44         if ( ! $this->app->request()->is_secret_valid() ) {
    45             return $this->app->response()->error( new WP_Error(
    46                 'invalid_headers',
    47                 __( 'Failed to validate secret.', 'writing-on-github' )
    48             ) );
    49         }
    50 
    51         // ping
    52         if ( $this->app->request()->is_ping() ) {
    53             return $this->app->response()->success( __( 'Wordpress is ready.', 'writing-on-github' ) );
    54         }
    55 
    56         // push
    57         if ( ! $this->app->request()->is_push() ) {
    58             return $this->app->response()->error( new WP_Error(
    59                 'invalid_headers',
    60                 __( 'Failed to validate webhook event.', 'writing-on-github' )
    61             ) );
    62         }
    63         $payload = $this->app->request()->payload();
    64 
    65         if ( ! $payload->should_import() ) {
    66             return $this->app->response()->error( new WP_Error(
    67                 'invalid_payload',
    68                 sprintf(
    69                     __( "%s won't be imported.", 'writing-on-github' ),
    70                     strtolower( $payload->get_commit_id() ) ? : '[Missing Commit ID]'
    71                 )
    72             ) );
    73         }
    74 
    75         $this->app->semaphore()->lock();
    76         remove_action( 'save_post', array( $this, 'export_post' ) );
    77         remove_action( 'delete_post', array( $this, 'delete_post' ) );
    78 
    79         $result = $this->app->import()->payload( $payload );
    80 
    81         $this->app->semaphore()->unlock();
    82 
    83         if ( is_wp_error( $result ) ) {
    84             return $this->app->response()->error( $result );
    85         }
    86 
    87         return $this->app->response()->success( $result );
    88     }
    89 
    90     /**
    91      * Imports posts from the current master branch.
    92      *
    93      * @return boolean
    94      */
    95     public function import_master( $user_id ) {
    96         if ( ! $this->app->semaphore()->is_open() ) {
    97             return $this->app->response()->error( new WP_Error(
    98                 'semaphore_locked',
    99                 sprintf( __( '%s : Semaphore is locked, import/export already in progress.', 'writing-on-github' ), 'Controller::import_master()' )
    100             ) );
    101         }
    102 
    103         $this->app->semaphore()->lock();
    104         remove_action( 'save_post', array( $this, 'export_post' ) );
    105         remove_action( 'save_post', array( $this, 'delete_post' ) );
    106 
    107         if ( $user_id ) {
    108             wp_set_current_user( $user_id );
    109         }
    110 
    111         $result = $this->app->import()->master();
    112 
    113         $this->app->semaphore()->unlock();
    114 
    115         if ( is_wp_error( $result ) ) {
    116             update_option( '_wogh_import_error', $result->get_error_message() );
    117 
    118             return $this->app->response()->error( $result );
    119         }
    120 
    121         update_option( '_wogh_import_complete', 'yes' );
    122 
    123         return $this->app->response()->success( $result );
    124     }
    125 
    126     /**
    127      * Export all the posts in the database to GitHub.
    128      *
     12    /**
     13     * Application container.
     14     *
     15     * @var Writing_On_GitHub
     16     */
     17    public $app;
     18
     19    /**
     20     * Instantiates a new Controller object
     21     *
     22     * @param Writing_On_GitHub $app Applicatio container.
     23     */
     24    public function __construct( Writing_On_GitHub $app ) {
     25        $this->app = $app;
     26    }
     27
     28    /**
     29     * Webhook callback as triggered from GitHub push.
     30     *
     31     * Reads the Webhook payload and syncs posts as necessary.
     32     *
     33     * @return boolean
     34     */
     35    public function pull_posts() {
     36        $this->set_ajax();
     37        if ( ! $this->app->semaphore()->is_open() ) {
     38            return $this->app->response()->error( new WP_Error(
     39                'semaphore_locked',
     40                sprintf( __( '%s : Semaphore is locked, import/export already in progress.', 'writing-on-github' ), 'Controller::pull_posts()' )
     41            ) );
     42        }
     43
     44        if ( ! $this->app->request()->is_secret_valid() ) {
     45            return $this->app->response()->error( new WP_Error(
     46                'invalid_headers',
     47                __( 'Failed to validate secret.', 'writing-on-github' )
     48            ) );
     49        }
     50
     51        // ping
     52        if ( $this->app->request()->is_ping() ) {
     53            return $this->app->response()->success( __( 'Wordpress is ready.', 'writing-on-github' ) );
     54        }
     55
     56        // push
     57        if ( ! $this->app->request()->is_push() ) {
     58            return $this->app->response()->error( new WP_Error(
     59                'invalid_headers',
     60                __( 'Failed to validate webhook event.', 'writing-on-github' )
     61            ) );
     62        }
     63        $payload = $this->app->request()->payload();
     64
     65        if ( ! $payload->should_import() ) {
     66            return $this->app->response()->error( new WP_Error(
     67                'invalid_payload',
     68                sprintf(
     69                    __( "%s won't be imported.", 'writing-on-github' ),
     70                    strtolower( $payload->get_commit_id() ) ? : '[Missing Commit ID]'
     71                )
     72            ) );
     73        }
     74
     75        $this->app->semaphore()->lock();
     76        remove_action( 'save_post', array( $this, 'export_post' ) );
     77        remove_action( 'delete_post', array( $this, 'delete_post' ) );
     78
     79        $result = $this->app->import()->payload( $payload );
     80
     81        $this->app->semaphore()->unlock();
     82
     83        if ( is_wp_error( $result ) ) {
     84            /* @var WP_Error $result */
     85            return $this->app->response()->error( $result );
     86        }
     87
     88        return $this->app->response()->success( $result );
     89    }
     90
     91    /**
     92     * Imports posts from the current master branch.
     93     *
     94     * @return boolean
     95     */
     96    public function import_master( $user_id = 0 ) {
     97        if ( ! $this->app->semaphore()->is_open() ) {
     98            return $this->app->response()->error( new WP_Error(
     99                'semaphore_locked',
     100                sprintf( __( '%s : Semaphore is locked, import/export already in progress.', 'writing-on-github' ), 'Controller::import_master()' )
     101            ) );
     102        }
     103
     104        $this->app->semaphore()->lock();
     105        remove_action( 'save_post', array( $this, 'export_post' ) );
     106        remove_action( 'save_post', array( $this, 'delete_post' ) );
     107
     108        if ( $user_id ) {
     109            wp_set_current_user( $user_id );
     110        }
     111
     112        $result = $this->app->import()->master();
     113
     114        $this->app->semaphore()->unlock();
     115
     116        if ( is_wp_error( $result ) ) {
     117            /* @var WP_Error $result */
     118            update_option( '_wogh_import_error', $result->get_error_message() );
     119
     120            return $this->app->response()->error( $result );
     121        }
     122
     123        update_option( '_wogh_import_complete', 'yes' );
     124
     125        return $this->app->response()->success( $result );
     126    }
     127
     128    /**
     129     * Export all the posts in the database to GitHub.
     130     *
    129131     * @param  int        $user_id
    130132     * @param  boolean    $force
    131133     * @return boolean
    132134     */
    133     public function export_all( $user_id, $force = false ) {
    134         if ( ! $this->app->semaphore()->is_open() ) {
    135             return $this->app->response()->error( new WP_Error(
    136                 'semaphore_locked',
    137                 sprintf( __( '%s : Semaphore is locked, import/export already in progress.', 'writing-on-github' ), 'Controller::export_all()' )
    138             ) );
    139         }
    140 
    141         $this->app->semaphore()->lock();
    142 
    143         if ( $user_id ) {
    144             wp_set_current_user( $user_id );
    145         }
    146 
    147         $result = $this->app->export()->full($force);
    148         $this->app->semaphore()->unlock();
    149 
    150         // Maybe move option updating out of this class/upgrade message display?
    151         if ( is_wp_error( $result ) ) {
    152             update_option( '_wogh_export_error', $result->get_error_message() );
    153 
    154             return $this->app->response()->error( $result );
    155         } else {
    156             update_option( '_wogh_export_complete', 'yes' );
    157             update_option( '_wogh_fully_exported', 'yes' );
    158 
    159             return $this->app->response()->success( $result );
    160         }
    161     }
    162 
    163     /**
    164      * Exports a single post to GitHub by ID.
    165      *
    166      * Called on the save_post hook.
    167      *
    168      * @param int $post_id Post ID.
    169      *
    170      * @return boolean
    171      */
    172     public function export_post( $post_id ) {
    173         if ( wp_is_post_revision( $post_id ) ) {
    174             return;
    175         }
    176 
    177         if ( ! $this->app->semaphore()->is_open() ) {
    178             return $this->app->response()->error( new WP_Error(
    179                 'semaphore_locked',
    180                 sprintf( __( '%s : Semaphore is locked, import/export already in progress.', 'writing-on-github' ), 'Controller::export_post()' )
    181             ) );
    182         }
    183 
    184         $this->app->semaphore()->lock();
    185         $result = $this->app->export()->update( $post_id );
    186         $this->app->semaphore()->unlock();
    187 
    188         if ( is_wp_error( $result ) ) {
    189             return $this->app->response()->error( $result );
    190         }
    191 
    192         return $this->app->response()->success( $result );
    193     }
    194 
    195     /**
    196      * Removes the post from the tree.
    197      *
    198      * Called the delete_post hook.
    199      *
    200      * @param int $post_id Post ID.
    201      *
    202      * @return boolean
    203      */
    204     public function delete_post( $post_id ) {
    205         if ( wp_is_post_revision( $post_id ) ) {
    206             return;
    207         }
    208 
    209         if ( ! $this->app->semaphore()->is_open() ) {
    210             return $this->app->response()->error( new WP_Error(
    211                 'semaphore_locked',
    212                 sprintf( __( '%s : Semaphore is locked, import/export already in progress.', 'writing-on-github' ), 'Controller::delete_post()' )
    213             ) );
    214         }
    215 
    216         $this->app->semaphore()->lock();
    217         $result = $this->app->export()->delete( $post_id );
    218         $this->app->semaphore()->unlock();
    219 
    220         if ( is_wp_error( $result ) ) {
    221             return $this->app->response()->error( $result );
    222         }
    223 
    224         return $this->app->response()->success( $result );
    225     }
    226 
    227     /**
    228      * Indicates we're running our own AJAX hook
    229      * and thus should respond with JSON, rather
    230      * than just returning data.
    231      */
    232     protected function set_ajax() {
    233         if ( ! defined( 'WOGH_AJAX' ) ) {
    234             define( 'WOGH_AJAX', true );
    235         }
    236     }
     135    public function export_all( $user_id = 0, $force = false ) {
     136        if ( ! $this->app->semaphore()->is_open() ) {
     137            return $this->app->response()->error( new WP_Error(
     138                'semaphore_locked',
     139                sprintf( __( '%s : Semaphore is locked, import/export already in progress.', 'writing-on-github' ), 'Controller::export_all()' )
     140            ) );
     141        }
     142
     143        $this->app->semaphore()->lock();
     144
     145        if ( $user_id ) {
     146            wp_set_current_user( $user_id );
     147        }
     148
     149        $result = $this->app->export()->full($force);
     150        $this->app->semaphore()->unlock();
     151
     152        // Maybe move option updating out of this class/upgrade message display?
     153        if ( is_wp_error( $result ) ) {
     154            /* @var WP_Error $result */
     155            update_option( '_wogh_export_error', $result->get_error_message() );
     156
     157            return $this->app->response()->error( $result );
     158        } else {
     159            update_option( '_wogh_export_complete', 'yes' );
     160            update_option( '_wogh_fully_exported', 'yes' );
     161
     162            return $this->app->response()->success( $result );
     163        }
     164    }
     165
     166    /**
     167     * Exports a single post to GitHub by ID.
     168     *
     169     * Called on the save_post hook.
     170     *
     171     * @param int $post_id Post ID.
     172     *
     173     * @return boolean
     174     */
     175    public function export_post( $post_id ) {
     176        if ( wp_is_post_revision( $post_id ) ) {
     177            return;
     178        }
     179
     180        if ( ! $this->app->semaphore()->is_open() ) {
     181            return $this->app->response()->error( new WP_Error(
     182                'semaphore_locked',
     183                sprintf( __( '%s : Semaphore is locked, import/export already in progress.', 'writing-on-github' ), 'Controller::export_post()' )
     184            ) );
     185        }
     186
     187        $this->app->semaphore()->lock();
     188        $result = $this->app->export()->update( $post_id );
     189        $this->app->semaphore()->unlock();
     190
     191        if ( is_wp_error( $result ) ) {
     192            /* @var WP_Error $result */
     193            return $this->app->response()->error( $result );
     194        }
     195
     196        return $this->app->response()->success( $result );
     197    }
     198
     199    /**
     200     * Removes the post from the tree.
     201     *
     202     * Called the delete_post hook.
     203     *
     204     * @param int $post_id Post ID.
     205     *
     206     * @return boolean
     207     */
     208    public function delete_post( $post_id ) {
     209        if ( wp_is_post_revision( $post_id ) ) {
     210            return;
     211        }
     212
     213        if ( ! $this->app->semaphore()->is_open() ) {
     214            return $this->app->response()->error( new WP_Error(
     215                'semaphore_locked',
     216                sprintf( __( '%s : Semaphore is locked, import/export already in progress.', 'writing-on-github' ), 'Controller::delete_post()' )
     217            ) );
     218        }
     219
     220        $this->app->semaphore()->lock();
     221        $result = $this->app->export()->delete( $post_id );
     222        $this->app->semaphore()->unlock();
     223
     224        if ( is_wp_error( $result ) ) {
     225            /* @var WP_Error $result */
     226            return $this->app->response()->error( $result );
     227        }
     228
     229        return $this->app->response()->success( $result );
     230    }
     231
     232    /**
     233     * Indicates we're running our own AJAX hook
     234     * and thus should respond with JSON, rather
     235     * than just returning data.
     236     */
     237    protected function set_ajax() {
     238        if ( ! defined( 'WOGH_AJAX' ) ) {
     239            define( 'WOGH_AJAX', true );
     240        }
     241    }
    237242}
  • writing-on-github/trunk/lib/database.php

    r1709881 r1713007  
    1010class Writing_On_GitHub_Database {
    1111
    12     /**
    13     * Application container.
    14     *
    15     * @var Writing_On_GitHub
    16     */
    17     protected $app;
    18 
    19     /**
    20     * Currently whitelisted post types.
    21     *
    22     * @var array
    23     */
    24     protected $whitelisted_post_types = array( 'post', 'page' );
    25 
    26     /**
    27     * Currently whitelisted post statuses.
    28     *
    29     * @var array
    30     */
    31     protected $whitelisted_post_statuses = array( 'publish' );
    32 
    33     /**
    34     * Instantiates a new Database object.
    35     *
    36     * @param Writing_On_GitHub $app Application container.
    37     */
    38     public function __construct( Writing_On_GitHub $app ) {
    39         $this->app = $app;
    40     }
    41 
    42     /**
    43     * Queries the database for all of the supported posts.
    44     *
     12    /**
     13    * Application container.
     14    *
     15    * @var Writing_On_GitHub
     16    */
     17    protected $app;
     18
     19    /**
     20    * Currently whitelisted post types.
     21    *
     22    * @var array
     23    */
     24    protected $whitelisted_post_types = array( 'post', 'page' );
     25
     26    /**
     27    * Currently whitelisted post statuses.
     28    *
     29    * @var array
     30    */
     31    protected $whitelisted_post_statuses = array( 'publish' );
     32
     33    /**
     34    * Instantiates a new Database object.
     35    *
     36    * @param Writing_On_GitHub $app Application container.
     37    */
     38    public function __construct( Writing_On_GitHub $app ) {
     39        $this->app = $app;
     40    }
     41
     42    /**
     43    * Queries the database for all of the supported posts.
     44    *
    4545     * @param  bool $force
     46     *
    4647     * @return Writing_On_GitHub_Post[]|WP_Error
    4748     */
    48     public function fetch_all_supported( $force = false ) {
    49         $args  = array(
    50             'post_type'   => $this->get_whitelisted_post_types(),
    51             'post_status' => $this->get_whitelisted_post_statuses(),
    52             'nopaging'    => true,
    53             'fields'      => 'ids',
    54         );
    55 
    56         $query = new WP_Query( apply_filters( 'wogh_pre_fetch_all_supported', $args ) );
    57 
    58         $post_ids = $query->get_posts();
    59 
    60         if ( ! $post_ids ) {
    61             return new WP_Error(
    62                 'no_results',
    63                 __( 'Querying for supported posts returned no results.', 'writing-on-github' )
    64             );
    65         }
    66 
    67         $results = array();
    68         foreach ( $post_ids as $post_id ) {
    69             // Do not export posts that have already been exported
    70             if ( $force || ! get_post_meta( $post_id, '_wogh_sha', true ) ||
    71                  ! get_post_meta( $post_id, '_wogh_github_path', true) ) {
    72 
    73                 $results[] = new Writing_On_GitHub_Post( $post_id, $this->app->api() );
    74             }
    75         }
    76 
    77         return $results;
    78     }
    79 
    80     /**
    81      * Queries a post and returns it if it's supported.
    82      *
    83      * @param int $post_id Post ID to fetch.
    84      *
    85      * @return WP_Error|Writing_On_GitHub_Post
    86      */
    87     public function fetch_by_id( $post_id ) {
    88         $post = new Writing_On_GitHub_Post( $post_id, $this->app->api() );
    89 
    90         if ( ! $this->is_post_supported( $post ) ) {
    91             return new WP_Error(
    92                 'unsupported_post',
    93                 sprintf(
    94                     __(
    95                         'Post ID %s is not supported by WOGH. See wiki to find out how to add support.',
    96                         'writing-on-github'
    97                     ),
    98                     $post_id
    99                 )
    100             );
    101         }
    102 
    103         return $post;
    104     }
    105 
    106     /**
    107      * Saves an array of Post objects to the database
    108      * and associates their author as well as their latest
    109      *
    110      * @param Writing_On_GitHub_Post[] $posts Array of Posts to save.
    111      * @param string                       $email Author email.
    112      *
    113      * @return string|WP_Error
    114      */
    115     public function save_posts( array $posts ) {
    116 
    117         /**
    118          * Whether an error has occurred.
    119          *
    120          * @var WP_Error|false $error
    121          */
    122         $error = false;
    123 
    124         foreach ( $posts as $post ) {
    125             $args = apply_filters( 'wogh_pre_import_args', $this->post_args( $post ), $post );
    126 
    127             remove_filter('content_save_pre', 'wp_filter_post_kses');
    128             $post_id = $post->is_new() ?
    129                 wp_insert_post( $args, true ) :
    130                 wp_update_post( $args, true );
    131             add_filter('content_save_pre', 'wp_filter_post_kses');
    132 
    133             if ( is_wp_error( $post_id ) ) {
    134                 if ( ! $error ) {
    135                     $error = $post_id;
    136                 } else {
    137                     $error->add( $post_id->get_error_code(), $post_id->get_error_message() );
    138                 }
    139 
    140                 // Abort saving if updating the post fails.
    141                 continue;
    142             }
    143 
    144             // $this->set_revision_author( $post_id, $user_id );
    145 
    146             if ( $post->is_new() ) {
    147                 $author = false;
    148                 $meta = $post->get_meta();
    149                 if ( ! empty( $meta ) && ! empty( $meta['author'] ) ) {
    150                     $author = $meta['author'];
    151                 }
    152                 $user    = $this->fetch_commit_user( $author );
    153                 $user_id = ! is_wp_error( $user ) ? $user->ID : 0;
    154                 $this->set_post_author( $post_id, $user_id );
    155             }
    156 
    157             $post->set_post( get_post( $post_id ) );
    158 
    159             $meta = apply_filters( 'wogh_pre_import_meta', $post->get_meta(), $post );
    160 
    161             unset( $meta['tags'] );
    162             unset( $meta['categories'] );
    163             unset( $meta['author'] );
    164             unset( $meta['post_date'] );
    165             unset( $meta['post_excerpt'] );
    166             unset( $meta['permalink'] );
    167             unset( $meta['link'] );
    168 
    169             foreach ( $meta as $key => $value ) {
    170                 update_post_meta( $post_id, $key, $value );
    171             }
    172         }
    173 
    174         if ( $error ) {
    175             return $error;
    176         }
    177 
    178         return __( 'Successfully saved posts.', 'writing-on-github' );
    179     }
    180 
    181     protected function post_args( $post ) {
    182         $args = $post->get_args();
    183         $meta = $post->get_meta();
    184 
    185         // prevent backslash loss
    186         $args['post_content'] = addslashes($args['post_content']);
    187 
    188         // update tags
    189         if ( isset( $meta['tags'] ) && $meta['tags'] ) {
    190             $args['tags_input'] = $meta['tags'];
    191         }
    192 
    193         // update categories
    194         if ( isset( $meta['categories'] ) && $meta['categories'] ) {
    195             $categories = $meta['categories'];
    196             if (!is_array($categories)) {
    197                 $categories = array($categories);
    198             }
    199             $terms = get_terms(array(
    200                 'taxonomy' => 'category',
    201                 'fields' => 'id=>name',
    202                 'hide_empty' => 0,
    203                 'name' => $categories
    204                 )
    205             );
    206             $map = array();
    207             foreach ($categories as $name) {
    208                 $map[$name] = 1;
    209             }
    210 
    211             $ids = array();
    212             if (!empty($terms)) {
    213                 foreach ($terms as $id => $name) {
    214                     $ids[] = $id;
    215                     unset($map[$name]);
    216                 }
    217             }
    218 
    219             // create new terms
    220             if (!empty($map)) {
    221                 foreach ($map as $name => $value) {
    222                     $term = wp_insert_term($name, 'category', array('parent' => 0));
    223                     // array('term_id' => $term_id, 'term_taxonomy_id' => $tt_id);
    224                     $ids[] = $term['term_id'];
    225                 }
    226             }
    227 
    228             $args['post_category'] = $ids;
    229         }
    230 
    231         return $args;
    232     }
    233 
    234     /**
    235      * Deletes a post from the database based on its GitHub path.
    236      *
    237      * @param string $path Path of Post to delete.
    238      *
    239      * @return string|WP_Error
    240      */
    241     public function delete_post_by_path( $path ) {
    242         $query = new WP_Query( array(
    243             'meta_key'       => '_wogh_github_path',
    244             'meta_value'     => $path,
    245             'meta_compare'   => '=',
    246             'posts_per_page' => 1,
    247             'fields'         => 'ids',
    248         ) );
    249 
    250         $post_id = $query->get_posts();
    251         $post_id = array_pop( $post_id );
    252 
    253         if ( ! $post_id ) {
    254             $parts     = explode( '/', $path );
    255             $filename  = array_pop( $parts );
    256             $directory = $parts ? array_shift( $parts ) : '';
    257 
    258             if ( false !== strpos( $directory, 'post' ) ) {
    259                 preg_match( '/([0-9]{4})-([0-9]{2})-([0-9]{2})-(.*)\.md/', $filename, $matches );
    260                 $title = $matches[4];
    261 
    262                 $query = new WP_Query( array(
    263                     'name'     => $title,
    264                     'posts_per_page' => 1,
    265                     'post_type' => $this->get_whitelisted_post_types(),
    266                     'fields'         => 'ids',
    267                 ) );
    268 
    269                 $post_id = $query->get_posts();
    270                 $post_id = array_pop( $post_id );
    271             }
    272 
    273             if ( ! $post_id ) {
    274                 preg_match( '/(.*)\.md/', $filename, $matches );
    275                 $title = $matches[1];
    276 
    277                 $query = new WP_Query( array(
    278                     'name'     => $title,
    279                     'posts_per_page' => 1,
    280                     'post_type' => $this->get_whitelisted_post_types(),
    281                     'fields'         => 'ids',
    282                 ) );
    283 
    284                 $post_id = $query->get_posts();
    285                 $post_id = array_pop( $post_id );
    286             }
    287         }
    288 
    289         if ( ! $post_id ) {
    290             return new WP_Error(
    291                 'path_not_found',
    292                 sprintf(
    293                     __( 'Post not found for path %s.', 'writing-on-github' ),
    294                     $path
    295                 )
    296             );
    297         }
    298 
    299         $result = wp_delete_post( $post_id );
    300 
    301         // If deleting fails...
    302         if ( false === $result ) {
    303             $post = get_post( $post_id );
    304 
    305             // ...and the post both exists and isn't in the trash...
    306             if ( $post && 'trash' !== $post->post_status ) {
    307                 // ... then something went wrong.
    308                 return new WP_Error(
    309                     'db_error',
    310                     sprintf(
    311                         __( 'Failed to delete post ID %d.', 'writing-on-github' ),
    312                         $post_id
    313                     )
    314                 );
    315             }
    316         }
    317 
    318         return sprintf(
    319             __( 'Successfully deleted post ID %d.', 'writing-on-github' ),
    320             $post_id
    321         );
    322     }
    323 
    324     public function delete_post( $post_id ) {
    325         $result = wp_delete_post( $post_id );
    326 
    327         // If deleting fails...
    328         if ( false === $result ) {
    329             $post = get_post( $post_id );
    330 
    331             // ...and the post both exists and isn't in the trash...
    332             if ( $post && 'trash' !== $post->post_status ) {
    333                 // ... then something went wrong.
    334                 return new WP_Error(
    335                     'db_error',
    336                     sprintf(
    337                         __( 'Failed to delete post ID %d.', 'writing-on-github' ),
    338                         $post_id
    339                     )
    340                 );
    341             }
    342         }
    343 
    344         return sprintf(
    345             __( 'Successfully deleted post ID %d.', 'writing-on-github' ),
    346             $post_id
    347         );
    348     }
    349 
    350     /**
    351      * Returns the list of post type permitted.
    352      *
    353      * @return array
    354      */
    355     protected function get_whitelisted_post_types() {
    356         return apply_filters( 'wogh_whitelisted_post_types', $this->whitelisted_post_types );
    357     }
    358 
    359     /**
    360      * Returns the list of post status permitted.
    361      *
    362      * @return array
    363      */
    364     protected function get_whitelisted_post_statuses() {
    365         return apply_filters( 'wogh_whitelisted_post_statuses', $this->whitelisted_post_statuses );
    366     }
    367 
    368     /**
    369      * Formats a whitelist array for a query.
    370      *
    371      * @param array $whitelist Whitelisted posts to format into query.
    372      *
    373      * @return string Whitelist formatted for query
    374      */
    375     protected function format_for_query( $whitelist ) {
    376         foreach ( $whitelist as $key => $value ) {
    377             $whitelist[ $key ] = "'$value'";
    378         }
    379 
    380         return implode( ', ', $whitelist );
    381     }
    382 
    383     /**
    384      * Verifies that both the post's status & type
    385      * are currently whitelisted
    386      *
    387      * @param  Writing_On_GitHub_Post $post Post to verify.
    388      *
    389      * @return boolean                          True if supported, false if not.
    390      */
    391     protected function is_post_supported( Writing_On_GitHub_Post $post ) {
    392         if ( wp_is_post_revision( $post->id ) ) {
    393             return false;
    394         }
    395 
    396         // We need to allow trashed posts to be queried, but they are not whitelisted for export.
    397         if ( ! in_array( $post->status(), $this->get_whitelisted_post_statuses() ) && 'trash' !== $post->status() ) {
    398             return false;
    399         }
    400 
    401         if ( ! in_array( $post->type(), $this->get_whitelisted_post_types() ) ) {
    402             return false;
    403         }
    404 
    405         if ( $post->has_password() ) {
    406             return false;
    407         }
    408 
    409         return apply_filters( 'wogh_is_post_supported', true, $post );
    410     }
    411 
    412     /**
    413      * Retrieves the commit user for a provided display name
    414      *
    415      * Searches for a user with provided display name or returns
    416      * the default user saved in the database.
    417      *
    418      * @param string $display_name User display name to search for.
    419      *
    420      * @return WP_Error|WP_User
    421      */
    422     protected function fetch_commit_user( $display_name ) {
    423         // If we can't find a user and a default hasn't been set,
    424         // we're just going to set the revision author to 0.
    425         $user = false;
    426 
    427         if ( ! empty( $display_name ) ) {
    428             $search_string = esc_attr( $display_name );
    429             $query = new WP_User_Query( array(
    430                 'search'         => "{$search_string}",
    431                 'search_columns' => array(
    432                     'display_name',
    433                     'user_nicename',
    434                     'user_login',
    435                 )
    436             ) );
    437             $users = $query->get_results();
    438             $user = empty($users) ? false : $users[0];
    439         }
    440 
    441         if ( ! $user ) {
    442             // Use the default user.
    443             $user = get_user_by( 'id', (int) get_option( 'wogh_default_user' ) );
    444         }
    445 
    446         if ( ! $user ) {
    447             return new WP_Error(
    448                 'user_not_found',
    449                 sprintf(
    450                     __( 'Commit user not found for email %s', 'writing-on-github' ),
    451                     $email
    452                 )
    453             );
    454         }
    455 
    456         return $user;
    457     }
    458 
    459     /**
    460      * Sets the author latest revision
    461      * of the provided post ID to the provided user.
    462      *
    463      * @param int $post_id Post ID to update revision author.
    464      * @param int $user_id User ID for revision author.
    465      *
    466      * @return string|WP_Error
    467      */
    468     protected function set_revision_author( $post_id, $user_id ) {
    469         $revision = wp_get_post_revisions( $post_id );
    470 
    471         if ( ! $revision ) {
    472             $new_revision = wp_save_post_revision( $post_id );
    473 
    474             if ( ! $new_revision || is_wp_error( $new_revision ) ) {
    475                 return new WP_Error( 'db_error', 'There was a problem saving a new revision.' );
    476             }
    477 
    478             // `wp_save_post_revision` returns the ID, whereas `get_post_revision` returns the whole object
    479             // in order to be consistent, let's make sure we have the whole object before continuing.
    480             $revision = get_post( $new_revision );
    481 
    482             if ( ! $revision ) {
    483                 return new WP_Error( 'db_error', 'There was a problem retrieving the newly recreated revision.' );
    484             }
    485         } else {
    486             $revision = array_shift( $revision );
    487         }
    488 
    489         return $this->set_post_author( $revision->ID, $user_id );
    490     }
    491 
    492     /**
    493      * Updates the user ID for the provided post ID.
    494      *
    495      * Bypassing triggering any hooks, including creating new revisions.
    496      *
    497      * @param int $post_id Post ID to update.
    498      * @param int $user_id User ID to update to.
    499      *
    500      * @return string|WP_Error
    501      */
    502     protected function set_post_author( $post_id, $user_id ) {
    503         global $wpdb;
    504 
    505         $result = $wpdb->update(
    506             $wpdb->posts,
    507             array(
    508                 'post_author' => (int) $user_id,
    509             ),
    510             array(
    511                 'ID' => (int) $post_id,
    512             ),
    513             array( '%d' ),
    514             array( '%d' )
    515         );
    516 
    517         if ( false === $result ) {
    518             return new WP_Error( 'db_error', $wpdb->last_error );
    519         }
    520 
    521         if ( 0 === $result ) {
    522             return sprintf(
    523                 __( 'No change for post ID %d.', 'writing-on-github' ),
    524                 $post_id
    525             );
    526         }
    527 
    528         clean_post_cache( $post_id );
    529 
    530         return sprintf(
    531             __( 'Successfully updated post ID %d.', 'writing-on-github' ),
    532             $post_id
    533         );
    534     }
    535 
    536     /**
    537      * Update the provided post's blob sha.
    538      *
    539      * @param Writing_On_GitHub_Post $post Post to update.
    540      * @param string                     $sha Sha to update to.
    541      *
    542      * @return bool|int
    543      */
    544     public function set_post_sha( $post, $sha ) {
    545         return update_post_meta( $post->id, '_wogh_sha', $sha );
    546     }
     49    public function fetch_all_supported( $force = false ) {
     50        $args  = array(
     51            'post_type'   => $this->get_whitelisted_post_types(),
     52            'post_status' => $this->get_whitelisted_post_statuses(),
     53            'nopaging'    => true,
     54            'fields'      => 'ids',
     55        );
     56
     57        $query = new WP_Query( apply_filters( 'wogh_pre_fetch_all_supported', $args ) );
     58
     59        $post_ids = $query->get_posts();
     60
     61        if ( ! $post_ids ) {
     62            return new WP_Error(
     63                'no_results',
     64                __( 'Querying for supported posts returned no results.', 'writing-on-github' )
     65            );
     66        }
     67
     68        /* @var Writing_On_GitHub_Post[] $results */
     69        $results = array();
     70        foreach ( $post_ids as $post_id ) {
     71            // Do not export posts that have already been exported
     72            if ( $force || ! get_post_meta( $post_id, '_wogh_sha', true ) ||
     73                 ! get_post_meta( $post_id, '_wogh_github_path', true ) ) {
     74
     75                $results[] = new Writing_On_GitHub_Post( $post_id, $this->app->api() );
     76            }
     77        }
     78
     79        return $results;
     80    }
     81
     82    /**
     83     * Queries a post and returns it if it's supported.
     84     *
     85     * @param int $post_id Post ID to fetch.
     86     *
     87     * @return WP_Error|Writing_On_GitHub_Post
     88     */
     89    public function fetch_by_id( $post_id ) {
     90        $post = new Writing_On_GitHub_Post( $post_id, $this->app->api() );
     91
     92        if ( ! $this->is_post_supported( $post ) ) {
     93            return new WP_Error(
     94                'unsupported_post',
     95                sprintf(
     96                    __(
     97                        'Post ID %s is not supported by WOGH. See wiki to find out how to add support.',
     98                        'writing-on-github'
     99                    ),
     100                    $post_id
     101                )
     102            );
     103        }
     104
     105        return $post;
     106    }
     107
     108    /**
     109     * Save an post to database
     110     * and associates their author as well as their latest
     111     *
     112     * @param  Writing_On_GitHub_Post $post [description]
     113     * @return WP_Error|true
     114     */
     115    public function save_post( Writing_On_GitHub_Post $post ) {
     116        $args = apply_filters( 'wogh_pre_import_args', $this->post_args( $post ), $post );
     117
     118        remove_filter( 'content_save_pre', 'wp_filter_post_kses' );
     119        $post_id = $post->is_new() ?
     120            wp_insert_post( $args, true ) :
     121            wp_update_post( $args, true );
     122        add_filter( 'content_save_pre', 'wp_filter_post_kses' );
     123
     124        if ( is_wp_error( $post_id ) ) {
     125            /* @var WP_Error $post_id */
     126            return $post_id;
     127        }
     128
     129        if ( $post->is_new() ) {
     130            $author = false;
     131            $meta = $post->get_meta();
     132            if ( ! empty( $meta ) && ! empty( $meta['author'] ) ) {
     133                $author = $meta['author'];
     134            }
     135            $user    = $this->fetch_commit_user( $author );
     136            $user_id = is_wp_error( $user ) ? 0 : $user->ID;
     137            $this->set_post_author( $post_id, $user_id );
     138        }
     139
     140        $post->set_post( get_post( $post_id ) );
     141
     142        $meta = apply_filters( 'wogh_pre_import_meta', $post->get_meta(), $post );
     143
     144        update_post_meta( $post_id, '_wogh_sha', $meta['_wogh_sha'] );
     145
     146        // unset( $meta['tags'] );
     147        // unset( $meta['categories'] );
     148        // unset( $meta['author'] );
     149        // unset( $meta['post_date'] );
     150        // unset( $meta['post_excerpt'] );
     151        // unset( $meta['permalink'] );
     152        // unset( $meta['link'] );
     153
     154        // foreach ( $meta as $key => $value ) {
     155        //  update_post_meta( $post_id, $key, $value );
     156        // }
     157        return true;
     158    }
     159
     160    protected function post_args( $post ) {
     161        $args = $post->get_args();
     162        $meta = $post->get_meta();
     163
     164        // prevent backslash loss
     165        $args['post_content'] = addslashes( $args['post_content'] );
     166
     167        // update tags
     168        if ( ! empty( $meta['tags'] ) ) {
     169            $args['tags_input'] = $meta['tags'];
     170        }
     171
     172        // update categories
     173        if ( ! empty( $meta['categories'] ) ) {
     174            $categories = $meta['categories'];
     175            if ( ! is_array( $categories ) ) {
     176                $categories = array( $categories );
     177            }
     178            $terms = get_terms( array(
     179                'taxonomy' => 'category',
     180                'fields' => 'id=>name',
     181                'hide_empty' => 0,
     182                'name' => $categories
     183                )
     184            );
     185            $map = array();
     186            foreach ( $categories as $name ) {
     187                $map[$name] = 1;
     188            }
     189
     190            $ids = array();
     191            if ( ! empty( $terms ) ) {
     192                foreach ( $terms as $id => $name ) {
     193                    $ids[] = $id;
     194                    unset( $map[$name] );
     195                }
     196            }
     197
     198            // create new terms
     199            if ( ! empty( $map ) ) {
     200                foreach ( $map as $name => $value ) {
     201                    $term = wp_insert_term( $name, 'category', array( 'parent' => 0 ) );
     202                    // array('term_id' => $term_id, 'term_taxonomy_id' => $tt_id);
     203                    $ids[] = $term['term_id'];
     204                }
     205            }
     206
     207            $args['post_category'] = $ids;
     208        }
     209
     210        return $args;
     211    }
     212
     213    private function get_post_id_by_filename( $filename, $pattern  ) {
     214        preg_match( $pattern , $filename, $matches );
     215        $title = $matches[4];
     216
     217        $query = new WP_Query( array(
     218            'name'     => $title,
     219            'posts_per_page' => 1,
     220            'post_type' => $this->get_whitelisted_post_types(),
     221            'fields'         => 'ids',
     222        ) );
     223
     224        $post_id = $query->get_posts();
     225        $post_id = array_pop( $post_id );
     226        return $post_id;
     227    }
     228
     229    /**
     230     * Deletes a post from the database based on its GitHub path.
     231     *
     232     * @param string $path Path of Post to delete.
     233     *
     234     * @return string|WP_Error
     235     */
     236    public function delete_post_by_path( $path ) {
     237        $query = new WP_Query( array(
     238            'meta_key'       => '_wogh_github_path',
     239            'meta_value'     => $path,
     240            'meta_compare'   => '=',
     241            'posts_per_page' => 1,
     242            'fields'         => 'ids',
     243        ) );
     244
     245        $post_id = $query->get_posts();
     246        $post_id = array_pop( $post_id );
     247
     248        if ( ! $post_id ) {
     249            $parts     = explode( '/', $path );
     250            $filename  = array_pop( $parts );
     251            $directory = $parts ? array_shift( $parts ) : '';
     252
     253            if ( false !== strpos( $directory, 'post' ) ) {
     254                $post_id = get_post_id_by_filename( $filename, '/([0-9]{4})-([0-9]{2})-([0-9]{2})-(.*)\.md/' );
     255            }
     256
     257            if ( ! $post_id ) {
     258                $post_id = get_post_id_by_filename( $filename, '/(.*)\.md/' );
     259            }
     260        }
     261
     262        if ( ! $post_id ) {
     263            return new WP_Error(
     264                'path_not_found',
     265                sprintf(
     266                    __( 'Post not found for path %s.', 'writing-on-github' ),
     267                    $path
     268                )
     269            );
     270        }
     271
     272        $result = wp_delete_post( $post_id );
     273
     274        // If deleting fails...
     275        if ( false === $result ) {
     276            $post = get_post( $post_id );
     277
     278            // ...and the post both exists and isn't in the trash...
     279            if ( $post && 'trash' !== $post->post_status ) {
     280                // ... then something went wrong.
     281                return new WP_Error(
     282                    'db_error',
     283                    sprintf(
     284                        __( 'Failed to delete post ID %d.', 'writing-on-github' ),
     285                        $post_id
     286                    )
     287                );
     288            }
     289        }
     290
     291        return sprintf(
     292            __( 'Successfully deleted post ID %d.', 'writing-on-github' ),
     293            $post_id
     294        );
     295    }
     296
     297    public function delete_post( $post_id ) {
     298        $result = wp_delete_post( $post_id );
     299
     300        // If deleting fails...
     301        if ( false === $result ) {
     302            $post = get_post( $post_id );
     303
     304            // ...and the post both exists and isn't in the trash...
     305            if ( $post && 'trash' !== $post->post_status ) {
     306                // ... then something went wrong.
     307                return new WP_Error(
     308                    'db_error',
     309                    sprintf(
     310                        __( 'Failed to delete post ID %d.', 'writing-on-github' ),
     311                        $post_id
     312                    )
     313                );
     314            }
     315        }
     316
     317        return sprintf(
     318            __( 'Successfully deleted post ID %d.', 'writing-on-github' ),
     319            $post_id
     320        );
     321    }
     322
     323    /**
     324     * Returns the list of post type permitted.
     325     *
     326     * @return array
     327     */
     328    protected function get_whitelisted_post_types() {
     329        return apply_filters( 'wogh_whitelisted_post_types', $this->whitelisted_post_types );
     330    }
     331
     332    /**
     333     * Returns the list of post status permitted.
     334     *
     335     * @return array
     336     */
     337    protected function get_whitelisted_post_statuses() {
     338        return apply_filters( 'wogh_whitelisted_post_statuses', $this->whitelisted_post_statuses );
     339    }
     340
     341    /**
     342     * Formats a whitelist array for a query.
     343     *
     344     * @param array $whitelist Whitelisted posts to format into query.
     345     *
     346     * @return string Whitelist formatted for query
     347     */
     348    protected function format_for_query( $whitelist ) {
     349        foreach ( $whitelist as $key => $value ) {
     350            $whitelist[ $key ] = "'$value'";
     351        }
     352
     353        return implode( ', ', $whitelist );
     354    }
     355
     356    /**
     357     * Verifies that both the post's status & type
     358     * are currently whitelisted
     359     *
     360     * @param  Writing_On_GitHub_Post $post Post to verify.
     361     *
     362     * @return boolean                          True if supported, false if not.
     363     */
     364    protected function is_post_supported( Writing_On_GitHub_Post $post ) {
     365        if ( wp_is_post_revision( $post->id ) ) {
     366            return false;
     367        }
     368
     369        // We need to allow trashed posts to be queried, but they are not whitelisted for export.
     370        if ( ! in_array( $post->status(), $this->get_whitelisted_post_statuses() ) && 'trash' !== $post->status() ) {
     371            return false;
     372        }
     373
     374        if ( ! in_array( $post->type(), $this->get_whitelisted_post_types() ) ) {
     375            return false;
     376        }
     377
     378        if ( $post->has_password() ) {
     379            return false;
     380        }
     381
     382        return apply_filters( 'wogh_is_post_supported', true, $post );
     383    }
     384
     385    /**
     386     * Retrieves the commit user for a provided display name
     387     *
     388     * Searches for a user with provided display name or returns
     389     * the default user saved in the database.
     390     *
     391     * @param string $display_name User display name to search for.
     392     *
     393     * @return WP_Error|WP_User
     394     */
     395    protected function fetch_commit_user( $display_name ) {
     396        // If we can't find a user and a default hasn't been set,
     397        // we're just going to set the revision author to 0.
     398        $user = false;
     399
     400        if ( ! empty( $display_name ) ) {
     401            $search_string = esc_attr( $display_name );
     402            $query = new WP_User_Query( array(
     403                'search'         => "{$search_string}",
     404                'search_columns' => array(
     405                    'display_name',
     406                    'user_nicename',
     407                    'user_login',
     408                )
     409            ) );
     410            $users = $query->get_results();
     411            $user = empty($users) ? false : $users[0];
     412        }
     413
     414        if ( ! $user ) {
     415            // Use the default user.
     416            $user = get_user_by( 'id', (int) get_option( 'wogh_default_user' ) );
     417        }
     418
     419        if ( ! $user ) {
     420            return new WP_Error(
     421                'user_not_found',
     422                sprintf(
     423                    __( 'Commit user not found for email %s', 'writing-on-github' ),
     424                    $email
     425                )
     426            );
     427        }
     428
     429        return $user;
     430    }
     431
     432    // /**
     433    //  * Sets the author latest revision
     434    //  * of the provided post ID to the provided user.
     435    //  *
     436    //  * @param int $post_id Post ID to update revision author.
     437    //  * @param int $user_id User ID for revision author.
     438    //  *
     439    //  * @return string|WP_Error
     440    //  */
     441    // protected function set_revision_author( $post_id, $user_id ) {
     442    //  $revision = wp_get_post_revisions( $post_id );
     443
     444    //  if ( ! $revision ) {
     445    //      $new_revision = wp_save_post_revision( $post_id );
     446
     447    //      if ( ! $new_revision || is_wp_error( $new_revision ) ) {
     448    //          return new WP_Error( 'db_error', 'There was a problem saving a new revision.' );
     449    //      }
     450
     451    //      // `wp_save_post_revision` returns the ID, whereas `get_post_revision` returns the whole object
     452    //      // in order to be consistent, let's make sure we have the whole object before continuing.
     453    //      $revision = get_post( $new_revision );
     454
     455    //      if ( ! $revision ) {
     456    //          return new WP_Error( 'db_error', 'There was a problem retrieving the newly recreated revision.' );
     457    //      }
     458    //  } else {
     459    //      $revision = array_shift( $revision );
     460    //  }
     461
     462    //  return $this->set_post_author( $revision->ID, $user_id );
     463    // }
     464
     465    /**
     466     * Updates the user ID for the provided post ID.
     467     *
     468     * Bypassing triggering any hooks, including creating new revisions.
     469     *
     470     * @param int $post_id Post ID to update.
     471     * @param int $user_id User ID to update to.
     472     *
     473     * @return string|WP_Error
     474     */
     475    protected function set_post_author( $post_id, $user_id ) {
     476        global $wpdb;
     477
     478        $result = $wpdb->update(
     479            $wpdb->posts,
     480            array(
     481                'post_author' => (int) $user_id,
     482            ),
     483            array(
     484                'ID' => (int) $post_id,
     485            ),
     486            array( '%d' ),
     487            array( '%d' )
     488        );
     489
     490        if ( false === $result ) {
     491            return new WP_Error( 'db_error', $wpdb->last_error );
     492        }
     493
     494        if ( 0 === $result ) {
     495            return sprintf(
     496                __( 'No change for post ID %d.', 'writing-on-github' ),
     497                $post_id
     498            );
     499        }
     500
     501        clean_post_cache( $post_id );
     502
     503        return sprintf(
     504            __( 'Successfully updated post ID %d.', 'writing-on-github' ),
     505            $post_id
     506        );
     507    }
     508
     509    // *
     510    //  * Update the provided post's blob sha.
     511    //  *
     512    //  * @param Writing_On_GitHub_Post $post Post to update.
     513    //  * @param string                     $sha Sha to update to.
     514    //  *
     515    //  * @return bool|int
     516
     517    // public function set_post_sha( $post, $sha ) {
     518    //  return update_post_meta( $post->id, '_wogh_sha', $sha );
     519    // }
    547520}
  • writing-on-github/trunk/lib/export.php

    r1709881 r1713007  
    1111class Writing_On_GitHub_Export {
    1212
    13     /**
    14      * Application container.
    15      *
    16      * @var Writing_On_GitHub
    17      */
    18     protected $app;
    19 
    20     /**
    21      * Initializes a new export manager.
    22      *
    23      * @param Writing_On_GitHub $app Application container.
    24      */
    25     public function __construct( Writing_On_GitHub $app ) {
    26         $this->app = $app;
    27     }
    28 
    29     /**
    30      * Updates all of the current posts in the database on master.
    31      *
    32      * @param  bool    $force_all
     13    /**
     14     * Application container.
     15     *
     16     * @var Writing_On_GitHub
     17     */
     18    protected $app;
     19
     20    /**
     21     * Initializes a new export manager.
     22     *
     23     * @param Writing_On_GitHub $app Application container.
     24     */
     25    public function __construct( Writing_On_GitHub $app ) {
     26        $this->app = $app;
     27    }
     28
     29    /**
     30     * Updates all of the current posts in the database on master.
     31     *
     32     * @param  bool    $force
     33     *
    3334     * @return string|WP_Error
    3435     */
    35     public function full( $force_all = false ) {
    36         $posts = $this->app->database()->fetch_all_supported($force_all);
    37 
    38         if ( is_wp_error( $posts ) ) {
    39             return $posts;
    40         }
    41 
    42         $error = false;
     36    public function full( $force = false ) {
     37        $posts = $this->app->database()->fetch_all_supported( $force );
     38
     39        if ( is_wp_error( $posts ) ) {
     40            /* @var WP_Error $posts */
     41            return $posts;
     42        }
     43
     44        $error = '';
    4345
    4446        foreach ( $posts as $post ) {
    4547            $result = $this->update( $post->id() );
    4648            if ( is_wp_error( $result ) ) {
    47                 if ( $error ) {
    48                     $error->add( $result->get_error_code(), $result->get_error_message() );
    49                 } else {
    50                     $error = $result;
    51                 }
     49                /* @var WP_Error $result */
     50                $error = wogh_append_error( $error, $result );
    5251            }
    5352        }
    5453
    5554        if ( is_wp_error( $error ) ) {
     55            /* @var WP_Error $error */
    5656            return $error;
    5757        }
    5858
    5959        return __( 'Export to GitHub completed successfully.', 'writing-on-github' );
    60     }
    61 
    62 
    63     /**
    64      * Check if it exists in github
    65      * @param  int  $post_id
    66      * @return boolean
    67      */
    68     protected function github_path( $post_id ) {
    69         $github_path = get_post_meta( $post_id, '_wogh_github_path', true );
    70 
    71         if ( $github_path && $this->app->api()->fetch()->exists( $github_path ) ) {
    72             return $github_path;
    73         }
    74 
    75         return false;
    76     }
    77 
    78     /**
    79      * Updates the provided post ID in master.
    80      *
    81      * @param int $post_id Post ID to update.
    82      *
    83      * @return string|WP_Error
    84      */
    85     public function update( $post_id ) {
    86         $post = $this->app->database()->fetch_by_id( $post_id );
    87 
    88         if ( is_wp_error( $post ) ) {
    89             return $post;
    90         }
    91 
    92         if ( 'trash' === $post->status() ) {
    93             return $this->delete( $post_id );
    94         }
    95 
    96         if ( $old_github_path = $this->github_path( $post->id() ) ) {
    97             error_log("old_github_path: $old_github_path");
    98             $post->set_old_github_path($old_github_path);
    99         }
    100 
    101         $result = $this->new_posts( array( $post ) );
    102 
    103         if ( is_wp_error( $result ) ) {
    104             return $result;
    105         }
    106 
    107         return __( 'Export to GitHub completed successfully.', 'writing-on-github' );
    108     }
    109 
    110     /**
    111      * Updates GitHub-created posts with latest WordPress data.
    112      *
    113      * @param array<Writing_On_GitHub_Post> $posts Array of Posts to create.
    114      *
    115      * @return string|WP_Error
    116      */
    117     public function new_posts( array $posts ) {
    118         $error = false;
    119 
    120         $persist = $this->app->api()->persist();
    121 
    122         foreach ( $posts as $post ) {
    123             $result = $this->new_post( $post, $persist );
    124             if ( is_wp_error( $result ) ) {
    125                 if ( $error ) {
    126                     $error->add( $result->get_error_code(), $result->get_error_message() );
    127                 } else {
    128                     $error = $result;
    129                 }
    130             }
    131         }
    132 
    133 
    134 
    135         // $result = $this->app->api()->persist()->commit( $master );
    136 
    137         if ( is_wp_error( $error ) ) {
    138             return $error;
    139         }
    140 
    141         // return $this->update_shas( $posts );
    142         return true;
    143     }
    144 
    145     protected function new_post( $post, $persist ) {
    146         $github_path = $post->github_path();
    147         $old_github_path = $post->old_github_path();
    148         $blob = $post->to_blob();
    149         $result = false;
    150 
    151         if ( $old_github_path && $old_github_path != $github_path ) {
    152             // rename
    153             $message = apply_filters(
    154                 'wogh_commit_msg_move_post',
    155                 sprintf(
    156                     'Move %s to %s via WordPress at %s (%s)',
    157                     $old_github_path, $github_path,
    158                     site_url(),
    159                     get_bloginfo( 'name' )
    160                 )
    161             ) . $this->get_commit_msg_tag();
    162 
    163             $result = $persist->delete_file( $post->old_github_path(), $blob->sha(), $message );
    164             if ( is_wp_error( $result ) ) {
    165                 return $result;
    166             }
    167 
    168             $result = $persist->create_file( $blob, $message );
    169             if ( is_wp_error( $result ) ) {
    170                 return $result;
    171             }
    172         } elseif ( ! $old_github_path ) {
    173             // create new
    174             $message = apply_filters(
    175                 'wogh_commit_msg_new_post',
    176                 sprintf(
    177                     'Create new post %s from WordPress at %s (%s)',
    178                     $github_path,
    179                     site_url(),
    180                     get_bloginfo( 'name' )
    181                 )
    182             ) . $this->get_commit_msg_tag();
    183             $result = $persist->create_file( $blob, $message );
    184             if ( is_wp_error( $result ) ) {
    185                 return $result;
    186             }
    187         } elseif ( $old_github_path && $old_github_path == $github_path ) {
    188             // update
    189             $message = apply_filters(
    190                 'wogh_commit_msg_update_post',
    191                 sprintf(
    192                     'Update post %s from WordPress at %s (%s)',
    193                     $github_path,
    194                     site_url(),
    195                     get_bloginfo( 'name' )
    196                 )
    197             ) . $this->get_commit_msg_tag();
    198             $result = $persist->update_file( $blob, $message );
    199             if ( is_wp_error( $result ) ) {
    200                 return $result;
    201             }
    202         }
    203 
    204         $sha = $result->content->sha;
    205         $post->set_sha($sha);
    206         $post->set_old_github_path($github_path);
    207 
    208         return true;
    209     }
    210 
    211     /**
    212      * Deletes a provided post ID from master.
    213      *
    214      * @param int $post_id Post ID to delete.
    215      *
    216      * @return string|WP_Error
    217      */
    218     public function delete( $post_id ) {
    219         $post = $this->app->database()->fetch_by_id( $post_id );
    220 
    221         if ( is_wp_error( $post ) ) {
    222             return $post;
    223         }
    224 
    225         $github_path = get_post_meta( $post_id, '_wogh_github_path', true );
    226 
    227         $message = apply_filters(
    228             'wogh_commit_msg_delete',
    229             sprintf(
    230                 'Deleting %s via WordPress at %s (%s)',
    231                 $github_path,
    232                 site_url(),
    233                 get_bloginfo( 'name' )
    234             ),
    235             $post
    236         ) . $this->get_commit_msg_tag();
    237 
    238         $result = $this->app->api()->persist()->delete_file( $github_path, $post->sha(), $message );
    239 
    240         if ( is_wp_error( $result ) ) {
    241             return $result;
    242         }
    243 
    244         return __( 'Export to GitHub completed successfully.', 'writing-on-github' );
    245     }
    246 
    247 
    248     /**
    249      * Saves the export user to the database.
    250      *
    251      * @param int $user_id User ID to export with.
    252      *
    253      * @return bool
    254      */
    255     public function set_user( $user_id ) {
    256         return update_option( self::EXPORT_USER_OPTION, (int) $user_id );
    257     }
    258 
    259     /**
    260      * Gets the commit message tag.
    261      *
    262      * @return string
    263      */
    264     protected function get_commit_msg_tag() {
    265         $tag = apply_filters( 'wogh_commit_msg_tag', 'wogh' );
    266 
    267         if ( ! $tag ) {
    268             throw new Exception( __( 'Commit message tag not set. Filter `wogh_commit_msg_tag` misconfigured.', 'writing-on-github' ) );
    269         }
    270 
    271         return ' - ' . $tag;
    272     }
     60    }
     61
     62
     63    /**
     64     * Check if it exists in github
     65     * @param  int  $post_id
     66     * @return boolean
     67     */
     68    protected function github_path( $post_id ) {
     69        $github_path = get_post_meta( $post_id, '_wogh_github_path', true );
     70
     71        if ( $github_path && $this->app->api()->fetch()->exists( $github_path ) ) {
     72            return $github_path;
     73        }
     74
     75        return false;
     76    }
     77
     78    /**
     79     * Updates the provided post ID in master.
     80     *
     81     * @param int $post_id Post ID to update.
     82     *
     83     * @return string|WP_Error
     84     */
     85    public function update( $post_id ) {
     86        $post = $this->app->database()->fetch_by_id( $post_id );
     87
     88        if ( is_wp_error( $post ) ) {
     89            /* @var WP_Error $post */
     90            return $post;
     91        }
     92
     93        if ( 'trash' === $post->status() ) {
     94            return $this->delete( $post_id );
     95        }
     96
     97        if ( $old_github_path = $this->github_path( $post->id() ) ) {
     98            error_log("old_github_path: $old_github_path");
     99            $post->set_old_github_path($old_github_path);
     100        }
     101
     102        $result = $this->export_post( $post );
     103
     104        if ( is_wp_error( $result ) ) {
     105            /* @var WP_Error $result */
     106            return $result;
     107        }
     108
     109        return __( 'Export to GitHub completed successfully.', 'writing-on-github' );
     110    }
     111
     112    /**
     113     * Post to blob
     114     * @param  Writing_On_GitHub_Post $post
     115     * @return WP_Error|Writing_On_GitHub_Blob
     116     */
     117    protected function post_to_blob( Writing_On_GitHub_Post $post ) {
     118        if ( ! $post->get_blob()
     119            && $post->old_github_path()
     120            && wogh_is_dont_export_content() ) {
     121
     122
     123            $blob = $this->app->api()->fetch()->blob_by_path( $post->old_github_path() );
     124
     125            if ( is_wp_error( $blob ) ) {
     126                /** @var WP_Error $blob */
     127                return $blob;
     128            }
     129
     130            $post->set_blob( $blob );
     131        }
     132
     133        return $post->to_blob();
     134    }
     135
     136    /**
     137     * Export post to github
     138     * @param  Writing_On_GitHub_Post $post
     139     * @return WP_Error|true
     140     */
     141    public function export_post( Writing_On_GitHub_Post $post ) {
     142        // check blob
     143        $blob = $this->post_to_blob( $post );
     144        if ( is_wp_error( $blob ) ) {
     145            /** @var WP_Error $blob */
     146            return $blob;
     147        }
     148
     149        $result = false;
     150
     151        $persist = $this->app->api()->persist();
     152        $github_path = $post->github_path();
     153        $old_github_path = $post->old_github_path();
     154
     155        if ( $old_github_path && $old_github_path != $github_path ) {
     156            // rename
     157            $message = apply_filters(
     158                'wogh_commit_msg_move_post',
     159                sprintf(
     160                    'Move %s to %s via WordPress at %s (%s)',
     161                    $old_github_path, $github_path,
     162                    site_url(),
     163                    get_bloginfo( 'name' )
     164                )
     165            ) . $this->get_commit_msg_tag();
     166
     167            $result = $persist->delete_file( $post->old_github_path(), $blob->sha(), $message );
     168            if ( is_wp_error( $result ) ) {
     169                return $result;
     170            }
     171
     172            $result = $persist->create_file( $blob, $message );
     173            if ( is_wp_error( $result ) ) {
     174                return $result;
     175            }
     176        } elseif ( ! $old_github_path ) {
     177            // create new
     178            $message = apply_filters(
     179                'wogh_commit_msg_new_post',
     180                sprintf(
     181                    'Create new post %s from WordPress at %s (%s)',
     182                    $github_path,
     183                    site_url(),
     184                    get_bloginfo( 'name' )
     185                )
     186            ) . $this->get_commit_msg_tag();
     187            $result = $persist->create_file( $blob, $message );
     188            if ( is_wp_error( $result ) ) {
     189                return $result;
     190            }
     191        } elseif ( $old_github_path && $old_github_path == $github_path ) {
     192            // update
     193            $sha = wogh_git_sha( $blob->content() );
     194            if ( $sha === $blob->sha() ) {
     195                // don't export when has not changed
     196                return true;
     197            }
     198            $message = apply_filters(
     199                'wogh_commit_msg_update_post',
     200                sprintf(
     201                    'Update post %s from WordPress at %s (%s)',
     202                    $github_path,
     203                    site_url(),
     204                    get_bloginfo( 'name' )
     205                )
     206            ) . $this->get_commit_msg_tag();
     207            $result = $persist->update_file( $blob, $message );
     208            if ( is_wp_error( $result ) ) {
     209                return $result;
     210            }
     211        }
     212
     213        $sha = $result->content->sha;
     214        $post->set_sha( $sha );
     215        $post->set_old_github_path( $github_path );
     216
     217        return true;
     218    }
     219
     220    /**
     221     * Deletes a provided post ID from master.
     222     *
     223     * @param int $post_id Post ID to delete.
     224     *
     225     * @return string|WP_Error
     226     */
     227    public function delete( $post_id ) {
     228        $post = $this->app->database()->fetch_by_id( $post_id );
     229
     230        if ( is_wp_error( $post ) ) {
     231            /* @var WP_Error $post */
     232            return $post;
     233        }
     234
     235        $github_path = get_post_meta( $post_id, '_wogh_github_path', true );
     236
     237        $message = apply_filters(
     238            'wogh_commit_msg_delete',
     239            sprintf(
     240                'Deleting %s via WordPress at %s (%s)',
     241                $github_path,
     242                site_url(),
     243                get_bloginfo( 'name' )
     244            ),
     245            $post
     246        ) . $this->get_commit_msg_tag();
     247
     248        $result = $this->app->api()->persist()->delete_file( $github_path, $post->sha(), $message );
     249
     250        if ( is_wp_error( $result ) ) {
     251            /* @var WP_Error $result */
     252            return $result;
     253        }
     254
     255        return __( 'Export to GitHub completed successfully.', 'writing-on-github' );
     256    }
     257
     258
     259    /**
     260     * Saves the export user to the database.
     261     *
     262     * @param int $user_id User ID to export with.
     263     *
     264     * @return bool
     265     */
     266    public function set_user( $user_id ) {
     267        return update_option( self::EXPORT_USER_OPTION, (int) $user_id );
     268    }
     269
     270    /**
     271     * Gets the commit message tag.
     272     *
     273     * @return string
     274     */
     275    protected function get_commit_msg_tag() {
     276        $tag = apply_filters( 'wogh_commit_msg_tag', 'wogh' );
     277
     278        if ( ! $tag ) {
     279            throw new Exception( __( 'Commit message tag not set. Filter `wogh_commit_msg_tag` misconfigured.', 'writing-on-github' ) );
     280        }
     281
     282        return ' - ' . $tag;
     283    }
    273284}
  • writing-on-github/trunk/lib/fileinfo.php

    r1709881 r1713007  
    77class Writing_On_GitHub_File_Info {
    88
    9     public function __construct( stdClass $data ) {
    10         $this->sha          = $data->sha;
    11         $this->path         = $data->path;
    12         $this->status       = $data->status;
    13     }
     9    public function __construct( stdClass $data ) {
     10        $this->sha          = $data->sha;
     11        $this->path         = $data->path;
     12        $this->status       = $data->status;
     13    }
    1414
    15     public $sha;
    16     public $path;
    17     public $status;  // added removed modified
     15    public $sha;
     16    public $path;
     17    public $status;  // added removed modified
    1818}
  • writing-on-github/trunk/lib/import.php

    r1709881 r1713007  
    1111class Writing_On_GitHub_Import {
    1212
    13     /**
    14      * Application container.
    15      *
    16      * @var Writing_On_GitHub
    17      */
    18     protected $app;
    19 
    20     /**
    21      * Initializes a new import manager.
    22      *
    23      * @param Writing_On_GitHub $app Application container.
    24      */
    25     public function __construct( Writing_On_GitHub $app ) {
    26         $this->app = $app;
    27     }
    28 
    29     /**
    30      * Imports a payload.
    31      *
    32      * @param Writing_On_GitHub_Payload $payload GitHub payload object.
    33      *
    34      * @return string|WP_Error
    35      */
    36     // public function payload( Writing_On_GitHub_Payload $payload ) {
    37     //  /**
    38     //   * Whether there's an error during import.
    39     //   *
    40     //   * @var false|WP_Error $error
    41     //   */
    42     //  $error = false;
    43 
    44     //  $result = $this->commit( $this->app->api()->fetch()->commit( $payload->get_commit_id() ) );
    45 
    46     //  if ( is_wp_error( $result ) ) {
    47     //      $error = $result;
    48     //  }
    49 
    50     //  $removed = array();
    51     //  foreach ( $payload->get_commits() as $commit ) {
    52     //      $removed = array_merge( $removed, $commit->removed );
    53     //  }
    54     //  foreach ( array_unique( $removed ) as $path ) {
    55     //      $result = $this->app->database()->delete_post_by_path( $path );
    56 
    57     //      if ( is_wp_error( $result ) ) {
    58     //          if ( $error ) {
    59     //              $error->add( $result->get_error_code(), $result->get_error_message() );
    60     //          } else {
    61     //              $error = $result;
    62     //          }
    63     //      }
    64     //  }
    65 
    66     //  if ( $error ) {
    67     //      return $error;
    68     //  }
    69 
    70     //  return __( 'Payload processed', 'writing-on-github' );
    71     // }
    72 
    73     public function payload( Writing_On_GitHub_Payload $payload ) {
    74 
    75         $result = $this->app->api()->fetch()->compare( $payload->get_before_commit_id() );
    76 
    77         if ( is_wp_error( $result ) ) {
    78             return $result;
    79         }
    80 
    81         $result = $this->import_files( $result );
    82 
    83         if ( is_wp_error( $result ) ) {
    84             return $files;
    85         }
    86 
    87         return __( 'Payload processed', 'writing-on-github' );
    88     }
    89 
    90     /**
    91      * import blob by files
    92      * @param  array $files [Writing_On_GitHub_File_Info]
    93      * @return string|WP_ERROR
    94      */
    95     protected function import_files( $files ) {
    96 
    97         $error      = false;
    98         $delete_ids = false;
    99 
    100         $result = $this->compare( $files, $delete_ids );
    101 
    102         if ( is_wp_error( $result ) ) {
    103             return $result;
    104         }
    105 
    106         if ( $delete_ids ) {
    107             foreach ($delete_ids as $id) {
    108                 $result = $this->app->database()->delete_post( $id );
    109                 if ( is_wp_error( $result ) ) {
    110                     if ( $error ) {
    111                         $error->add( $result->get_error_code(), $result->get_error_message() );
    112                     } else {
    113                         $error = $result;
    114                     }
    115                 }
    116             }
    117         }
    118 
    119         return $error;
    120     }
    121 
    122     /**
    123      * Imports the latest commit on the master branch.
    124      *
    125      * @return string|WP_Error
    126      */
    127     public function master() {
    128         $result = $this->app->api()->fetch()->tree_recursive();
    129 
    130         if ( is_wp_error( $result ) ) {
    131             return $result;
    132         }
    133 
    134         $result = $this->import_files( $result );
    135 
    136         if ( is_wp_error( $result ) ) {
    137             return $result;
    138         }
    139 
    140         return __( 'Payload processed', 'writing-on-github' );
    141     }
    142 
    143     protected function compare( $files, &$delete_ids ) {
    144         if ( is_wp_error( $files ) ) {
    145             return $files;
    146         }
    147 
    148         $posts = array();
    149         $new   = array();
    150 
    151         $idsmap = array();
    152 
    153         foreach ( $files as $file ) {
    154             if ( ! $this->importable_file( $file ) ) {
    155                 continue;
    156             }
    157 
    158             $blob = $this->app->api()->fetch()->blob($file);
    159             // network error ?
    160             if ( is_wp_error($blob) ) {
    161                 continue;
    162             }
    163 
    164 
    165             if ( $this->importable_raw_file($blob) ) {
    166                 $this->import_raw_file($blob, $file->status == 'removed');
    167                 continue;
    168             }
    169 
    170             if ( ! $this->importable_blob($blob) ) {
    171                 continue;
    172             }
    173 
    174             $post = $this->blob_to_post( $blob );
    175 
    176             if ( $file->status == 'removed' ) {
    177                 if ( $blob->id() ) {
    178                     $idsmap[$blob->id()] = true;
    179                 }
    180             } elseif ( $post != false ) {
    181                 $posts[] = $post;
    182                 if ( $post->is_new() ) {
    183                     $new[] = $post;
    184                 }
    185             }
    186         }
    187 
    188         foreach ($posts as $post) {
    189             if ( $post->id() && isset( $idsmap[$post->id()] ) ) {
    190                 unset( $idsmap[$post->id()] );
    191             }
    192         }
    193         $delete_ids = array();
    194         foreach ($idsmap as $id => $value) {
    195             $delete_ids[] = $id;
    196         }
    197 
    198         // $this->app->database()->save_posts( $posts, $commit->author_email() );
    199 
    200         $result = $this->app->database()->save_posts( $posts );
    201 
    202         if ( is_wp_error( $result ) ) {
    203             return $result;
    204         }
    205 
    206         if ( $new ) {
    207             $result = $this->app->export()->new_posts( $new );
    208 
    209             if ( is_wp_error( $result ) ) {
    210                 return $result;
    211             }
    212         }
    213 
    214         return $posts;
    215     }
    216 
    217     /**
    218      * Checks whether the provided blob should be imported.
    219      *
    220      * @param Writing_On_GitHub_Blob $blob Blob to validate.
    221      *
    222      * @return bool
    223      */
    224     protected function importable_file( Writing_On_GitHub_File_Info $file ) {
    225 
    226         // only _pages and _posts
    227         if ( strncasecmp($file->path, '_pages/', strlen('_pages/') ) != 0 &&
    228              strncasecmp($file->path, '_posts/', strlen('_posts/') ) != 0 &&
    229              strncasecmp($file->path, 'images/', strlen('images/') ) != 0 ) {
    230             return false;
    231         }
    232 
    233 
    234         // if ( ! $file->has_frontmatter() ) {
    235         //  return false;
    236         // }
    237 
    238         return true;
    239     }
    240 
    241     /**
    242      * Checks whether the provided blob should be imported.
    243      *
    244      * @param Writing_On_GitHub_Blob $blob Blob to validate.
    245      *
    246      * @return bool
    247      */
    248     protected function importable_blob( Writing_On_GitHub_Blob $blob ) {
    249         // global $wpdb;
    250 
    251         // // Skip the repo's readme.
    252         // if ( 'readme' === strtolower( substr( $blob->path(), 0, 6 ) ) ) {
    253         //  return false;
    254         // }
    255 
    256         // // If the blob sha already matches a post, then move on.
    257         // if ( ! is_wp_error( $this->app->database()->fetch_by_sha( $blob->sha() ) ) ) {
    258         //  return false;
    259         // }
    260 
    261         if ( ! $blob->has_frontmatter() ) {
    262             return false;
    263         }
    264 
    265         return true;
    266     }
    267 
    268     protected function importable_raw_file( Writing_On_GitHub_Blob $blob ) {
    269         if ( $blob->has_frontmatter() ) {
    270             return false;
    271         }
    272 
    273         // only images
    274         if ( strncasecmp($blob->path(), 'images/', strlen('images/') ) != 0) {
    275             return false;
    276         }
    277 
    278         return true;
    279     }
    280 
    281     /**
    282      * Imports a raw file content into file system.
    283      * @param  Writing_On_GitHub_Blob $blob
    284      * @param  bool                   $is_remove
    285      */
    286     protected function import_raw_file( Writing_On_GitHub_Blob $blob, $is_remove ) {
    287         $arr = wp_upload_dir();
    288         $path = $arr['basedir'] . '/writing-on-github/' . $blob->path();
    289         if ( $is_remove ) {
    290             if ( file_exists($path) ) {
    291                 unlink($path);
    292             }
    293         } else {
    294             $dirname = dirname($path);
    295             if ( ! file_exists($dirname) ) {
    296                 wp_mkdir_p($dirname);
    297             }
    298 
    299             file_put_contents($path, $blob->content());
    300         }
    301     }
    302 
    303     /**
    304      * Imports a single blob content into matching post.
    305      *
    306      * @param Writing_On_GitHub_Blob $blob Blob to transform into a Post.
    307      *
    308      * @return Writing_On_GitHub_Post
    309      */
    310     protected function blob_to_post( Writing_On_GitHub_Blob $blob ) {
    311         $args = array( 'post_content' => $blob->content_import() );
    312         $meta = $blob->meta();
    313 
    314         $id = false;
    315 
    316         if ( $meta ) {
    317             if ( array_key_exists( 'layout', $meta ) ) {
    318                 $args['post_type'] = $meta['layout'];
    319                 unset( $meta['layout'] );
    320             }
    321 
    322             if ( array_key_exists( 'published', $meta ) ) {
    323                 $args['post_status'] = true === $meta['published'] ? 'publish' : 'draft';
    324                 unset( $meta['published'] );
    325             }
    326 
    327             if ( array_key_exists( 'post_title', $meta ) ) {
    328                 $args['post_title'] = $meta['post_title'];
    329                 unset( $meta['post_title'] );
    330             }
    331 
    332             if ( array_key_exists( 'post_name', $meta ) ) {
    333                 $args['post_name'] = $meta['post_name'];
    334                 unset( $meta['post_name'] );
    335             }
    336 
    337             if ( array_key_exists( 'ID', $meta ) ) {
    338                 $id = $args['ID'] = $meta['ID'];
    339                 $blob->set_id($id);
    340                 unset( $meta['ID'] );
    341             }
    342         }
    343 
    344         $meta['_wogh_sha'] = $blob->sha();
    345 
    346         if ( $id ) {
    347             $old_sha = get_post_meta( $id, '_wogh_sha', true );
    348             $old_github_path = get_post_meta( $id, '_wogh_github_path', true );
    349 
    350             // dont save post when has same sha
    351             if ( $old_sha  && $old_sha == $meta['_wogh_sha'] &&
    352                  $old_github_path && $old_github_path == $blob->path() ) {
    353                 return false;
    354             }
    355         }
    356 
    357         $post = new Writing_On_GitHub_Post( $args, $this->app->api() );
    358         $post->set_old_github_path( $blob->path() );
    359         $post->set_meta( $meta );
    360         $blob->set_id( $post->id() );
    361 
    362         return $post;
    363     }
     13    /**
     14     * Application container.
     15     *
     16     * @var Writing_On_GitHub
     17     */
     18    protected $app;
     19
     20    /**
     21     * Initializes a new import manager.
     22     *
     23     * @param Writing_On_GitHub $app Application container.
     24     */
     25    public function __construct( Writing_On_GitHub $app ) {
     26        $this->app = $app;
     27    }
     28
     29    /**
     30     * Imports a payload.
     31     * @param  Writing_On_GitHub_Payload $payload
     32     *
     33     * @return string|WP_Error
     34     */
     35    public function payload( Writing_On_GitHub_Payload $payload ) {
     36
     37        $result = $this->app->api()->fetch()->compare( $payload->get_before_commit_id() );
     38
     39        if ( is_wp_error( $result ) ) {
     40            /* @var WP_Error $result */
     41            return $result;
     42        }
     43
     44        if ( is_array( $result ) ) {
     45            $result = $this->import_files( $result );
     46        }
     47
     48        if ( is_wp_error( $result ) ) {
     49            return $files;
     50        }
     51
     52        return __( 'Payload processed', 'writing-on-github' );
     53    }
     54
     55    /**
     56     * import blob by files
     57     * @param  Writing_On_GitHub_File_Info[] $files
     58     *
     59     * @return true|WP_Error
     60     */
     61    protected function import_files( $files ) {
     62
     63        $error = true;
     64
     65        foreach ( $files as $file ) {
     66            if ( ! $this->importable_file( $file ) ) {
     67                continue;
     68            }
     69
     70            $blob = $this->app->api()->fetch()->blob( $file );
     71            // network error ?
     72            if ( ! $blob instanceof Writing_On_GitHub_Blob ) {
     73                continue;
     74            }
     75
     76            $is_remove = 'removed' == $file->status;
     77
     78            $result = false;
     79            if ( $this->importable_raw_file( $blob ) ) {
     80                $result = $this->import_raw_file( $blob, $is_remove );
     81            } elseif ( $this->importable_post( $blob ) ) {
     82                if ( $is_remove ) {
     83                    $result = $this->delete_post( $blob );
     84                } else {
     85                    $result = $this->import_post( $blob );
     86                }
     87            }
     88
     89            if ( is_wp_error( $result ) ) {
     90                /* @var WP_Error $result */
     91                $error = wogh_append_error( $error, $result );
     92            }
     93        }
     94
     95        return $error;
     96    }
     97
     98    /**
     99     * Imports the latest commit on the master branch.
     100     *
     101     * @return string|WP_Error
     102     */
     103    public function master() {
     104        $result = $this->app->api()->fetch()->tree_recursive();
     105
     106        if ( is_wp_error( $result ) ) {
     107            /* @var WP_Error $result */
     108            return $result;
     109        }
     110
     111        if ( is_array( $result ) ) {
     112            $result = $this->import_files( $result );
     113        }
     114
     115        if ( is_wp_error( $result ) ) {
     116            /* @var WP_Error $result */
     117            return $result;
     118        }
     119
     120        return __( 'Payload processed', 'writing-on-github' );
     121    }
     122
     123    /**
     124     * Checks whether the provided blob should be imported.
     125     *
     126     * @param Writing_On_GitHub_File_Info $file
     127     *
     128     * @return bool
     129     */
     130    protected function importable_file( Writing_On_GitHub_File_Info $file ) {
     131
     132        $path = $file->path;
     133
     134        // only _pages, _posts and images
     135        $prefixs = array( '_pages/', '_posts/', 'images/');
     136        foreach ($prefixs as $prefix) {
     137            if ( ! strncasecmp($path, $prefix, strlen( $prefix ) ) ) {
     138                return true;
     139            }
     140        }
     141        return false;
     142    }
     143
     144    /**
     145     * Checks whether the provided blob should be imported.
     146     *
     147     * @param Writing_On_GitHub_Blob $blob Blob to validate.
     148     *
     149     * @return bool
     150     */
     151    protected function importable_post( Writing_On_GitHub_Blob $blob ) {
     152        // global $wpdb;
     153
     154        // // Skip the repo's readme.
     155        // if ( 'readme' === strtolower( substr( $blob->path(), 0, 6 ) ) ) {
     156        //  return false;
     157        // }
     158
     159        // // If the blob sha already matches a post, then move on.
     160        // if ( ! is_wp_error( $this->app->database()->fetch_by_sha( $blob->sha() ) ) ) {
     161        //  return false;
     162        // }
     163
     164        if ( ! $blob->has_frontmatter() ) {
     165            return false;
     166        }
     167
     168        return true;
     169    }
     170
     171    /**
     172     * Delete post
     173     * @param  Writing_On_GitHub_Blob $blob
     174     * @return WP_Error|bool
     175     */
     176    protected function delete_post( Writing_On_GitHub_Blob $blob ) {
     177        $id = $blob->id();
     178        if ( empty( $id ) ) {
     179            return false;
     180        }
     181        $result = $this->app->database()->delete_post( $id );
     182        if ( is_wp_error( $result ) ) {
     183            /* @var WP_Error $result */
     184            return $result;
     185        }
     186        return true;
     187    }
     188
     189    /**
     190     * Imports a post into wordpress
     191     * @param  Writing_On_GitHub_Blob $blob
     192     * @return WP_Error|bool
     193     */
     194    protected function import_post( Writing_On_GitHub_Blob $blob ) {
     195        $post = $this->blob_to_post( $blob );
     196
     197        if ( ! $post instanceof Writing_On_GitHub_Post ) {
     198            return false;
     199        }
     200
     201        $result = $this->app->database()->save_post( $post );
     202        if ( is_wp_error( $result ) ) {
     203            /** @var WP_Error $result */
     204            return $result;
     205        }
     206
     207        if ( $post->is_new() ||
     208                ! wogh_equal_front_matter( $post, $blob ) ) {
     209
     210            $result = $this->app->export()->export_post( $post );
     211
     212            if ( is_wp_error( $result ) ) {
     213                /** @var WP_Error $result */
     214                return $result;
     215            }
     216        }
     217
     218        clean_post_cache( $post->id() );
     219
     220        return true;
     221    }
     222
     223    /**
     224     * import raw file
     225     * @param  Writing_On_GitHub_Blob $blob
     226     * @return bool
     227     */
     228    protected function importable_raw_file( Writing_On_GitHub_Blob $blob ) {
     229        if ( $blob->has_frontmatter() ) {
     230            return false;
     231        }
     232
     233        // only images
     234        if ( strncasecmp($blob->path(), 'images/', strlen('images/') ) != 0) {
     235            return false;
     236        }
     237
     238        return true;
     239    }
     240
     241    /**
     242     * Imports a raw file content into file system.
     243     * @param  Writing_On_GitHub_Blob $blob
     244     * @param  bool                   $is_remove
     245     */
     246    protected function import_raw_file( Writing_On_GitHub_Blob $blob, $is_remove ) {
     247        $arr = wp_upload_dir();
     248        $path = $arr['basedir'] . '/writing-on-github/' . $blob->path();
     249        if ( $is_remove ) {
     250            if ( file_exists($path) ) {
     251                unlink($path);
     252            }
     253        } else {
     254            $dirname = dirname($path);
     255            if ( ! file_exists($dirname) ) {
     256                wp_mkdir_p($dirname);
     257            }
     258
     259            file_put_contents($path, $blob->content());
     260        }
     261        return true;
     262    }
     263
     264    /**
     265     * Imports a single blob content into matching post.
     266     *
     267     * @param Writing_On_GitHub_Blob $blob Blob to transform into a Post.
     268     *
     269     * @return Writing_On_GitHub_Post|false
     270     */
     271    protected function blob_to_post( Writing_On_GitHub_Blob $blob ) {
     272        $args = array( 'post_content' => $blob->content_import() );
     273        $meta = $blob->meta();
     274
     275        $id = false;
     276
     277        if ( ! empty( $meta ) ) {
     278            if ( array_key_exists( 'layout', $meta ) ) {
     279                $args['post_type'] = $meta['layout'];
     280                unset( $meta['layout'] );
     281            }
     282
     283            if ( array_key_exists( 'published', $meta ) ) {
     284                $args['post_status'] = true === $meta['published'] ? 'publish' : 'draft';
     285                unset( $meta['published'] );
     286            }
     287
     288            if ( array_key_exists( 'post_title', $meta ) ) {
     289                $args['post_title'] = $meta['post_title'];
     290                unset( $meta['post_title'] );
     291            }
     292
     293            if ( array_key_exists( 'post_name', $meta ) ) {
     294                $args['post_name'] = $meta['post_name'];
     295                unset( $meta['post_name'] );
     296            }
     297
     298            if ( array_key_exists( 'ID', $meta ) ) {
     299                $id = $args['ID'] = $meta['ID'];
     300                $blob->set_id($id);
     301                unset( $meta['ID'] );
     302            }
     303        }
     304
     305        $meta['_wogh_sha'] = $blob->sha();
     306
     307        if ( $id ) {
     308            $old_sha = get_post_meta( $id, '_wogh_sha', true );
     309            $old_github_path = get_post_meta( $id, '_wogh_github_path', true );
     310
     311            // dont save post when has same sha
     312            if ( $old_sha  && $old_sha == $meta['_wogh_sha'] &&
     313                 $old_github_path && $old_github_path == $blob->path() ) {
     314                return false;
     315            }
     316        }
     317
     318        $post = new Writing_On_GitHub_Post( $args, $this->app->api() );
     319        $post->set_old_github_path( $blob->path() );
     320        $post->set_meta( $meta );
     321        $post->set_blob( $blob );
     322        $blob->set_id( $post->id() );
     323
     324        return $post;
     325    }
    364326}
  • writing-on-github/trunk/lib/payload.php

    r1709881 r1713007  
    1010class Writing_On_GitHub_Payload {
    1111
    12     /**
    13     * Application container.
    14     *
    15     * @var Writing_On_GitHub
    16     */
    17     protected $app;
     12    /**
     13    * Application container.
     14    *
     15    * @var Writing_On_GitHub
     16    */
     17    protected $app;
    1818
    19     /**
    20     * Payload data.
    21     *
    22     * @var stdClass
    23     */
    24     protected $data;
     19    /**
     20    * Payload data.
     21    *
     22    * @var stdClass
     23    */
     24    protected $data;
    2525
    26     /**
    27     * Writing_On_GitHub_Payload constructor.
    28     *
    29     * @param Writing_On_GitHub $app      Application container.
    30     * @param string                $raw_data Raw request data.
    31     */
    32     public function __construct( Writing_On_GitHub $app, $raw_data ) {
    33         $this->app  = $app;
    34         $this->data = json_decode( $raw_data );
    35     }
     26    /**
     27    * Writing_On_GitHub_Payload constructor.
     28    *
     29    * @param Writing_On_GitHub $app      Application container.
     30    * @param string                $raw_data Raw request data.
     31    */
     32    public function __construct( Writing_On_GitHub $app, $raw_data ) {
     33        $this->app  = $app;
     34        $this->data = json_decode( $raw_data );
     35    }
    3636
    37     /**
    38     * Returns whether payload should be imported.
    39     *
    40     * @return bool
    41     */
    42     public function should_import() {
    43         // @todo how do we get this without importing the whole api object just for this?
    44         if ( strtolower( $this->data->repository->full_name ) !== strtolower( $this->app->api()->fetch()->repository() ) ) {
    45             return false;
    46         }
     37    /**
     38    * Returns whether payload should be imported.
     39    *
     40    * @return bool
     41    */
     42    public function should_import() {
     43        // @todo how do we get this without importing the whole api object just for this?
     44        if ( strtolower( $this->data->repository->full_name ) !== strtolower( $this->app->api()->fetch()->repository() ) ) {
     45            return false;
     46        }
    4747
    48         // The last term in the ref is the payload_branch name.
    49         $refs   = explode( '/', $this->data->ref );
    50         $payload_branch = array_pop( $refs );
     48        // The last term in the ref is the payload_branch name.
     49        $refs   = explode( '/', $this->data->ref );
     50        $payload_branch = array_pop( $refs );
    5151
    52         $branch = $this->app->api()->fetch()->branch();
     52        $branch = $this->app->api()->fetch()->branch();
    5353
    54         if ( $branch !== $payload_branch ) {
    55             return false;
    56         }
     54        if ( $branch !== $payload_branch ) {
     55            return false;
     56        }
    5757
    58         // We add a tag to commits we push out, so we shouldn't pull them in again.
    59         $tag = apply_filters( 'wogh_commit_msg_tag', 'wogh' );
     58        // We add a tag to commits we push out, so we shouldn't pull them in again.
     59        $tag = apply_filters( 'wogh_commit_msg_tag', 'wogh' );
    6060
    61         if ( ! $tag ) {
    62             throw new Exception( __( 'Commit message tag not set. Filter `wogh_commit_msg_tag` misconfigured.', 'writing-on-github' ) );
    63         }
     61        if ( ! $tag ) {
     62            throw new Exception( __( 'Commit message tag not set. Filter `wogh_commit_msg_tag` misconfigured.', 'writing-on-github' ) );
     63        }
    6464
    65         if ( $tag === substr( $this->message(), -1 * strlen( $tag ) ) ) {
    66             return false;
    67         }
     65        if ( $tag === substr( $this->message(), -1 * strlen( $tag ) ) ) {
     66            return false;
     67        }
    6868
    69         if ( ! $this->get_commit_id() ) {
    70             return false;
    71         }
     69        if ( ! $this->get_commit_id() ) {
     70            return false;
     71        }
    7272
    73         return true;
    74     }
     73        return true;
     74    }
    7575
    76     public function get_before_commit_id() {
    77         return $this->data->before ? $this->data->before : null;
    78     }
     76    public function get_before_commit_id() {
     77        return $this->data->before ? $this->data->before : null;
     78    }
    7979
    80     /**
    81     * Returns the sha of the head commit.
    82     *
    83     * @return string
    84     */
    85     public function get_commit_id() {
    86         return $this->data->head_commit ? $this->data->head_commit->id : null;
    87     }
     80    /**
     81    * Returns the sha of the head commit.
     82    *
     83    * @return string
     84    */
     85    public function get_commit_id() {
     86        return $this->data->head_commit ? $this->data->head_commit->id : null;
     87    }
    8888
    89     /**
    90     * Returns the email address for the commit author.
    91     *
    92     * @return string
    93     */
    94     public function get_author_email() {
    95         return $this->data->head_commit->author->email;
    96     }
     89    /**
     90    * Returns the email address for the commit author.
     91    *
     92    * @return string
     93    */
     94    public function get_author_email() {
     95        return $this->data->head_commit->author->email;
     96    }
    9797
    98     /**
    99     * Returns array commits for the payload.
    100     *
    101     * @return array
    102     */
    103     public function get_commits() {
    104         return $this->data->commits;
    105     }
     98    /**
     99    * Returns array commits for the payload.
     100    *
     101    * @return array
     102    */
     103    public function get_commits() {
     104        return $this->data->commits;
     105    }
    106106
    107     /**
    108     * Returns the repository's full name.
    109     *
    110     * @return string
    111     */
    112     public function get_repository_name() {
    113         return $this->data->repository->full_name;
    114     }
     107    /**
     108    * Returns the repository's full name.
     109    *
     110    * @return string
     111    */
     112    public function get_repository_name() {
     113        return $this->data->repository->full_name;
     114    }
    115115
    116     /**
    117     * Returns the payload's commit message.
    118     *
    119     * @return string
    120     */
    121     protected function message() {
    122         return $this->data->head_commit->message;
    123     }
     116    /**
     117    * Returns the payload's commit message.
     118    *
     119    * @return string
     120    */
     121    protected function message() {
     122        return $this->data->head_commit->message;
     123    }
    124124}
  • writing-on-github/trunk/lib/post.php

    r1709881 r1713007  
    1010class Writing_On_GitHub_Post {
    1111
    12     /**
    13      * Api object
    14      *
    15      * @var Writing_On_GitHub_Api
    16      */
    17     public $api;
    18 
    19     /**
    20      * Post ID
    21      * @var integer
    22      */
    23     public $id = 0;
    24 
    25     /**
    26      * Post object
    27      * @var WP_Post
    28      */
    29     public $post;
    30 
    31     /**
    32      * Post args.
    33      *
    34      * @var array
    35      */
    36     protected $args;
    37 
    38     /**
    39      * Post meta.
    40      *
    41      * @var array
    42      */
    43     protected $meta;
    44 
    45     /**
    46      * Whether the post has been saved.
    47      *
    48      * @var bool
    49      */
    50     protected $new = true;
    51 
    52 
    53     protected $old_github_path;
    54 
    55     /**
    56      * Instantiates a new Post object
    57      *
    58      * @param int|array                 $id_or_args Either a post ID or an array of arguments.
    59      * @param Writing_On_GitHub_Api $api API object.
    60      *
    61      * @todo remove database operations from this method
    62      */
    63     public function __construct( $id_or_args, Writing_On_GitHub_Api $api ) {
    64         $this->api = $api;
    65 
    66         if ( is_numeric( $id_or_args ) ) {
    67             $this->id   = (int) $id_or_args;
    68             $this->post = get_post( $this->id );
    69             $this->new  = false;
    70         }
    71 
    72         if ( is_array( $id_or_args ) ) {
    73             $this->args = $id_or_args;
    74 
    75             if ( isset( $this->args['ID'] ) ) {
    76                 $this->post = get_post( $this->args['ID'] );
    77 
    78                 if ( $this->post ) {
    79                     $this->id  = $this->post->ID;
    80                     $this->new = false;
    81                 } else {
    82                     unset( $this->args['ID'] );
    83                 }
    84             }
    85         }
    86     }
    87 
    88     public function id() {
    89         return $this->id;
    90     }
    91 
    92     /**
    93      * Returns the post type
    94      */
    95     public function type() {
    96         return $this->post->post_type;
    97     }
    98 
    99     /**
    100      * Returns the post type
    101      */
    102     public function status() {
    103         return $this->post->post_status;
    104     }
    105 
    106     /**
    107      * Returns the post name
    108      */
    109     public function name() {
    110         return $this->post->post_name;
    111     }
    112 
    113     /**
    114      * Returns true if the post has a password
    115      * @return bool
    116      */
    117     public function has_password() {
    118         return ! empty( $this->post->post_password );
    119     }
    120 
    121     /**
    122      * Combines the 2 content parts for GitHub
    123      */
    124     public function github_content() {
    125         $content = $this->front_matter() . $this->post_content();
    126         $ending  = apply_filters( 'wogh_line_endings', "\n" );
    127 
    128         return preg_replace( '~(*BSR_ANYCRLF)\R~', $ending, $content );
    129     }
    130 
    131     /**
    132      * The post's YAML frontmatter
    133      *
    134      * Returns String the YAML frontmatter, ready to be written to the file
    135      */
    136     public function front_matter() {
    137         return "---\n" . spyc_dump( $this->meta() ) . "---\n";
    138     }
    139 
    140     /**
    141      * Returns the post_content
    142      *
    143      * Markdownify's the content if applicable
    144      */
    145     public function post_content() {
    146         $content = $this->post->post_content;
    147 
    148         if ( function_exists( 'wpmarkdown_html_to_markdown' ) ) {
    149             $content = wpmarkdown_html_to_markdown( $content );
    150         } else if ( class_exists( 'WPCom_Markdown' ) ) {
    151             if ( WPCom_Markdown::get_instance()->is_markdown( $this->post->ID ) ) {
    152                 $content = $this->post->post_content_filtered;
    153             }
    154         }
    155 
    156         return apply_filters( 'wogh_content_export', $content, $this );
    157     }
    158 
    159     public function old_github_path() {
    160         return $this->old_github_path;
    161     }
    162 
    163     public function set_old_github_path( $path ) {
    164         $this->old_github_path = $path;
    165         update_post_meta( $this->id, '_wogh_github_path', $path);
    166     }
    167 
    168 
    169 
    170     /**
    171      * Retrieves or calculates the proper GitHub path for a given post
    172      *
    173      * Returns (string) the path relative to repo root
    174      */
    175     public function github_path() {
    176         $path = $this->github_directory() . $this->github_filename();
    177 
    178         return $path;
    179     }
    180 
    181     /**
    182      * Get GitHub directory based on post
    183      *
    184      * @return string
    185      */
    186     public function github_directory() {
    187         if ( 'publish' !== $this->status() ) {
    188             return apply_filters( 'wogh_directory_unpublished', '_drafts/', $this );
    189         }
    190 
    191         $name = '';
    192 
    193         switch ( $this->type() ) {
    194             case 'post':
    195                 $name = 'posts';
    196                 break;
    197             case 'page':
    198                 $name = 'pages';
    199                 break;
    200             default:
    201                 $obj = get_post_type_object( $this->type() );
    202 
    203                 if ( $obj ) {
    204                     $name = strtolower( $obj->labels->name );
    205                 }
    206 
    207                 if ( ! $name ) {
    208                     $name = '';
    209                 }
    210         }
    211 
    212         if ( $name ) {
    213             $name = '_' . $name . '/';
    214         }
    215 
    216         return apply_filters( 'wogh_directory_published', $name, $this );
    217     }
    218 
    219     /**
    220      * Build GitHub filename based on post
    221      */
    222     public function github_filename() {
    223         if ( 'post' === $this->type() ) {
    224             $filename = get_the_time( 'Y-m-d-', $this->id ) . $this->get_name() . '.md';
    225         } else {
    226             $filename = $this->get_name() . '.md';
    227         }
    228 
    229         return apply_filters( 'wogh_filename', $filename, $this );
    230     }
    231 
    232     /**
    233      * Returns a post slug we can use in the GitHub filename
    234      *
    235      * @return string
    236      */
    237     protected function get_name() {
    238         if ( '' !== $this->name() ) {
    239             return $this->name();
    240         }
    241 
    242         return sanitize_title( get_the_title( $this->post ) );
    243     }
    244 
    245     /**
    246      * is put on github
    247      * @return boolean
    248      */
    249     public function is_on_github() {
    250         $sha = get_post_meta( $this->id, '_wogh_sha', true );
    251         $github_path = get_post_meta( $this->id, '_wogh_github_path', true );
    252         if ( $sha && $github_path ) {
    253             return true;
    254         }
    255         return false;
    256     }
    257 
    258     /**
    259      * Returns the URL for the post on GitHub.
    260      *
    261      * @return string
    262      */
    263     public function github_view_url() {
    264         $github_path = get_post_meta( $this->id, '_wogh_github_path', true );
    265         $repository = $this->api->fetch()->repository();
    266         $branch = $this->api->fetch()->branch();
    267 
    268         return "https://github.com/$repository/blob/$branch/$github_path";
    269     }
    270 
    271     /**
    272      * Returns the URL for the post on GitHub.
    273      *
    274      * @return string
    275      */
    276     public function github_edit_url() {
    277         $github_path = get_post_meta( $this->id, '_wogh_github_path', true );
    278         $repository = $this->api->fetch()->repository();
    279         $branch = $this->api->fetch()->branch();
    280 
    281         return "https://github.com/$repository/edit/$branch/$github_path";
    282     }
    283 
    284     /**
    285      * Retrieve post type directory from blob path.
    286      *
    287      * @param string $path Path string.
    288      *
    289      * @return string
    290      */
    291     public function get_directory_from_path( $path ) {
    292         $directory = explode( '/', $path );
    293         $directory = count( $directory ) > 0 ? $directory[0] : '';
    294 
    295         return $directory;
    296     }
    297 
    298     /**
    299      * Determines the last author to modify the post
    300      *
    301      * Returns Array an array containing the author name and email
    302      */
    303     public function last_modified_author() {
    304         if ( $last_id = get_post_meta( $this->id, '_edit_last', true ) ) {
    305             $user = get_userdata( $last_id );
    306 
    307             if ( $user ) {
    308                 return array( 'name' => $user->display_name, 'email' => $user->user_email );
    309             }
    310         }
    311 
    312         return array();
    313     }
    314 
    315     /**
    316      * The post's sha
    317      * Cached as post meta, or will make a live call if need be
    318      *
    319      * Returns String the sha1 hash
    320      */
    321     public function sha() {
    322         $sha = get_post_meta( $this->id, '_wogh_sha', true );
    323 
    324         // If we've done a full export and we have no sha
    325         // then we should try a live check to see if it exists.
    326         // if ( ! $sha && 'yes' === get_option( '_wogh_fully_exported' ) ) {
    327 
    328         //  // @todo could we eliminate this by calling down the full tree and searching it
    329         //  $data = $this->api->fetch()->remote_contents( $this );
    330 
    331         //  if ( ! is_wp_error( $data ) ) {
    332         //      update_post_meta( $this->id, '_wogh_sha', $data->sha );
    333         //      $sha = $data->sha;
    334         //  }
    335         // }
    336 
    337         // if the sha still doesn't exist, then it's empty
    338         if ( ! $sha || is_wp_error( $sha ) ) {
    339             $sha = '';
    340         }
    341 
    342         return $sha;
    343     }
    344 
    345     /**
    346      * Save the sha to post
    347      *
    348      * @param string $sha
    349      */
    350     public function set_sha( $sha ) {
    351         update_post_meta( $this->id, '_wogh_sha', $sha );
    352     }
    353 
    354     /**
    355      * The post's metadata
    356      *
    357      * Returns Array the post's metadata
    358      */
    359     public function meta() {
    360         $meta = array(
    361             'ID'           => $this->id,
    362             'post_title'   => get_the_title( $this->post ),
    363             'post_name'    => $this->post->post_name,
    364             'author'       => ( $author = get_userdata( $this->post->post_author ) ) ? $author->display_name : '',
    365             'post_date'    => $this->post->post_date,
    366             'post_excerpt' => $this->post->post_excerpt,
    367             'layout'       => get_post_type( $this->post ),
    368             'link'         => get_permalink( $this->post ),
    369             'published'    => 'publish' === $this->status() ? true : false,
    370             'tags'         => wp_get_post_tags( $this->id, array( 'fields' => 'names' ) ),
    371             'categories'   => wp_get_post_categories( $this->id, array( 'fields' => 'names' ) )
    372         );
    373         if ( empty($this->post->post_name) ) {
    374             unset($meta['post_name']);
    375         }
    376         if ( empty($this->post->post_excerpt) ) {
    377             unset($meta['post_excerpt']);
    378         }
     12    /**
     13     * Api object
     14     *
     15     * @var Writing_On_GitHub_Api
     16     */
     17    public $api;
     18
     19    /**
     20     * Post ID
     21     * @var integer
     22     */
     23    public $id = 0;
     24
     25    /**
     26     * Blob object
     27     * @var Writing_On_GitHub_Blob
     28     */
     29    public $blob;
     30
     31    /**
     32     * Post object
     33     * @var WP_Post
     34     */
     35    public $post;
     36
     37    /**
     38     * Post args.
     39     *
     40     * @var array
     41     */
     42    protected $args;
     43
     44    /**
     45     * Post meta.
     46     *
     47     * @var array
     48     */
     49    protected $meta;
     50
     51    /**
     52     * Whether the post has been saved.
     53     *
     54     * @var bool
     55     */
     56    protected $new = true;
     57
     58
     59    protected $old_github_path;
     60
     61    /**
     62     * Instantiates a new Post object
     63     *
     64     * @param int|array                 $id_or_args Either a post ID or an array of arguments.
     65     * @param Writing_On_GitHub_Api $api API object.
     66     *
     67     * @todo remove database operations from this method
     68     */
     69    public function __construct( $id_or_args, Writing_On_GitHub_Api $api ) {
     70        $this->api = $api;
     71
     72        if ( is_numeric( $id_or_args ) ) {
     73            $this->id   = (int) $id_or_args;
     74            $this->post = get_post( $this->id );
     75            $this->new  = false;
     76        }
     77
     78        if ( is_array( $id_or_args ) ) {
     79            $this->args = $id_or_args;
     80
     81            if ( isset( $this->args['ID'] ) ) {
     82                $this->post = get_post( $this->args['ID'] );
     83
     84                if ( $this->post ) {
     85                    $this->id  = $this->post->ID;
     86                    $this->new = false;
     87                } else {
     88                    unset( $this->args['ID'] );
     89                }
     90            }
     91        }
     92    }
     93
     94    public function id() {
     95        return $this->id;
     96    }
     97
     98    /**
     99     * Returns the post type
     100     */
     101    public function type() {
     102        return $this->post->post_type;
     103    }
     104
     105    /**
     106     * Returns the post type
     107     */
     108    public function status() {
     109        return $this->post->post_status;
     110    }
     111
     112    /**
     113     * Returns the post name
     114     */
     115    public function name() {
     116        return $this->post->post_name;
     117    }
     118
     119    /**
     120     * Returns true if the post has a password
     121     * @return bool
     122     */
     123    public function has_password() {
     124        return ! empty( $this->post->post_password );
     125    }
     126
     127    /**
     128     * Combines the 2 content parts for GitHub
     129     */
     130    public function github_content() {
     131        $use_blob = wogh_is_dont_export_content() && $this->blob;
     132        $content = $use_blob ?
     133            $this->blob->post_content() :
     134            $this->post_content();
     135
     136        return $this->front_matter() . $content;
     137        // $content = $this->front_matter() . $content;
     138        // $ending  = apply_filters( 'wogh_line_endings', "\n" );
     139
     140        // return preg_replace( '~(*BSR_ANYCRLF)\R~', $ending, $content );
     141    }
     142
     143    /**
     144     * The post's YAML frontmatter
     145     *
     146     * Returns String the YAML frontmatter, ready to be written to the file
     147     */
     148    public function front_matter() {
     149        return "---\n" . spyc_dump( $this->meta() ) . "---\n";
     150    }
     151
     152    /**
     153     * Returns the post_content
     154     *
     155     * Markdownify's the content if applicable
     156     */
     157    public function post_content() {
     158        $content = $this->post->post_content;
     159
     160        if ( function_exists( 'wpmarkdown_html_to_markdown' ) ) {
     161            $content = wpmarkdown_html_to_markdown( $content );
     162        } else if ( class_exists( 'WPCom_Markdown' ) ) {
     163            if ( WPCom_Markdown::get_instance()->is_markdown( $this->post->ID ) ) {
     164                $content = $this->post->post_content_filtered;
     165            }
     166        }
     167
     168        return apply_filters( 'wogh_content_export', $content, $this );
     169    }
     170
     171    public function old_github_path() {
     172        return $this->old_github_path;
     173    }
     174
     175    public function set_old_github_path( $path ) {
     176        $this->old_github_path = $path;
     177        update_post_meta( $this->id, '_wogh_github_path', $path );
     178    }
     179
     180
     181    /**
     182     * Retrieves or calculates the proper GitHub path for a given post
     183     *
     184     * Returns (string) the path relative to repo root
     185     */
     186    public function github_path() {
     187        $path = $this->github_directory() . $this->github_filename();
     188
     189        return $path;
     190    }
     191
     192    /**
     193     * Get GitHub directory based on post
     194     *
     195     * @return string
     196     */
     197    public function github_directory() {
     198        if ( 'publish' !== $this->status() ) {
     199            return apply_filters( 'wogh_directory_unpublished', '_drafts/', $this );
     200        }
     201
     202        $name = '';
     203
     204        switch ( $this->type() ) {
     205            case 'post':
     206                $name = 'posts';
     207                break;
     208            case 'page':
     209                $name = 'pages';
     210                break;
     211            default:
     212                $obj = get_post_type_object( $this->type() );
     213
     214                if ( $obj ) {
     215                    $name = strtolower( $obj->labels->name );
     216                }
     217
     218                if ( ! $name ) {
     219                    $name = '';
     220                }
     221        }
     222
     223        if ( $name ) {
     224            $name = '_' . $name . '/';
     225        }
     226
     227        return apply_filters( 'wogh_directory_published', $name, $this );
     228    }
     229
     230    /**
     231     * Build GitHub filename based on post
     232     */
     233    public function github_filename() {
     234        if ( 'post' === $this->type() ) {
     235            $filename = get_the_time( 'Y-m-d-', $this->id ) . $this->get_name() . '.md';
     236        } else {
     237            $filename = $this->get_name() . '.md';
     238        }
     239
     240        return apply_filters( 'wogh_filename', $filename, $this );
     241    }
     242
     243    /**
     244     * Returns a post slug we can use in the GitHub filename
     245     *
     246     * @return string
     247     */
     248    protected function get_name() {
     249        if ( '' !== $this->name() ) {
     250            return $this->name();
     251        }
     252
     253        return sanitize_title( get_the_title( $this->post ) );
     254    }
     255
     256    /**
     257     * is put on github
     258     * @return boolean
     259     */
     260    public function is_on_github() {
     261        $sha = get_post_meta( $this->id, '_wogh_sha', true );
     262        $github_path = get_post_meta( $this->id, '_wogh_github_path', true );
     263        if ( $sha && $github_path ) {
     264            return true;
     265        }
     266        return false;
     267    }
     268
     269    /**
     270     * Returns the URL for the post on GitHub.
     271     *
     272     * @return string
     273     */
     274    public function github_view_url() {
     275        $github_path = get_post_meta( $this->id, '_wogh_github_path', true );
     276        $repository = $this->api->fetch()->repository();
     277        $branch = $this->api->fetch()->branch();
     278
     279        return "https://github.com/$repository/blob/$branch/$github_path";
     280    }
     281
     282    /**
     283     * Returns the URL for the post on GitHub.
     284     *
     285     * @return string
     286     */
     287    public function github_edit_url() {
     288        $github_path = get_post_meta( $this->id, '_wogh_github_path', true );
     289        $repository = $this->api->fetch()->repository();
     290        $branch = $this->api->fetch()->branch();
     291
     292        return "https://github.com/$repository/edit/$branch/$github_path";
     293    }
     294
     295    /**
     296     * Retrieve post type directory from blob path.
     297     *
     298     * @param string $path Path string.
     299     *
     300     * @return string
     301     */
     302    public function get_directory_from_path( $path ) {
     303        $directory = explode( '/', $path );
     304        $directory = count( $directory ) > 0 ? $directory[0] : '';
     305
     306        return $directory;
     307    }
     308
     309    /**
     310     * Determines the last author to modify the post
     311     *
     312     * Returns Array an array containing the author name and email
     313     */
     314    public function last_modified_author() {
     315        if ( $last_id = get_post_meta( $this->id, '_edit_last', true ) ) {
     316            $user = get_userdata( $last_id );
     317
     318            if ( $user ) {
     319                return array( 'name' => $user->display_name, 'email' => $user->user_email );
     320            }
     321        }
     322
     323        return array();
     324    }
     325
     326    /**
     327     * The post's sha
     328     * Cached as post meta, or will make a live call if need be
     329     *
     330     * Returns String the sha1 hash
     331     */
     332    public function sha() {
     333        $sha = get_post_meta( $this->id, '_wogh_sha', true );
     334
     335        // If we've done a full export and we have no sha
     336        // then we should try a live check to see if it exists.
     337        // if ( ! $sha && 'yes' === get_option( '_wogh_fully_exported' ) ) {
     338
     339        //  // @todo could we eliminate this by calling down the full tree and searching it
     340        //  $data = $this->api->fetch()->remote_contents( $this );
     341
     342        //  if ( ! is_wp_error( $data ) ) {
     343        //      update_post_meta( $this->id, '_wogh_sha', $data->sha );
     344        //      $sha = $data->sha;
     345        //  }
     346        // }
     347
     348        // if the sha still doesn't exist, then it's empty
     349        if ( ! $sha || is_wp_error( $sha ) ) {
     350            $sha = '';
     351        }
     352
     353        return $sha;
     354    }
     355
     356    /**
     357     * Save the sha to post
     358     *
     359     * @param string $sha
     360     */
     361    public function set_sha( $sha ) {
     362        update_post_meta( $this->id, '_wogh_sha', $sha );
     363    }
     364
     365    /**
     366     * The post's metadata
     367     *
     368     * Returns Array the post's metadata
     369     */
     370    public function meta() {
     371        $meta = array(
     372            'ID'           => $this->id,
     373            'post_title'   => get_the_title( $this->post ),
     374            'post_name'    => $this->post->post_name,
     375            'author'       => ( $author = get_userdata( $this->post->post_author ) ) ? $author->display_name : '',
     376            'post_date'    => $this->post->post_date,
     377            'post_excerpt' => $this->post->post_excerpt,
     378            'layout'       => get_post_type( $this->post ),
     379            'link'         => get_permalink( $this->post ),
     380            'published'    => 'publish' === $this->status() ? true : false,
     381            'tags'         => wp_get_post_tags( $this->id, array( 'fields' => 'names' ) ),
     382            'categories'   => wp_get_post_categories( $this->id, array( 'fields' => 'names' ) )
     383        );
     384        if ( empty($this->post->post_name) ) {
     385            unset($meta['post_name']);
     386        }
     387        if ( empty($this->post->post_excerpt) ) {
     388            unset($meta['post_excerpt']);
     389        }
    379390        if ( 'yes' == get_option('wogh_ignore_author') ) {
    380391            unset($meta['author']);
    381392        }
    382393
    383         //convert traditional post_meta values, hide hidden values, skip already populated values
    384         // foreach ( get_post_custom( $this->id ) as $key => $value ) {
    385 
    386         //  if ( '_' === substr( $key, 0, 1 ) || isset( $meta[ $key ] ) ) {
    387         //      continue;
    388         //  }
    389 
    390         //  $meta[ $key ] = $value;
    391 
    392         // }
    393 
    394         return apply_filters( 'wogh_post_meta', $meta, $this );
    395     }
    396 
    397     /**
    398      * Returns whether the Post has been saved in the DB yet.
    399      *
    400      * @return bool
    401      */
    402     public function is_new() {
    403         return $this->new;
    404     }
    405 
    406     /**
    407      * Sets the Post's meta.
    408      *
    409      * @param array $meta
    410      */
    411     public function set_meta( $meta ) {
    412         $this->meta = $meta;
    413     }
    414 
    415     /**
    416      * Returns the Post's arguments.
    417      *
    418      * @return array
    419      */
    420     public function get_args() {
    421         return $this->args;
    422     }
    423 
    424     /**
    425      * Returns the Post's meta.
    426      *
    427      * @return array
    428      */
    429     public function get_meta() {
    430         return $this->meta;
    431     }
    432 
    433     /**
    434      * Sets the Post's WP_Post object.
    435      *
    436      * @param WP_Post $post
    437      *
    438      * @return $this
    439      */
    440     public function set_post( WP_Post $post ) {
    441         $this->post = $post;
    442         $this->id   = $post->ID;
    443 
    444         return $this;
    445     }
    446 
    447     /**
    448      * Transforms the Post into a Blob.
    449      *
    450      * @return Writing_On_GitHub_Blob
    451      */
    452     public function to_blob() {
    453         $data = new stdClass;
    454 
    455         $data->path    = $this->github_path();
    456         $data->content = $this->github_content();
    457         $data->sha     = $this->sha();
    458 
    459         return new Writing_On_GitHub_Blob( $data );
    460     }
     394        //convert traditional post_meta values, hide hidden values, skip already populated values
     395        // foreach ( get_post_custom( $this->id ) as $key => $value ) {
     396
     397        //  if ( '_' === substr( $key, 0, 1 ) || isset( $meta[ $key ] ) ) {
     398        //      continue;
     399        //  }
     400
     401        //  $meta[ $key ] = $value;
     402
     403        // }
     404
     405        return apply_filters( 'wogh_post_meta', $meta, $this );
     406    }
     407
     408    /**
     409     * Returns whether the Post has been saved in the DB yet.
     410     *
     411     * @return bool
     412     */
     413    public function is_new() {
     414        return $this->new;
     415    }
     416
     417    /**
     418     * Sets the Post's meta.
     419     *
     420     * @param array $meta
     421     */
     422    public function set_meta( $meta ) {
     423        $this->meta = $meta;
     424    }
     425
     426    /**
     427     * Returns the Post's arguments.
     428     *
     429     * @return array
     430     */
     431    public function get_args() {
     432        return $this->args;
     433    }
     434
     435    /**
     436     * Returns the Post's meta.
     437     *
     438     * @return array
     439     */
     440    public function get_meta() {
     441        return $this->meta;
     442    }
     443
     444    /**
     445     * Get the blob
     446     * @return Writing_On_GitHub_Blob
     447     */
     448    public function get_blob() {
     449        return $this->blob;
     450    }
     451
     452    /**
     453     * Set the blob
     454     * @param Writing_On_GitHub_Blob $blob
     455     */
     456    public function set_blob( Writing_On_GitHub_Blob $blob ) {
     457        $this->blob = $blob;
     458    }
     459
     460    /**
     461     * Sets the Post's WP_Post object.
     462     *
     463     * @param WP_Post $post
     464     *
     465     * @return $this
     466     */
     467    public function set_post( WP_Post $post ) {
     468        $this->post = $post;
     469        $this->id   = $post->ID;
     470
     471        return $this;
     472    }
     473
     474    /**
     475     * Transforms the Post into a Blob.
     476     *
     477     * @return Writing_On_GitHub_Blob
     478     */
     479    public function to_blob() {
     480        $data = new stdClass;
     481
     482        $data->path    = $this->github_path();
     483        $data->content = $this->github_content();
     484        $data->sha     = $this->sha();
     485
     486        return new Writing_On_GitHub_Blob( $data );
     487    }
    461488}
  • writing-on-github/trunk/lib/request.php

    r1709881 r1713007  
    1010class Writing_On_GitHub_Request {
    1111
    12     /**
    13     * Application container.
    14     *
    15     * @var Writing_On_GitHub
    16     */
    17     protected $app;
     12    /**
     13    * Application container.
     14    *
     15    * @var Writing_On_GitHub
     16    */
     17    protected $app;
    1818
    19     /**
    20     * Raw request data.
    21     *
    22     * @var string
    23     */
    24     protected $raw_data;
     19    /**
     20    * Raw request data.
     21    *
     22    * @var string
     23    */
     24    protected $raw_data;
    2525
    26     /**
    27     * Headers
    28     * @var array
    29     */
    30     protected $headers;
     26    /**
     27    * Headers
     28    * @var array
     29    */
     30    protected $headers;
    3131
    32     /**
    33     * Writing_On_GitHub_Request constructor.
    34     *
    35     * @param Writing_On_GitHub $app Application container.
    36     */
    37     public function __construct( Writing_On_GitHub $app ) {
    38         $this->app = $app;
    39     }
     32    /**
     33    * Writing_On_GitHub_Request constructor.
     34    *
     35    * @param Writing_On_GitHub $app Application container.
     36    */
     37    public function __construct( Writing_On_GitHub $app ) {
     38        $this->app = $app;
     39    }
    4040
    41     /**
    42     * Validates the header's secret.
    43     *
    44     * @return true|WP_Error
    45     */
    46     public function is_secret_valid() {
    47         $headers = $this->headers();
     41    /**
     42    * Validates the header's secret.
     43    *
     44    * @return true|WP_Error
     45    */
     46    public function is_secret_valid() {
     47        $headers = $this->headers();
    4848
    49         $this->raw_data = $this->read_raw_data();
     49        $this->raw_data = $this->read_raw_data();
    5050
    51         // Validate request secret.
    52         $hash = hash_hmac( 'sha1', $this->raw_data, $this->secret() );
    53         if ( 'sha1=' . $hash !== $headers['X-Hub-Signature'] ) {
    54             return false;
    55         }
     51        // Validate request secret.
     52        $hash = hash_hmac( 'sha1', $this->raw_data, $this->secret() );
     53        if ( 'sha1=' . $hash !== $headers['X-Hub-Signature'] ) {
     54            return false;
     55        }
    5656
    57         //      [X-Hub-Signature] => sha1=3cf3da70de401f7dfff053392f60cc534efed3b4
    58         //     [Content-Type] => application/json
    59         //     [X-Github-Delivery] => b2102500-0acf-11e7-8acb-fd86a3497c2f
    60         //     [X-Github-Event] => ping
     57        //      [X-Hub-Signature] => sha1=3cf3da70de401f7dfff053392f60cc534efed3b4
     58        //     [Content-Type] => application/json
     59        //     [X-Github-Delivery] => b2102500-0acf-11e7-8acb-fd86a3497c2f
     60        //     [X-Github-Event] => ping
    6161
    62         return true;
    63     }
     62        return true;
     63    }
    6464
    65     /**
    66     * Validates the ping event.
    67     * @return boolean
    68     */
    69     public function is_ping() {
    70         $headers = $this->headers();
     65    /**
     66    * Validates the ping event.
     67    * @return boolean
     68    */
     69    public function is_ping() {
     70        $headers = $this->headers();
    7171
    72         $event = $headers['X-Github-Event'];
    73         return 'ping' == $event;
    74     }
     72        $event = $headers['X-Github-Event'];
     73        return 'ping' == $event;
     74    }
    7575
    76     /**
    77     * Validates the push event.
    78     * @return boolean
    79     */
    80     public function is_push() {
    81         $headers = $this->headers();
     76    /**
     77    * Validates the push event.
     78    * @return boolean
     79    */
     80    public function is_push() {
     81        $headers = $this->headers();
    8282
    83         $event = $headers['X-Github-Event'];
    84         return 'push' == $event;
    85     }
     83        $event = $headers['X-Github-Event'];
     84        return 'push' == $event;
     85    }
    8686
    87     /**
    88     * Returns a payload object for the given request.
    89     *
    90     * @return Writing_On_GitHub_Payload
    91     */
    92     public function payload() {
    93         return new Writing_On_GitHub_Payload( $this->app, $this->raw_data );
    94     }
     87    /**
     88    * Returns a payload object for the given request.
     89    *
     90    * @return Writing_On_GitHub_Payload
     91    */
     92    public function payload() {
     93        return new Writing_On_GitHub_Payload( $this->app, $this->raw_data );
     94    }
    9595
    96     /**
    97     * Cross-server header support.
    98     *
    99     * Returns an array of the request's headers.
    100     *
    101     * @return array
    102     */
    103     protected function headers() {
    104         if ( $this->headers ) {
    105             return $this->headers;
    106         }
     96    /**
     97    * Cross-server header support.
     98    *
     99    * Returns an array of the request's headers.
     100    *
     101    * @return array
     102    */
     103    protected function headers() {
     104        if ( ! empty( $this->headers ) ) {
     105            return $this->headers;
     106        }
    107107
    108         if ( function_exists( 'getallheaders' ) ) {
     108        if ( function_exists( 'getallheaders' ) ) {
    109109
    110             $this->headers = getallheaders();
    111             return $this->headers;
    112         }
    113         /**
    114         * Nginx and pre 5.4 workaround.
    115         * @see http://www.php.net/manual/en/function.getallheaders.php
    116         */
    117         $this->headers = array();
    118         foreach ( $_SERVER as $name => $value ) {
    119             if ( 'HTTP_' === substr( $name, 0, 5 ) ) {
    120                 $this->headers[ str_replace( ' ', '-', ucwords( strtolower( str_replace( '_', ' ', substr( $name, 5 ) ) ) ) ) ] = $value;
    121             }
    122         }
     110            $this->headers = getallheaders();
     111            return $this->headers;
     112        }
     113        /**
     114        * Nginx and pre 5.4 workaround.
     115        * @see http://www.php.net/manual/en/function.getallheaders.php
     116        */
     117        $this->headers = array();
     118        foreach ( $_SERVER as $name => $value ) {
     119            if ( 'HTTP_' === substr( $name, 0, 5 ) ) {
     120                $this->headers[ str_replace( ' ', '-', ucwords( strtolower( str_replace( '_', ' ', substr( $name, 5 ) ) ) ) ) ] = $value;
     121            }
     122        }
    123123
    124         return $this->headers;
    125     }
     124        return $this->headers;
     125    }
    126126
    127     /**
    128     * Reads the raw data from STDIN.
    129     *
    130     * @return string
    131     */
    132     protected function read_raw_data() {
    133         return file_get_contents( 'php://input' );
    134     }
     127    /**
     128    * Reads the raw data from STDIN.
     129    *
     130    * @return string
     131    */
     132    protected function read_raw_data() {
     133        return file_get_contents( 'php://input' );
     134    }
    135135
    136     /**
    137     * Returns the Webhook secret
    138     *
    139     * @return string
    140     */
    141     protected function secret() {
    142         return get_option( 'wogh_secret' );
    143     }
     136    /**
     137    * Returns the Webhook secret
     138    *
     139    * @return string
     140    */
     141    protected function secret() {
     142        return get_option( 'wogh_secret' );
     143    }
    144144}
  • writing-on-github/trunk/lib/response.php

    r1709881 r1713007  
    1010class Writing_On_GitHub_Response {
    1111
    12     /**
    13     * Application container.
    14     *
    15     * @var Writing_On_GitHub
    16     */
    17     protected $app;
     12    /**
     13    * Application container.
     14    *
     15    * @var Writing_On_GitHub
     16    */
     17    protected $app;
    1818
    19     /**
    20     * Writing_On_GitHub_Response constructor.
    21     *
    22     * @param Writing_On_GitHub $app Application container.
    23     */
    24     public function __construct( Writing_On_GitHub $app ) {
    25         $this->app = $app;
    26     }
     19    /**
     20    * Writing_On_GitHub_Response constructor.
     21    *
     22    * @param Writing_On_GitHub $app Application container.
     23    */
     24    public function __construct( Writing_On_GitHub $app ) {
     25        $this->app = $app;
     26    }
    2727
    28     /**
    29     * Writes to the log and returns the error response.
    30     *
    31     * @param WP_Error $error Error to respond with.
    32     *
    33     * @return false
    34     */
    35     public function error( WP_Error $error ) {
    36         global $wp_version;
     28    /**
     29    * Writes to the log and returns the error response.
     30    *
     31    * @param WP_Error $error Error to respond with.
     32    *
     33    * @return false
     34    */
     35    public function error( WP_Error $error ) {
     36        global $wp_version;
    3737
    38         $this->log( $error );
     38        $this->log( $error );
    3939
    40         if ( defined( 'DOING_AJAX' ) && DOING_AJAX && defined( 'WOGH_AJAX' ) && WOGH_AJAX ) {
    41             /**
    42             * WordPress 4.1.0 introduced allowing WP_Error objects to be
    43             * passed directly into `wp_send_json_error`. This shims in
    44             * compatibility for older versions. We're currently supporting 3.9+.
    45             */
    46             if ( version_compare( $wp_version, '4.1.0', '<' ) ) {
    47                 $result = array();
     40        if ( defined( 'DOING_AJAX' ) && DOING_AJAX && defined( 'WOGH_AJAX' ) && WOGH_AJAX ) {
     41            /**
     42            * WordPress 4.1.0 introduced allowing WP_Error objects to be
     43            * passed directly into `wp_send_json_error`. This shims in
     44            * compatibility for older versions. We're currently supporting 3.9+.
     45            */
     46            if ( version_compare( $wp_version, '4.1.0', '<' ) ) {
     47                $result = array();
    4848
    49                 foreach ( $error->errors as $code => $messages ) {
    50                     foreach ( $messages as $message ) {
    51                         $result[] = array( 'code' => $code, 'message' => $message );
    52                     }
    53                 }
     49                foreach ( $error->errors as $code => $messages ) {
     50                    foreach ( $messages as $message ) {
     51                        $result[] = array( 'code' => $code, 'message' => $message );
     52                    }
     53                }
    5454
    55                 $error = $result;
    56             }
     55                $error = $result;
     56            }
    5757
    58             wp_send_json_error( $error );
    59         }
     58            wp_send_json_error( $error );
     59        }
    6060
    61         return false;
    62     }
     61        return false;
     62    }
    6363
    64     /**
    65     * Writes to the log and returns the success response.
    66     *
    67     * @param string $success Success message to respond with.
    68     *
    69     * @return true
    70     */
    71     public function success( $success ) {
    72         $this->log( $success );
     64    /**
     65    * Writes to the log and returns the success response.
     66    *
     67    * @param string $success Success message to respond with.
     68    *
     69    * @return true
     70    */
     71    public function success( $success ) {
     72        $this->log( $success );
    7373
    74         if ( defined( 'DOING_AJAX' ) && DOING_AJAX && defined( 'WOGH_AJAX' ) && WOGH_AJAX ) {
    75             wp_send_json_success( $success );
    76         }
     74        if ( defined( 'DOING_AJAX' ) && DOING_AJAX && defined( 'WOGH_AJAX' ) && WOGH_AJAX ) {
     75            wp_send_json_success( $success );
     76        }
    7777
    78         return true;
    79     }
     78        return true;
     79    }
    8080
    81     /**
    82     * Writes a log message.
    83     *
    84     * Can extract a message from WP_Error object.
    85     *
    86     * @param string|WP_Error $msg Message to log.
    87     */
    88     protected function log( $msg ) {
    89         if ( is_wp_error( $msg ) ) {
    90             $msg = $msg->get_error_message();
    91         }
     81    /**
     82    * Writes a log message.
     83    *
     84    * Can extract a message from WP_Error object.
     85    *
     86    * @param string|WP_Error $msg Message to log.
     87    */
     88    protected function log( $msg ) {
     89        if ( is_wp_error( $msg ) ) {
     90            $msg = $msg->get_error_message();
     91        }
    9292
    93         Writing_On_GitHub::write_log( $msg );
    94     }
     93        Writing_On_GitHub::write_log( $msg );
     94    }
    9595}
  • writing-on-github/trunk/lib/semaphore.php

    r1709881 r1713007  
    1010class Writing_On_GitHub_Semaphore {
    1111
    12     /**
    13     * Sempahore's option key.
    14     */
    15     const KEY = 'wogh_semaphore_lock';
     12    /**
     13    * Sempahore's option key.
     14    */
     15    const KEY = 'wogh_semaphore_lock';
    1616
    17     /**
    18     * Option key when semaphore is locked.
    19     */
    20     const VALUE_LOCKED = 'yes';
     17    /**
     18    * Option key when semaphore is locked.
     19    */
     20    const VALUE_LOCKED = 'yes';
    2121
    22     /**
    23     * Option key when semaphore is unlocked.
    24     */
    25     const VALUE_UNLOCKED = 'no';
     22    /**
     23    * Option key when semaphore is unlocked.
     24    */
     25    const VALUE_UNLOCKED = 'no';
    2626
    27     /**
    28     * Clean up the old values on instantiation.
    29     */
    30     public function __construct() {
    31         delete_option( self::KEY );
    32     }
     27    /**
     28    * Clean up the old values on instantiation.
     29    */
     30    public function __construct() {
     31        delete_option( self::KEY );
     32    }
    3333
    34     /**
    35     * Checks if the Semaphore is open.
    36     *
    37     * Fails to report it's open if the the Api class can't make a call
    38     * or the push lock has been enabled.
    39     *
    40     * @return bool
    41     */
    42     public function is_open() {
    43         if ( self::VALUE_LOCKED === get_transient( self::KEY ) ) {
    44             return false;
    45         }
     34    /**
     35    * Checks if the Semaphore is open.
     36    *
     37    * Fails to report it's open if the the Api class can't make a call
     38    * or the push lock has been enabled.
     39    *
     40    * @return bool
     41    */
     42    public function is_open() {
     43        if ( self::VALUE_LOCKED === get_transient( self::KEY ) ) {
     44            return false;
     45        }
    4646
    47         return true;
    48     }
     47        return true;
     48    }
    4949
    50     /**
    51     * Enables the push lock.
    52     */
    53     public function lock() {
    54         set_transient( self::KEY, self::VALUE_LOCKED, MINUTE_IN_SECONDS );
    55     }
     50    /**
     51    * Enables the push lock.
     52    */
     53    public function lock() {
     54        set_transient( self::KEY, self::VALUE_LOCKED, MINUTE_IN_SECONDS );
     55    }
    5656
    57     /**
    58     * Disables the push lock.
    59     */
    60     public function unlock() {
    61         set_transient( self::KEY, self::VALUE_UNLOCKED, MINUTE_IN_SECONDS );
    62     }
     57    /**
     58    * Disables the push lock.
     59    */
     60    public function unlock() {
     61        set_transient( self::KEY, self::VALUE_UNLOCKED, MINUTE_IN_SECONDS );
     62    }
    6363}
  • writing-on-github/trunk/readme.txt

    r1709881 r1713007  
    11=== Writing On GitHub ===
     2
     3[![Build Status](https://travis-ci.org/litefeel/writing-on-github.svg?branch=master)](https://travis-ci.org/litefeel/writing-on-github)
     4[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/litefeel/writing-on-github/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/litefeel/writing-on-github/?branch=master)
     5
    26Contributors: litefeel 
    37Tags: github, git, version control, content, collaboration, publishing 
  • writing-on-github/trunk/writing-on-github.php

    r1709881 r1713007  
    1313// If the functions have already been autoloaded, don't reload.
    1414// This fixes function duplication during unit testing.
    15 if ( defined( 'WRITING_ON_GITHUB_TEST' ) && WRITING_ON_GITHUB_TEST ) {
    16     $path = dirname( __FILE__ ) . '/vendor/autoload_52.php';
    17     include_once $path;
     15$path = dirname( __FILE__ ) . '/vendor/autoload.php';
     16if ( file_exists( $path ) ) {
     17    require_once( $path );
    1818}
    1919
    20 
    21 require_once(dirname(__FILE__) . '/Spyc.php');
    22 require_once(dirname(__FILE__) . '/lib/cache.php');
    23 require_once(dirname(__FILE__) . '/lib/database.php');
    24 require_once(dirname(__FILE__) . '/lib/admin.php');
    25 require_once(dirname(__FILE__) . '/lib/payload.php');
    26 require_once(dirname(__FILE__) . '/lib/post.php');
    27 // require_once(dirname(__FILE__) . '/lib/cli.php');
    28 require_once(dirname(__FILE__) . '/lib/controller.php');
    29 require_once(dirname(__FILE__) . '/lib/export.php');
    30 require_once(dirname(__FILE__) . '/lib/semaphore.php');
    31 require_once(dirname(__FILE__) . '/lib/request.php');
    32 require_once(dirname(__FILE__) . '/lib/client/base.php');
    33 require_once(dirname(__FILE__) . '/lib/client/fetch.php');
    34 require_once(dirname(__FILE__) . '/lib/client/persist.php');
    35 require_once(dirname(__FILE__) . '/lib/import.php');
    36 require_once(dirname(__FILE__) . '/lib/api.php');
    37 require_once(dirname(__FILE__) . '/lib/fileinfo.php');
    38 require_once(dirname(__FILE__) . '/lib/blob.php');
    39 require_once(dirname(__FILE__) . '/lib/response.php');
    40 // require_once(dirname(__FILE__) . '/views/setting-field.php');
    41 // require_once(dirname(__FILE__) . '/views/options.php');
    42 // require_once(dirname(__FILE__) . '/views/user-setting-field.php');
    43 
    4420add_action( 'plugins_loaded', array( new Writing_On_GitHub, 'boot' ) );
    4521
    4622class Writing_On_GitHub {
    4723
    48     /**
    49      * Object instance
    50      * @var self
    51      */
    52     public static $instance;
    53 
    54     /**
    55      * Language text domain
    56      * @var string
    57      */
    58     public static $text_domain = 'writing-on-github';
    59 
    60     /**
    61      * Controller object
    62      * @var Writing_On_GitHub_Controller
    63      */
    64     public $controller;
    65 
    66     /**
    67      * Controller object
    68      * @var Writing_On_GitHub_Admin
    69      */
    70     public $admin;
    71 
    72     /**
    73      * CLI object.
    74      *
    75      * @var Writing_On_GitHub_CLI
    76      */
    77     protected $cli;
    78 
    79     /**
    80      * Request object.
    81      *
    82      * @var Writing_On_GitHub_Request
    83      */
    84     protected $request;
    85 
    86     /**
    87      * Response object.
    88      *
    89      * @var Writing_On_GitHub_Response
    90      */
    91     protected $response;
    92 
    93     /**
    94      * Api object.
    95      *
    96      * @var Writing_On_GitHub_Api
    97      */
    98     protected $api;
    99 
    100     /**
    101      * Import object.
    102      *
    103      * @var Writing_On_GitHub_Import
    104      */
    105     protected $import;
    106 
    107     /**
    108      * Export object.
    109      *
    110      * @var Writing_On_GitHub_Export
    111      */
    112     protected $export;
    113 
    114     /**
    115      * Semaphore object.
    116      *
    117      * @var Writing_On_GitHub_Semaphore
    118      */
    119     protected $semaphore;
    120 
    121     /**
    122      * Database object.
    123      *
    124      * @var Writing_On_GitHub_Database
    125      */
    126     protected $database;
    127 
    128     /**
    129      * Cache object.
    130      *
    131      * @var Writing_On_GitHub_Cache
    132      */
    133     protected $cache;
    134 
    135     /**
    136      * Called at load time, hooks into WP core
    137      */
    138     public function __construct() {
    139         self::$instance = $this;
    140 
    141         if ( is_admin() ) {
    142             $this->admin = new Writing_On_GitHub_Admin;
    143         }
    144 
    145         $this->controller = new Writing_On_GitHub_Controller( $this );
    146 
    147         if ( defined( 'WP_CLI' ) && WP_CLI ) {
    148             WP_CLI::add_command( 'wogh', $this->cli() );
    149         }
    150     }
    151 
    152     /**
    153      * Attaches the plugin's hooks into WordPress.
    154      */
    155     public function boot() {
    156         register_activation_hook( __FILE__, array( $this, 'activate' ) );
    157         add_action( 'admin_notices', array( $this, 'activation_notice' ) );
    158 
    159         add_action( 'init', array( $this, 'l10n' ) );
    160 
    161         // Controller actions.
    162         add_action( 'save_post', array( $this->controller, 'export_post' ) );
    163         add_action( 'delete_post', array( $this->controller, 'delete_post' ) );
    164         add_action( 'wp_ajax_nopriv_wogh_push_request', array( $this->controller, 'pull_posts' ) );
     24    /**
     25     * Object instance
     26     * @var self
     27     */
     28    public static $instance;
     29
     30    /**
     31     * Language text domain
     32     * @var string
     33     */
     34    public static $text_domain = 'writing-on-github';
     35
     36    /**
     37     * Controller object
     38     * @var Writing_On_GitHub_Controller
     39     */
     40    public $controller;
     41
     42    /**
     43     * Controller object
     44     * @var Writing_On_GitHub_Admin
     45     */
     46    public $admin;
     47
     48    /**
     49     * CLI object.
     50     *
     51     * @var Writing_On_GitHub_CLI
     52     */
     53    protected $cli;
     54
     55    /**
     56     * Request object.
     57     *
     58     * @var Writing_On_GitHub_Request
     59     */
     60    protected $request;
     61
     62    /**
     63     * Response object.
     64     *
     65     * @var Writing_On_GitHub_Response
     66     */
     67    protected $response;
     68
     69    /**
     70     * Api object.
     71     *
     72     * @var Writing_On_GitHub_Api
     73     */
     74    protected $api;
     75
     76    /**
     77     * Import object.
     78     *
     79     * @var Writing_On_GitHub_Import
     80     */
     81    protected $import;
     82
     83    /**
     84     * Export object.
     85     *
     86     * @var Writing_On_GitHub_Export
     87     */
     88    protected $export;
     89
     90    /**
     91     * Semaphore object.
     92     *
     93     * @var Writing_On_GitHub_Semaphore
     94     */
     95    protected $semaphore;
     96
     97    /**
     98     * Database object.
     99     *
     100     * @var Writing_On_GitHub_Database
     101     */
     102    protected $database;
     103
     104    /**
     105     * Called at load time, hooks into WP core
     106     */
     107    public function __construct() {
     108        self::$instance = $this;
     109
     110        if ( is_admin() ) {
     111            $this->admin = new Writing_On_GitHub_Admin( plugin_basename( __FILE__ ) );
     112        }
     113
     114        $this->controller = new Writing_On_GitHub_Controller( $this );
     115
     116        if ( defined( 'WP_CLI' ) && WP_CLI ) {
     117            WP_CLI::add_command( 'wogh', $this->cli() );
     118        }
     119    }
     120
     121    /**
     122     * Attaches the plugin's hooks into WordPress.
     123     */
     124    public function boot() {
     125        register_activation_hook( __FILE__, array( $this, 'activate' ) );
     126        add_action( 'admin_notices', array( $this, 'activation_notice' ) );
     127
     128        add_action( 'init', array( $this, 'l10n' ) );
     129
     130        // Controller actions.
     131        add_action( 'save_post', array( $this->controller, 'export_post' ) );
     132        add_action( 'delete_post', array( $this->controller, 'delete_post' ) );
     133        add_action( 'wp_ajax_nopriv_wogh_push_request', array( $this->controller, 'pull_posts' ) );
    165134        add_action( 'wogh_export', array( $this->controller, 'export_all' ), 10, 2 );
    166         add_action( 'wogh_import', array( $this->controller, 'import_master' ), 10, 1 );
    167         add_filter( 'get_edit_post_link', array( $this, 'edit_post_link' ), 10, 3 );
    168 
    169         // add_filter( 'wogh_post_meta', array( $this, 'ignore_post_meta' ), 10, 1 );
    170         // add_filter( 'wogh_pre_import_meta', array( $this, 'ignore_post_meta' ), 10, 1 );
    171         add_filter( 'the_content', array( $this, 'the_content' ) );
    172 
    173         do_action( 'wogh_boot', $this );
    174     }
    175 
    176     public function edit_post_link($link, $postID, $context) {
    177         if ( ! wp_is_post_revision( $postID ) ) {
    178             $post = new Writing_On_GitHub_Post( $postID, Writing_On_GitHub::$instance->api() );
    179             if ( $post->is_on_github() ) {
    180                 return $post->github_edit_url();
    181             }
    182         }
    183 
    184         return $link;
    185     }
    186 
    187     public function ignore_post_meta($meta) {
    188         $ignore_meta_keys = get_option('wogh_ignore_metas');
    189         if (empty($ignore_meta_keys)) {
    190             return $meta;
    191         }
    192 
    193         $keys = preg_split("/\\r\\n|\\r|\\n/", $ignore_meta_keys);
    194         if (empty($keys)) {
    195             return $meta;
    196         }
    197         foreach ($keys as $key => $value) {
    198             $keys[$key] = trim($value);
    199         }
    200 
    201         foreach ($meta as $key => $value) {
    202             if (in_array($key, $keys)) {
    203                 unset($meta[$key]);
    204             }
    205         }
    206 
    207         return $meta;
    208     }
    209 
    210     public function the_content($content) {
    211         $arr = wp_upload_dir();
    212         $baseurl = $arr['baseurl'] . '/writing-on-github';
    213 
    214         $content = preg_replace_callback(
    215             '/(<img [^>]*?src=[\'"])\s*(\/images\/[^\s#]\S+)\s*([\'"][^>]*?>)/',
    216             function($matchs) use ($baseurl) {
    217                 $url = $baseurl . $matchs[2];
    218                 return "${matchs[1]}$url${matchs[3]}";
    219             },
    220             $content
    221         );
    222 
    223         $content = preg_replace_callback(
    224             '/(<a [^>]*?href=[\'"])\s*(\/images\/[^\s#]\S+)\s*([\'"][^>]*?>)/',
    225             function($matchs) use ($baseurl) {
    226                 $url = $baseurl . $matchs[2];
    227                 return "${matchs[1]}$url${matchs[3]}";
    228             },
    229             $content
    230         );
    231         return $content;
    232     }
    233 
    234     /**
    235      * Init i18n files
    236      */
    237     public function l10n() {
    238         load_plugin_textdomain( self::$text_domain );
    239     }
    240 
    241     /**
    242      * Sets and kicks off the export cronjob
    243      */
    244     public function start_export( $force = false ) {
    245         $this->start_cron( 'export', $force );
    246     }
    247 
    248     /**
    249      * Sets and kicks off the import cronjob
    250      */
    251     public function start_import() {
    252         $this->start_cron( 'import' );
    253     }
    254 
    255     /**
    256      * Enables the admin notice on initial activation
    257      */
    258     public function activate() {
    259         if ( 'yes' !== get_option( '_wogh_fully_exported' ) ) {
    260             set_transient( '_wogh_activated', 'yes' );
    261         }
    262     }
    263 
    264     /**
    265      * Displays the activation admin notice
    266      */
    267     public function activation_notice() {
    268         if ( ! get_transient( '_wogh_activated' ) ) {
    269             return;
    270         }
    271 
    272         delete_transient( '_wogh_activated' );
    273 
    274         ?><div class="updated">
    275             <p>
    276                 <?php
    277                     printf(
    278                         __( 'To set up your site to sync with GitHub, update your <a href="%s">settings</a> and click "Export to GitHub."', 'writing-on-github' ),
    279                         admin_url( 'options-general.php?page=' . static::$text_domain)
    280                     );
    281                 ?>
    282             </p>
    283         </div><?php
    284     }
    285 
    286     /**
    287      * Get the Controller object.
    288      *
    289      * @return Writing_On_GitHub_Controller
    290      */
    291     public function controller() {
    292         return $this->controller;
    293     }
    294 
    295     /**
    296      * Lazy-load the CLI object.
    297      *
    298      * @return Writing_On_GitHub_CLI
    299      */
    300     public function cli() {
    301         if ( ! $this->cli ) {
    302             $this->cli = new Writing_On_GitHub_CLI;
    303         }
    304 
    305         return $this->cli;
    306     }
    307 
    308     /**
    309      * Lazy-load the Request object.
    310      *
    311      * @return Writing_On_GitHub_Request
    312      */
    313     public function request() {
    314         if ( ! $this->request ) {
    315             $this->request = new Writing_On_GitHub_Request( $this );
    316         }
    317 
    318         return $this->request;
    319     }
    320 
    321     /**
    322      * Lazy-load the Response object.
    323      *
    324      * @return Writing_On_GitHub_Response
    325      */
    326     public function response() {
    327         if ( ! $this->response ) {
    328             $this->response = new Writing_On_GitHub_Response( $this );
    329         }
    330 
    331         return $this->response;
    332     }
    333 
    334     /**
    335      * Lazy-load the Api object.
    336      *
    337      * @return Writing_On_GitHub_Api
    338      */
    339     public function api() {
    340         if ( ! $this->api ) {
    341             $this->api = new Writing_On_GitHub_Api( $this );
    342         }
    343 
    344         return $this->api;
    345     }
    346 
    347     /**
    348      * Lazy-load the Import object.
    349      *
    350      * @return Writing_On_GitHub_Import
    351      */
    352     public function import() {
    353         if ( ! $this->import ) {
    354             $this->import = new Writing_On_GitHub_Import( $this );
    355         }
    356 
    357         return $this->import;
    358     }
    359 
    360     /**
    361      * Lazy-load the Export object.
    362      *
    363      * @return Writing_On_GitHub_Export
    364      */
    365     public function export() {
    366         if ( ! $this->export ) {
    367             $this->export = new Writing_On_GitHub_Export( $this );
    368         }
    369 
    370         return $this->export;
    371     }
    372 
    373     /**
    374      * Lazy-load the Semaphore object.
    375      *
    376      * @return Writing_On_GitHub_Semaphore
    377      */
    378     public function semaphore() {
    379         if ( ! $this->semaphore ) {
    380             $this->semaphore = new Writing_On_GitHub_Semaphore;
    381         }
    382 
    383         return $this->semaphore;
    384     }
    385 
    386     /**
    387      * Lazy-load the Database object.
    388      *
    389      * @return Writing_On_GitHub_Database
    390      */
    391     public function database() {
    392         if ( ! $this->database ) {
    393             $this->database = new Writing_On_GitHub_Database( $this );
    394         }
    395 
    396         return $this->database;
    397     }
    398 
    399     /**
    400      * Lazy-load the Cache object.
    401      *
    402      * @return Writing_On_GitHub_Cache
    403      */
    404     public function cache() {
    405         if ( ! $this->cache ) {
    406             $this->cache = new Writing_On_GitHub_Cache;
    407         }
    408 
    409         return $this->cache;
    410     }
    411 
    412     /**
    413      * Print to WP_CLI if in CLI environment or
    414      * write to debug.log if WP_DEBUG is enabled
    415      * @source http://www.stumiller.me/sending-output-to-the-wordpress-debug-log/
    416      *
    417      * @param mixed $msg
    418      * @param string $write
    419      */
    420     public static function write_log( $msg, $write = 'line' ) {
    421         if ( defined( 'WP_CLI' ) && WP_CLI ) {
    422             if ( is_array( $msg ) || is_object( $msg ) ) {
    423                 WP_CLI::print_value( $msg );
    424             } else {
    425                 WP_CLI::$write( $msg );
    426             }
    427         } elseif ( true === WP_DEBUG ) {
    428             if ( is_array( $msg ) || is_object( $msg ) ) {
    429                 error_log( print_r( $msg, true ) );
    430             } else {
    431                 error_log( $msg );
    432             }
    433         }
    434     }
    435 
    436     /**
    437      * Kicks of an import or export cronjob.
    438      *
     135        add_action( 'wogh_import', array( $this->controller, 'import_master' ), 10, 1 );
     136        add_filter( 'get_edit_post_link', array( $this, 'edit_post_link' ), 10, 3 );
     137
     138        // add_filter( 'wogh_post_meta', array( $this, 'ignore_post_meta' ), 10, 1 );
     139        // add_filter( 'wogh_pre_import_meta', array( $this, 'ignore_post_meta' ), 10, 1 );
     140        add_filter( 'the_content', array( $this, 'the_content' ) );
     141
     142        do_action( 'wogh_boot', $this );
     143    }
     144
     145    public function edit_post_link($link, $postID, $context) {
     146        if ( ! wp_is_post_revision( $postID ) ) {
     147            $post = new Writing_On_GitHub_Post( $postID, Writing_On_GitHub::$instance->api() );
     148            if ( $post->is_on_github() ) {
     149                return $post->github_edit_url();
     150            }
     151        }
     152
     153        return $link;
     154    }
     155
     156    public function ignore_post_meta($meta) {
     157        $ignore_meta_keys = get_option('wogh_ignore_metas');
     158        if (empty($ignore_meta_keys)) {
     159            return $meta;
     160        }
     161
     162        $keys = preg_split("/\\r\\n|\\r|\\n/", $ignore_meta_keys);
     163        if (empty($keys)) {
     164            return $meta;
     165        }
     166        foreach ($keys as $key => $value) {
     167            $keys[$key] = trim($value);
     168        }
     169
     170        foreach ($meta as $key => $value) {
     171            if (in_array($key, $keys)) {
     172                unset($meta[$key]);
     173            }
     174        }
     175
     176        return $meta;
     177    }
     178
     179    public function the_content($content) {
     180        $arr = wp_upload_dir();
     181        $baseurl = $arr['baseurl'] . '/writing-on-github';
     182
     183        $content = preg_replace_callback(
     184            '/(<img [^>]*?src=[\'"])\s*(\/images\/[^\s#]\S+)\s*([\'"][^>]*?>)/',
     185            function($matchs) use ($baseurl) {
     186                $url = $baseurl . $matchs[2];
     187                return "${matchs[1]}$url${matchs[3]}";
     188            },
     189            $content
     190        );
     191
     192        $content = preg_replace_callback(
     193            '/(<a [^>]*?href=[\'"])\s*(\/images\/[^\s#]\S+)\s*([\'"][^>]*?>)/',
     194            function($matchs) use ($baseurl) {
     195                $url = $baseurl . $matchs[2];
     196                return "${matchs[1]}$url${matchs[3]}";
     197            },
     198            $content
     199        );
     200        return $content;
     201    }
     202
     203    /**
     204     * Init i18n files
     205     */
     206    public function l10n() {
     207        load_plugin_textdomain( self::$text_domain );
     208    }
     209
     210    /**
     211     * Sets and kicks off the export cronjob
     212     */
     213    public function start_export( $force = false ) {
     214        $this->start_cron( 'export', $force );
     215    }
     216
     217    /**
     218     * Sets and kicks off the import cronjob
     219     */
     220    public function start_import() {
     221        $this->start_cron( 'import' );
     222    }
     223
     224    /**
     225     * Enables the admin notice on initial activation
     226     */
     227    public function activate() {
     228        if ( 'yes' !== get_option( '_wogh_fully_exported' ) ) {
     229            set_transient( '_wogh_activated', 'yes' );
     230        }
     231    }
     232
     233    /**
     234     * Displays the activation admin notice
     235     */
     236    public function activation_notice() {
     237        if ( ! get_transient( '_wogh_activated' ) ) {
     238            return;
     239        }
     240
     241        delete_transient( '_wogh_activated' );
     242
     243        ?><div class="updated">
     244            <p>
     245                <?php
     246                    printf(
     247                        __( 'To set up your site to sync with GitHub, update your <a href="%s">settings</a> and click "Export to GitHub."', 'writing-on-github' ),
     248                        admin_url( 'options-general.php?page=' . static::$text_domain)
     249                    );
     250                ?>
     251            </p>
     252        </div><?php
     253    }
     254
     255    /**
     256     * Get the Controller object.
     257     *
     258     * @return Writing_On_GitHub_Controller
     259     */
     260    public function controller() {
     261        return $this->controller;
     262    }
     263
     264    /**
     265     * Lazy-load the CLI object.
     266     *
     267     * @return Writing_On_GitHub_CLI
     268     */
     269    public function cli() {
     270        if ( ! $this->cli ) {
     271            $this->cli = new Writing_On_GitHub_CLI;
     272        }
     273
     274        return $this->cli;
     275    }
     276
     277    /**
     278     * Lazy-load the Request object.
     279     *
     280     * @return Writing_On_GitHub_Request
     281     */
     282    public function request() {
     283        if ( ! $this->request ) {
     284            $this->request = new Writing_On_GitHub_Request( $this );
     285        }
     286
     287        return $this->request;
     288    }
     289
     290    /**
     291     * Lazy-load the Response object.
     292     *
     293     * @return Writing_On_GitHub_Response
     294     */
     295    public function response() {
     296        if ( ! $this->response ) {
     297            $this->response = new Writing_On_GitHub_Response( $this );
     298        }
     299
     300        return $this->response;
     301    }
     302
     303    /**
     304     * Lazy-load the Api object.
     305     *
     306     * @return Writing_On_GitHub_Api
     307     */
     308    public function api() {
     309        if ( ! $this->api ) {
     310            $this->api = new Writing_On_GitHub_Api( $this );
     311        }
     312
     313        return $this->api;
     314    }
     315
     316    /**
     317     * Lazy-load the Import object.
     318     *
     319     * @return Writing_On_GitHub_Import
     320     */
     321    public function import() {
     322        if ( ! $this->import ) {
     323            $this->import = new Writing_On_GitHub_Import( $this );
     324        }
     325
     326        return $this->import;
     327    }
     328
     329    /**
     330     * Lazy-load the Export object.
     331     *
     332     * @return Writing_On_GitHub_Export
     333     */
     334    public function export() {
     335        if ( ! $this->export ) {
     336            $this->export = new Writing_On_GitHub_Export( $this );
     337        }
     338
     339        return $this->export;
     340    }
     341
     342    /**
     343     * Lazy-load the Semaphore object.
     344     *
     345     * @return Writing_On_GitHub_Semaphore
     346     */
     347    public function semaphore() {
     348        if ( ! $this->semaphore ) {
     349            $this->semaphore = new Writing_On_GitHub_Semaphore;
     350        }
     351
     352        return $this->semaphore;
     353    }
     354
     355    /**
     356     * Lazy-load the Database object.
     357     *
     358     * @return Writing_On_GitHub_Database
     359     */
     360    public function database() {
     361        if ( ! $this->database ) {
     362            $this->database = new Writing_On_GitHub_Database( $this );
     363        }
     364
     365        return $this->database;
     366    }
     367
     368    /**
     369     * Print to WP_CLI if in CLI environment or
     370     * write to debug.log if WP_DEBUG is enabled
     371     * @source http://www.stumiller.me/sending-output-to-the-wordpress-debug-log/
     372     *
     373     * @param mixed $msg
     374     * @param string $write
     375     */
     376    public static function write_log( $msg, $write = 'line' ) {
     377        if ( defined( 'WP_CLI' ) && WP_CLI ) {
     378            if ( is_array( $msg ) || is_object( $msg ) ) {
     379                WP_CLI::print_value( $msg );
     380            } else {
     381                WP_CLI::$write( $msg );
     382            }
     383        } elseif ( true === WP_DEBUG ) {
     384            if ( is_array( $msg ) || is_object( $msg ) ) {
     385                error_log( print_r( $msg, true ) );
     386            } else {
     387                error_log( $msg );
     388            }
     389        }
     390    }
     391
     392    /**
     393     * Kicks of an import or export cronjob.
     394     *
    439395     * @param bool   $force
    440396     * @param string $type
    441397     */
    442     protected function start_cron( $type, $force = false ) {
    443         update_option( '_wogh_' . $type . '_started', 'yes' );
    444         $user_id = get_current_user_id();
    445         wp_schedule_single_event( time(), 'wogh_' . $type . '', array( $user_id, $force ) );
    446         spawn_cron();
    447     }
     398    protected function start_cron( $type, $force = false ) {
     399        update_option( '_wogh_' . $type . '_started', 'yes' );
     400        $user_id = get_current_user_id();
     401        wp_schedule_single_event( time(), 'wogh_' . $type . '', array( $user_id, $force ) );
     402        spawn_cron();
     403    }
    448404}
Note: See TracChangeset for help on using the changeset viewer.