Initial commit
This commit is contained in:
21
wp-content/plugins/activitypub/LICENSE
Normal file
21
wp-content/plugins/activitypub/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Matthias Pfefferle
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
100
wp-content/plugins/activitypub/activitypub.php
Normal file
100
wp-content/plugins/activitypub/activitypub.php
Normal file
@ -0,0 +1,100 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin Name: ActivityPub
|
||||
* Plugin URI: https://github.com/pfefferle/wordpress-activitypub/
|
||||
* Description: The ActivityPub protocol is a decentralized social networking protocol based upon the ActivityStreams 2.0 data format.
|
||||
* Version: 0.10.0
|
||||
* Author: Matthias Pfefferle
|
||||
* Author URI: https://notiz.blog/
|
||||
* License: MIT
|
||||
* License URI: http://opensource.org/licenses/MIT
|
||||
* Requires PHP: 5.6
|
||||
* Text Domain: activitypub
|
||||
* Domain Path: /languages
|
||||
*/
|
||||
|
||||
namespace Activitypub;
|
||||
|
||||
/**
|
||||
* Initialize plugin
|
||||
*/
|
||||
function init() {
|
||||
\defined( 'ACTIVITYPUB_HASHTAGS_REGEXP' ) || \define( 'ACTIVITYPUB_HASHTAGS_REGEXP', '(?:(?<=\s)|^)#(\w*[A-Za-z_]+\w*)' );
|
||||
|
||||
require_once \dirname( __FILE__ ) . '/includes/table/followers-list.php';
|
||||
require_once \dirname( __FILE__ ) . '/includes/class-signature.php';
|
||||
require_once \dirname( __FILE__ ) . '/includes/peer/class-followers.php';
|
||||
require_once \dirname( __FILE__ ) . '/includes/functions.php';
|
||||
|
||||
require_once \dirname( __FILE__ ) . '/includes/class-activity-dispatcher.php';
|
||||
\Activitypub\Activity_Dispatcher::init();
|
||||
|
||||
require_once \dirname( __FILE__ ) . '/includes/model/class-activity.php';
|
||||
require_once \dirname( __FILE__ ) . '/includes/model/class-post.php';
|
||||
\Activitypub\Model\Post::init();
|
||||
|
||||
require_once \dirname( __FILE__ ) . '/includes/class-activitypub.php';
|
||||
\Activitypub\Activitypub::init();
|
||||
|
||||
// Configure the REST API route
|
||||
require_once \dirname( __FILE__ ) . '/includes/rest/class-outbox.php';
|
||||
\Activitypub\Rest\Outbox::init();
|
||||
|
||||
require_once \dirname( __FILE__ ) . '/includes/rest/class-inbox.php';
|
||||
\Activitypub\Rest\Inbox::init();
|
||||
|
||||
require_once \dirname( __FILE__ ) . '/includes/rest/class-followers.php';
|
||||
\Activitypub\Rest\Followers::init();
|
||||
|
||||
require_once \dirname( __FILE__ ) . '/includes/rest/class-following.php';
|
||||
\Activitypub\Rest\Following::init();
|
||||
|
||||
require_once \dirname( __FILE__ ) . '/includes/rest/class-webfinger.php';
|
||||
\Activitypub\Rest\Webfinger::init();
|
||||
|
||||
require_once \dirname( __FILE__ ) . '/includes/rest/class-nodeinfo.php';
|
||||
\Activitypub\Rest\NodeInfo::init();
|
||||
|
||||
require_once \dirname( __FILE__ ) . '/includes/class-admin.php';
|
||||
\Activitypub\Admin::init();
|
||||
|
||||
require_once \dirname( __FILE__ ) . '/includes/class-hashtag.php';
|
||||
\Activitypub\Hashtag::init();
|
||||
|
||||
require_once \dirname( __FILE__ ) . '/includes/class-debug.php';
|
||||
\Activitypub\Debug::init();
|
||||
|
||||
require_once \dirname( __FILE__ ) . '/includes/class-health-check.php';
|
||||
\Activitypub\Health_Check::init();
|
||||
|
||||
require_once \dirname( __FILE__ ) . '/includes/rest/class-server.php';
|
||||
\add_filter( 'wp_rest_server_class', function() {
|
||||
return '\Activitypub\Rest\Server';
|
||||
} );
|
||||
}
|
||||
add_action( 'plugins_loaded', '\Activitypub\init' );
|
||||
|
||||
/**
|
||||
* Add rewrite rules
|
||||
*/
|
||||
function add_rewrite_rules() {
|
||||
if ( ! \class_exists( 'Webfinger' ) ) {
|
||||
\add_rewrite_rule( '^.well-known/webfinger', 'index.php?rest_route=/activitypub/1.0/webfinger', 'top' );
|
||||
}
|
||||
|
||||
if ( ! \class_exists( 'Nodeinfo' ) ) {
|
||||
\add_rewrite_rule( '^.well-known/nodeinfo', 'index.php?rest_route=/activitypub/1.0/nodeinfo/discovery', 'top' );
|
||||
\add_rewrite_rule( '^.well-known/x-nodeinfo2', 'index.php?rest_route=/activitypub/1.0/nodeinfo2', 'top' );
|
||||
}
|
||||
}
|
||||
\add_action( 'init', '\Activitypub\add_rewrite_rules', 1 );
|
||||
|
||||
/**
|
||||
* Flush rewrite rules;
|
||||
*/
|
||||
function flush_rewrite_rules() {
|
||||
\Activitypub\add_rewrite_rules();
|
||||
\flush_rewrite_rules();
|
||||
}
|
||||
\register_activation_hook( __FILE__, '\Activitypub\flush_rewrite_rules' );
|
||||
\register_deactivation_hook( __FILE__, '\flush_rewrite_rules' );
|
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
namespace Activitypub;
|
||||
|
||||
/**
|
||||
* ActivityPub Activity_Dispatcher Class
|
||||
*
|
||||
* @author Matthias Pfefferle
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitypub/
|
||||
*/
|
||||
class Activity_Dispatcher {
|
||||
/**
|
||||
* Initialize the class, registering WordPress hooks
|
||||
*/
|
||||
public static function init() {
|
||||
\add_action( 'activitypub_send_post_activity', array( '\Activitypub\Activity_Dispatcher', 'send_post_activity' ) );
|
||||
\add_action( 'activitypub_send_update_activity', array( '\Activitypub\Activity_Dispatcher', 'send_update_activity' ) );
|
||||
// \add_action( 'activitypub_send_delete_activity', array( '\Activitypub\Activity_Dispatcher', 'send_delete_activity' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Send "create" activities
|
||||
*
|
||||
* @param int $post_id
|
||||
*/
|
||||
public static function send_post_activity( $post_id ) {
|
||||
$post = \get_post( $post_id );
|
||||
$user_id = $post->post_author;
|
||||
|
||||
$activitypub_post = new \Activitypub\Model\Post( $post );
|
||||
$activitypub_activity = new \Activitypub\Model\Activity( 'Create', \Activitypub\Model\Activity::TYPE_FULL );
|
||||
$activitypub_activity->from_post( $activitypub_post->to_array() );
|
||||
|
||||
foreach ( \Activitypub\get_follower_inboxes( $user_id ) as $inbox => $to ) {
|
||||
$activitypub_activity->set_to( $to );
|
||||
$activity = $activitypub_activity->to_json(); // phpcs:ignore
|
||||
|
||||
\Activitypub\safe_remote_post( $inbox, $activity, $user_id );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send "update" activities
|
||||
*
|
||||
* @param int $post_id
|
||||
*/
|
||||
public static function send_update_activity( $post_id ) {
|
||||
$post = \get_post( $post_id );
|
||||
$user_id = $post->post_author;
|
||||
|
||||
$activitypub_post = new \Activitypub\Model\Post( $post );
|
||||
$activitypub_activity = new \Activitypub\Model\Activity( 'Update', \Activitypub\Model\Activity::TYPE_FULL );
|
||||
$activitypub_activity->from_post( $activitypub_post->to_array() );
|
||||
|
||||
foreach ( \Activitypub\get_follower_inboxes( $user_id ) as $inbox => $to ) {
|
||||
$activitypub_activity->set_to( $to );
|
||||
$activity = $activitypub_activity->to_json(); // phpcs:ignore
|
||||
|
||||
\Activitypub\safe_remote_post( $inbox, $activity, $user_id );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send "delete" activities
|
||||
*
|
||||
* @param int $post_id
|
||||
*/
|
||||
public static function send_delete_activity( $post_id ) {
|
||||
$post = \get_post( $post_id );
|
||||
$user_id = $post->post_author;
|
||||
|
||||
$activitypub_post = new \Activitypub\Model\Post( $post );
|
||||
$activitypub_activity = new \Activitypub\Model\Activity( 'Delete', \Activitypub\Model\Activity::TYPE_FULL );
|
||||
$activitypub_activity->from_post( $activitypub_post->to_array() );
|
||||
|
||||
foreach ( \Activitypub\get_follower_inboxes( $user_id ) as $inbox => $to ) {
|
||||
$activitypub_activity->set_to( $to );
|
||||
$activity = $activitypub_activity->to_json(); // phpcs:ignore
|
||||
|
||||
\Activitypub\safe_remote_post( $inbox, $activity, $user_id );
|
||||
}
|
||||
}
|
||||
}
|
179
wp-content/plugins/activitypub/includes/class-activitypub.php
Normal file
179
wp-content/plugins/activitypub/includes/class-activitypub.php
Normal file
@ -0,0 +1,179 @@
|
||||
<?php
|
||||
namespace Activitypub;
|
||||
|
||||
/**
|
||||
* ActivityPub Class
|
||||
*
|
||||
* @author Matthias Pfefferle
|
||||
*/
|
||||
class Activitypub {
|
||||
/**
|
||||
* Initialize the class, registering WordPress hooks
|
||||
*/
|
||||
public static function init() {
|
||||
\add_filter( 'template_include', array( '\Activitypub\Activitypub', 'render_json_template' ), 99 );
|
||||
\add_filter( 'query_vars', array( '\Activitypub\Activitypub', 'add_query_vars' ) );
|
||||
\add_action( 'init', array( '\Activitypub\Activitypub', 'add_rewrite_endpoint' ) );
|
||||
\add_filter( 'pre_get_avatar_data', array( '\Activitypub\Activitypub', 'pre_get_avatar_data' ), 11, 2 );
|
||||
|
||||
// Add support for ActivityPub to custom post types
|
||||
$post_types = \get_option( 'activitypub_support_post_types', array( 'post', 'page' ) ) ? \get_option( 'activitypub_support_post_types', array( 'post', 'page' ) ) : array();
|
||||
|
||||
foreach ( $post_types as $post_type ) {
|
||||
\add_post_type_support( $post_type, 'activitypub' );
|
||||
}
|
||||
|
||||
\add_action( 'transition_post_status', array( '\Activitypub\Activitypub', 'schedule_post_activity' ), 10, 3 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a AS2 JSON version of an author, post or page
|
||||
*
|
||||
* @param string $template the path to the template object
|
||||
*
|
||||
* @return string the new path to the JSON template
|
||||
*/
|
||||
public static function render_json_template( $template ) {
|
||||
if ( ! \is_author() && ! \is_singular() ) {
|
||||
return $template;
|
||||
}
|
||||
|
||||
if ( \is_author() ) {
|
||||
$json_template = \dirname( __FILE__ ) . '/../templates/json-author.php';
|
||||
} elseif ( \is_singular() ) {
|
||||
$json_template = \dirname( __FILE__ ) . '/../templates/json-post.php';
|
||||
}
|
||||
|
||||
global $wp_query;
|
||||
|
||||
if ( isset( $wp_query->query_vars['activitypub'] ) ) {
|
||||
return $json_template;
|
||||
}
|
||||
|
||||
if ( ! isset( $_SERVER['HTTP_ACCEPT'] ) ) {
|
||||
return $template;
|
||||
}
|
||||
|
||||
$accept_header = $_SERVER['HTTP_ACCEPT'];
|
||||
|
||||
if (
|
||||
\stristr( $accept_header, 'application/activity+json' ) ||
|
||||
\stristr( $accept_header, 'application/ld+json' )
|
||||
) {
|
||||
return $json_template;
|
||||
}
|
||||
|
||||
// accept header as an array
|
||||
$accept = \explode( ',', \trim( $accept_header ) );
|
||||
|
||||
if (
|
||||
\in_array( 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"', $accept, true ) ||
|
||||
\in_array( 'application/activity+json', $accept, true ) ||
|
||||
\in_array( 'application/ld+json', $accept, true ) ||
|
||||
\in_array( 'application/json', $accept, true )
|
||||
) {
|
||||
return $json_template;
|
||||
}
|
||||
|
||||
return $template;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the 'photos' query variable so WordPress
|
||||
* won't mangle it.
|
||||
*/
|
||||
public static function add_query_vars( $vars ) {
|
||||
$vars[] = 'activitypub';
|
||||
|
||||
return $vars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add our rewrite endpoint to permalinks and pages.
|
||||
*/
|
||||
public static function add_rewrite_endpoint() {
|
||||
\add_rewrite_endpoint( 'activitypub', EP_AUTHORS | EP_PERMALINK | EP_PAGES );
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule Activities
|
||||
*
|
||||
* @param int $post_id
|
||||
*/
|
||||
public static function schedule_post_activity( $new_status, $old_status, $post ) {
|
||||
// do not send activities if post is password protected
|
||||
if ( \post_password_required( $post ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// check if post-type supports ActivityPub
|
||||
$post_types = \get_post_types_by_support( 'activitypub' );
|
||||
if ( ! \in_array( $post->post_type, $post_types, true ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( 'publish' === $new_status && 'publish' !== $old_status ) {
|
||||
\wp_schedule_single_event( \time(), 'activitypub_send_post_activity', array( $post->ID ) );
|
||||
} elseif ( 'publish' === $new_status ) {
|
||||
\wp_schedule_single_event( \time(), 'activitypub_send_update_activity', array( $post->ID ) );
|
||||
} elseif ( 'trash' === $new_status ) {
|
||||
\wp_schedule_single_event( \time(), 'activitypub_send_delete_activity', array( get_permalink( $post ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the default avatar
|
||||
*
|
||||
* @param array $args Arguments passed to get_avatar_data(), after processing.
|
||||
* @param int|string|object $id_or_email A user ID, email address, or comment object
|
||||
*
|
||||
* @return array $args
|
||||
*/
|
||||
public static function pre_get_avatar_data( $args, $id_or_email ) {
|
||||
if (
|
||||
! $id_or_email instanceof \WP_Comment ||
|
||||
! isset( $id_or_email->comment_type ) ||
|
||||
$id_or_email->user_id
|
||||
) {
|
||||
return $args;
|
||||
}
|
||||
|
||||
$allowed_comment_types = \apply_filters( 'get_avatar_comment_types', array( 'comment' ) );
|
||||
if ( ! empty( $id_or_email->comment_type ) && ! \in_array( $id_or_email->comment_type, (array) $allowed_comment_types, true ) ) {
|
||||
$args['url'] = false;
|
||||
/** This filter is documented in wp-includes/link-template.php */
|
||||
return \apply_filters( 'get_avatar_data', $args, $id_or_email );
|
||||
}
|
||||
|
||||
// check if comment has an avatar
|
||||
$avatar = self::get_avatar_url( $id_or_email->comment_ID );
|
||||
|
||||
if ( $avatar ) {
|
||||
if ( ! isset( $args['class'] ) || ! \is_array( $args['class'] ) ) {
|
||||
$args['class'] = array( 'u-photo' );
|
||||
} else {
|
||||
$args['class'][] = 'u-photo';
|
||||
$args['class'] = \array_unique( $args['class'] );
|
||||
}
|
||||
$args['url'] = $avatar;
|
||||
$args['class'][] = 'avatar-activitypub';
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to retrieve Avatar URL if stored in meta
|
||||
*
|
||||
*
|
||||
* @param int|WP_Comment $comment
|
||||
*
|
||||
* @return string $url
|
||||
*/
|
||||
public static function get_avatar_url( $comment ) {
|
||||
if ( \is_numeric( $comment ) ) {
|
||||
$comment = \get_comment( $comment );
|
||||
}
|
||||
return \get_comment_meta( $comment->comment_ID, 'avatar_url', true );
|
||||
}
|
||||
}
|
149
wp-content/plugins/activitypub/includes/class-admin.php
Normal file
149
wp-content/plugins/activitypub/includes/class-admin.php
Normal file
@ -0,0 +1,149 @@
|
||||
<?php
|
||||
namespace Activitypub;
|
||||
|
||||
/**
|
||||
* ActivityPub Admin Class
|
||||
*
|
||||
* @author Matthias Pfefferle
|
||||
*/
|
||||
class Admin {
|
||||
/**
|
||||
* Initialize the class, registering WordPress hooks
|
||||
*/
|
||||
public static function init() {
|
||||
\add_action( 'admin_menu', array( '\Activitypub\Admin', 'admin_menu' ) );
|
||||
\add_action( 'admin_init', array( '\Activitypub\Admin', 'register_settings' ) );
|
||||
\add_action( 'show_user_profile', array( '\Activitypub\Admin', 'add_fediverse_profile' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add admin menu entry
|
||||
*/
|
||||
public static function admin_menu() {
|
||||
$settings_page = \add_options_page(
|
||||
'ActivityPub',
|
||||
'ActivityPub',
|
||||
'manage_options',
|
||||
'activitypub',
|
||||
array( '\Activitypub\Admin', 'settings_page' )
|
||||
);
|
||||
|
||||
\add_action( 'load-' . $settings_page, array( '\Activitypub\Admin', 'add_settings_help_tab' ) );
|
||||
|
||||
$followers_list_page = \add_users_page( \__( 'Followers', 'activitypub' ), __( 'Followers (Fediverse)', 'activitypub' ), 'read', 'activitypub-followers-list', array( '\Activitypub\Admin', 'followers_list_page' ) );
|
||||
|
||||
\add_action( 'load-' . $followers_list_page, array( '\Activitypub\Admin', 'add_followers_list_help_tab' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Load settings page
|
||||
*/
|
||||
public static function settings_page() {
|
||||
\load_template( \dirname( __FILE__ ) . '/../templates/settings.php' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Load user settings page
|
||||
*/
|
||||
public static function followers_list_page() {
|
||||
\load_template( \dirname( __FILE__ ) . '/../templates/followers-list.php' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register PubSubHubbub settings
|
||||
*/
|
||||
public static function register_settings() {
|
||||
\register_setting(
|
||||
'activitypub', 'activitypub_post_content_type', array(
|
||||
'type' => 'string',
|
||||
'description' => \__( 'Use title and link, summary or full content', 'activitypub' ),
|
||||
'show_in_rest' => array(
|
||||
'schema' => array(
|
||||
'enum' => array( 'title', 'excerpt', 'content' ),
|
||||
),
|
||||
),
|
||||
'default' => 'content',
|
||||
)
|
||||
);
|
||||
\register_setting(
|
||||
'activitypub', 'activitypub_object_type', array(
|
||||
'type' => 'string',
|
||||
'description' => \__( 'The Activity-Object-Type', 'activitypub' ),
|
||||
'show_in_rest' => array(
|
||||
'schema' => array(
|
||||
'enum' => array( 'note', 'article', 'wordpress-post-format' ),
|
||||
),
|
||||
),
|
||||
'default' => 'note',
|
||||
)
|
||||
);
|
||||
\register_setting(
|
||||
'activitypub', 'activitypub_use_shortlink', array(
|
||||
'type' => 'boolean',
|
||||
'description' => \__( 'Use the Shortlink instead of the permalink', 'activitypub' ),
|
||||
'default' => 0,
|
||||
)
|
||||
);
|
||||
\register_setting(
|
||||
'activitypub', 'activitypub_use_hashtags', array(
|
||||
'type' => 'boolean',
|
||||
'description' => \__( 'Add hashtags in the content as native tags and replace the #tag with the tag-link', 'activitypub' ),
|
||||
'default' => 0,
|
||||
)
|
||||
);
|
||||
\register_setting(
|
||||
'activitypub', 'activitypub_add_tags_as_hashtags', array(
|
||||
'type' => 'boolean',
|
||||
'description' => \__( 'Add all tags as hashtags at the end of each activity', 'activitypub' ),
|
||||
'default' => 0,
|
||||
)
|
||||
);
|
||||
\register_setting(
|
||||
'activitypub', 'activitypub_support_post_types', array(
|
||||
'type' => 'string',
|
||||
'description' => \esc_html__( 'Enable ActivityPub support for post types', 'activitypub' ),
|
||||
'show_in_rest' => true,
|
||||
'default' => array( 'post', 'pages' ),
|
||||
)
|
||||
);
|
||||
\register_setting(
|
||||
'activitypub', 'activitypub_blacklist', array(
|
||||
'type' => 'string',
|
||||
'description' => \esc_html__( 'Block fediverse instances', 'activitypub' ),
|
||||
'show_in_rest' => true,
|
||||
'default' => 'gab.com',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public static function add_settings_help_tab() {
|
||||
\get_current_screen()->add_help_tab(
|
||||
array(
|
||||
'id' => 'overview',
|
||||
'title' => \__( 'Overview', 'activitypub' ),
|
||||
'content' =>
|
||||
'<p>' . \__( 'ActivityPub is a decentralized social networking protocol based on the ActivityStreams 2.0 data format. ActivityPub is an official W3C recommended standard published by the W3C Social Web Working Group. It provides a client to server API for creating, updating and deleting content, as well as a federated server to server API for delivering notifications and subscribing to content.', 'activitypub' ) . '</p>',
|
||||
)
|
||||
);
|
||||
|
||||
\get_current_screen()->set_help_sidebar(
|
||||
'<p><strong>' . \__( 'For more information:', 'activitypub' ) . '</strong></p>' .
|
||||
'<p>' . \__( '<a href="https://activitypub.rocks/">Test Suite</a>', 'activitypub' ) . '</p>' .
|
||||
'<p>' . \__( '<a href="https://www.w3.org/TR/activitypub/">W3C Spec</a>', 'activitypub' ) . '</p>' .
|
||||
'<p>' . \__( '<a href="https://github.com/pfefferle/wordpress-activitypub/issues">Give us feedback</a>', 'activitypub' ) . '</p>' .
|
||||
'<hr />' .
|
||||
'<p>' . \__( '<a href="https://notiz.blog/donate">Donate</a>', 'activitypub' ) . '</p>'
|
||||
);
|
||||
}
|
||||
|
||||
public static function add_followers_list_help_tab() {
|
||||
// todo
|
||||
}
|
||||
|
||||
public static function add_fediverse_profile( $user ) {
|
||||
?>
|
||||
<h2><?php \esc_html_e( 'Fediverse', 'activitypub' ); ?></h2>
|
||||
<?php
|
||||
\Activitypub\get_identifier_settings( $user->ID );
|
||||
}
|
||||
}
|
30
wp-content/plugins/activitypub/includes/class-debug.php
Normal file
30
wp-content/plugins/activitypub/includes/class-debug.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
namespace Activitypub;
|
||||
|
||||
/**
|
||||
* ActivityPub Debug Class
|
||||
*
|
||||
* @author Matthias Pfefferle
|
||||
*/
|
||||
class Debug {
|
||||
/**
|
||||
* Initialize the class, registering WordPress hooks
|
||||
*/
|
||||
public static function init() {
|
||||
if ( WP_DEBUG_LOG ) {
|
||||
\add_action( 'activitypub_safe_remote_post_response', array( '\Activitypub\Debug', 'log_remote_post_responses' ), 10, 4 );
|
||||
}
|
||||
}
|
||||
|
||||
public static function log_remote_post_responses( $response, $url, $body, $user_id ) {
|
||||
\error_log( "Request to: {$url} with response: " . \print_r( $response, true ) );
|
||||
}
|
||||
|
||||
public static function write_log( $log ) {
|
||||
if ( \is_array( $log ) || \is_object( $log ) ) {
|
||||
\error_log( \print_r( $log, true ) );
|
||||
} else {
|
||||
\error_log( $log );
|
||||
}
|
||||
}
|
||||
}
|
96
wp-content/plugins/activitypub/includes/class-hashtag.php
Normal file
96
wp-content/plugins/activitypub/includes/class-hashtag.php
Normal file
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
namespace Activitypub;
|
||||
|
||||
/**
|
||||
* ActivityPub Hashtag Class
|
||||
*
|
||||
* @author Matthias Pfefferle
|
||||
*/
|
||||
class Hashtag {
|
||||
/**
|
||||
* Initialize the class, registering WordPress hooks
|
||||
*/
|
||||
public static function init() {
|
||||
if ( '1' === \get_option( 'activitypub_use_hashtags', '1' ) ) {
|
||||
\add_filter( 'wp_insert_post', array( '\Activitypub\Hashtag', 'insert_post' ), 99, 2 );
|
||||
\add_filter( 'the_content', array( '\Activitypub\Hashtag', 'the_content' ), 99, 2 );
|
||||
}
|
||||
if ( '1' === \get_option( 'activitypub_add_tags_as_hashtags', '0' ) ) {
|
||||
\add_filter( 'activitypub_the_summary', array( '\Activitypub\Hashtag', 'add_hashtags_to_content' ), 10, 2 );
|
||||
\add_filter( 'activitypub_the_content', array( '\Activitypub\Hashtag', 'add_hashtags_to_content' ), 10, 2 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter to save #tags as real WordPress tags
|
||||
*
|
||||
* @param int $id the rev-id
|
||||
* @param array $data the post-data as array
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static function insert_post( $id, $data ) {
|
||||
if ( \preg_match_all( '/' . ACTIVITYPUB_HASHTAGS_REGEXP . '/i', $data->post_content, $match ) ) {
|
||||
$tags = \implode( ', ', $match[1] );
|
||||
|
||||
\wp_add_post_tags( $data->post_parent, $tags );
|
||||
}
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter to replace the #tags in the content with links
|
||||
*
|
||||
* @param string $the_content the post-content
|
||||
*
|
||||
* @return string the filtered post-content
|
||||
*/
|
||||
public static function the_content( $the_content ) {
|
||||
$the_content = \preg_replace_callback( '/' . ACTIVITYPUB_HASHTAGS_REGEXP . '/i', array( '\Activitypub\Hashtag', 'replace_with_links' ), $the_content );
|
||||
|
||||
return $the_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* A callback for preg_replace to build the term links
|
||||
*
|
||||
* @param array $result the preg_match results
|
||||
* @return string the final string
|
||||
*/
|
||||
public static function replace_with_links( $result ) {
|
||||
$tag = $result[1];
|
||||
$tag_object = \get_term_by( 'name', $tag, 'post_tag' );
|
||||
|
||||
if ( $tag_object ) {
|
||||
$link = \get_term_link( $tag_object, 'post_tag' );
|
||||
return \sprintf( '<a rel="tag" class="u-tag u-category" href="%s">#%s</a>', $link, $tag );
|
||||
}
|
||||
|
||||
return '#' . $tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all tags as hashtags to the post/summary content
|
||||
*
|
||||
* @param string $content
|
||||
* @param WP_Post $post
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function add_hashtags_to_content( $content, $post ) {
|
||||
$tags = \get_the_tags( $post->ID );
|
||||
|
||||
if ( ! $tags ) {
|
||||
return $content;
|
||||
}
|
||||
|
||||
$hash_tags = array();
|
||||
|
||||
foreach ( $tags as $tag ) {
|
||||
$hash_tags[] = \sprintf( '<a rel="tag" class="u-tag u-category" href="%s">#%s</a>', \get_tag_link( $tag ), $tag->slug );
|
||||
}
|
||||
|
||||
return $content . '<p>' . \implode( ' ', $hash_tags ) . '</p>';
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
namespace Activitypub;
|
||||
|
||||
/**
|
||||
* ActivityPub Health_Check Class
|
||||
*
|
||||
* @author Matthias Pfefferle
|
||||
*/
|
||||
class Health_Check {
|
||||
public static function init() {
|
||||
}
|
||||
}
|
105
wp-content/plugins/activitypub/includes/class-signature.php
Normal file
105
wp-content/plugins/activitypub/includes/class-signature.php
Normal file
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
namespace Activitypub;
|
||||
|
||||
/**
|
||||
* ActivityPub Signature Class
|
||||
*
|
||||
* @author Matthias Pfefferle
|
||||
*/
|
||||
class Signature {
|
||||
|
||||
/**
|
||||
* @param int $user_id
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function get_public_key( $user_id, $force = false ) {
|
||||
$key = \get_user_meta( $user_id, 'magic_sig_public_key' );
|
||||
|
||||
if ( $key && ! $force ) {
|
||||
return $key[0];
|
||||
}
|
||||
|
||||
self::generate_key_pair( $user_id );
|
||||
$key = \get_user_meta( $user_id, 'magic_sig_public_key' );
|
||||
|
||||
return $key[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $user_id
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function get_private_key( $user_id, $force = false ) {
|
||||
$key = \get_user_meta( $user_id, 'magic_sig_private_key' );
|
||||
|
||||
if ( $key && ! $force ) {
|
||||
return $key[0];
|
||||
}
|
||||
|
||||
self::generate_key_pair( $user_id );
|
||||
$key = \get_user_meta( $user_id, 'magic_sig_private_key' );
|
||||
|
||||
return $key[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the pair keys
|
||||
*
|
||||
* @param int $user_id
|
||||
*/
|
||||
public static function generate_key_pair( $user_id ) {
|
||||
$config = array(
|
||||
'digest_alg' => 'sha512',
|
||||
'private_key_bits' => 2048,
|
||||
'private_key_type' => OPENSSL_KEYTYPE_RSA,
|
||||
);
|
||||
|
||||
$key = \openssl_pkey_new( $config );
|
||||
$priv_key = null;
|
||||
|
||||
\openssl_pkey_export( $key, $priv_key );
|
||||
|
||||
// private key
|
||||
\update_user_meta( $user_id, 'magic_sig_private_key', $priv_key );
|
||||
|
||||
$detail = \openssl_pkey_get_details( $key );
|
||||
|
||||
// public key
|
||||
\update_user_meta( $user_id, 'magic_sig_public_key', $detail['key'] );
|
||||
}
|
||||
|
||||
public static function generate_signature( $user_id, $url, $date ) {
|
||||
$key = self::get_private_key( $user_id );
|
||||
|
||||
$url_parts = \wp_parse_url( $url );
|
||||
|
||||
$host = $url_parts['host'];
|
||||
$path = '/';
|
||||
|
||||
// add path
|
||||
if ( ! empty( $url_parts['path'] ) ) {
|
||||
$path = $url_parts['path'];
|
||||
}
|
||||
|
||||
// add query
|
||||
if ( ! empty( $url_parts['query'] ) ) {
|
||||
$path .= '?' . $url_parts['query'];
|
||||
}
|
||||
|
||||
$signed_string = "(request-target): post $path\nhost: $host\ndate: $date";
|
||||
|
||||
$signature = null;
|
||||
\openssl_sign( $signed_string, $signature, $key, OPENSSL_ALGO_SHA256 );
|
||||
$signature = \base64_encode( $signature ); // phpcs:ignore
|
||||
|
||||
$key_id = \get_author_posts_url( $user_id ) . '#main-key';
|
||||
|
||||
return \sprintf( 'keyId="%s",algorithm="rsa-sha256",headers="(request-target) host date",signature="%s"', $key_id, $signature );
|
||||
}
|
||||
|
||||
public static function verify_signature( $headers, $signature ) {
|
||||
|
||||
}
|
||||
}
|
336
wp-content/plugins/activitypub/includes/functions.php
Normal file
336
wp-content/plugins/activitypub/includes/functions.php
Normal file
@ -0,0 +1,336 @@
|
||||
<?php
|
||||
namespace Activitypub;
|
||||
|
||||
/**
|
||||
* Returns the ActivityPub default JSON-context
|
||||
*
|
||||
* @return array the activitypub context
|
||||
*/
|
||||
function get_context() {
|
||||
$context = array(
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
'https://w3id.org/security/v1',
|
||||
array(
|
||||
'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers',
|
||||
'PropertyValue' => 'schema:PropertyValue',
|
||||
'schema' => 'http://schema.org#',
|
||||
'value' => 'schema:value',
|
||||
),
|
||||
);
|
||||
|
||||
return \apply_filters( 'activitypub_json_context', $context );
|
||||
}
|
||||
|
||||
function safe_remote_post( $url, $body, $user_id ) {
|
||||
$date = \gmdate( 'D, d M Y H:i:s T' );
|
||||
$signature = \Activitypub\Signature::generate_signature( $user_id, $url, $date );
|
||||
|
||||
$wp_version = \get_bloginfo( 'version' );
|
||||
$user_agent = \apply_filters( 'http_headers_useragent', 'WordPress/' . $wp_version . '; ' . \get_bloginfo( 'url' ) );
|
||||
$args = array(
|
||||
'timeout' => 100,
|
||||
'limit_response_size' => 1048576,
|
||||
'redirection' => 3,
|
||||
'user-agent' => "$user_agent; ActivityPub",
|
||||
'headers' => array(
|
||||
'Accept' => 'application/activity+json',
|
||||
'Content-Type' => 'application/activity+json',
|
||||
'Signature' => $signature,
|
||||
'Date' => $date,
|
||||
),
|
||||
'body' => $body,
|
||||
);
|
||||
|
||||
$response = \wp_safe_remote_post( $url, $args );
|
||||
|
||||
\do_action( 'activitypub_safe_remote_post_response', $response, $url, $body, $user_id );
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
function safe_remote_get( $url, $user_id ) {
|
||||
$date = \gmdate( 'D, d M Y H:i:s T' );
|
||||
$signature = \Activitypub\Signature::generate_signature( $user_id, $url, $date );
|
||||
|
||||
$wp_version = \get_bloginfo( 'version' );
|
||||
$user_agent = \apply_filters( 'http_headers_useragent', 'WordPress/' . $wp_version . '; ' . \get_bloginfo( 'url' ) );
|
||||
$args = array(
|
||||
'timeout' => 100,
|
||||
'limit_response_size' => 1048576,
|
||||
'redirection' => 3,
|
||||
'user-agent' => "$user_agent; ActivityPub",
|
||||
'headers' => array(
|
||||
'Accept' => 'application/activity+json',
|
||||
'Content-Type' => 'application/activity+json',
|
||||
'Signature' => $signature,
|
||||
'Date' => $date,
|
||||
),
|
||||
);
|
||||
|
||||
$response = \wp_safe_remote_get( $url, $args );
|
||||
|
||||
\do_action( 'activitypub_safe_remote_get_response', $response, $url, $user_id );
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a users WebFinger "resource"
|
||||
*
|
||||
* @param int $user_id
|
||||
*
|
||||
* @return string The user-resource
|
||||
*/
|
||||
function get_webfinger_resource( $user_id ) {
|
||||
// use WebFinger plugin if installed
|
||||
if ( \function_exists( '\get_webfinger_resource' ) ) {
|
||||
return \get_webfinger_resource( $user_id, false );
|
||||
}
|
||||
|
||||
$user = \get_user_by( 'id', $user_id );
|
||||
|
||||
return $user->user_login . '@' . \wp_parse_url( \home_url(), PHP_URL_HOST );
|
||||
}
|
||||
|
||||
/**
|
||||
* [get_metadata_by_actor description]
|
||||
*
|
||||
* @param sting $actor
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function get_remote_metadata_by_actor( $actor ) {
|
||||
$metadata = \get_transient( 'activitypub_' . $actor );
|
||||
|
||||
if ( $metadata ) {
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
if ( ! \wp_http_validate_url( $actor ) ) {
|
||||
return new \WP_Error( 'activitypub_no_valid_actor_url', \__( 'The "actor" is no valid URL', 'activitypub' ), $actor );
|
||||
}
|
||||
|
||||
$user = \get_users( array (
|
||||
'number' => 1,
|
||||
'who' => 'authors',
|
||||
'fields' => 'ID',
|
||||
) );
|
||||
|
||||
// we just need any user to generate a request signature
|
||||
$user_id = \reset( $user );
|
||||
|
||||
$response = \Activitypub\safe_remote_get( $actor, $user_id );
|
||||
|
||||
if ( \is_wp_error( $response ) ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$metadata = \wp_remote_retrieve_body( $response );
|
||||
$metadata = \json_decode( $metadata, true );
|
||||
|
||||
if ( ! $metadata ) {
|
||||
return new \WP_Error( 'activitypub_invalid_json', \__( 'No valid JSON data', 'activitypub' ), $actor );
|
||||
}
|
||||
|
||||
\set_transient( 'activitypub_' . $actor, $metadata, WEEK_IN_SECONDS );
|
||||
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* [get_inbox_by_actor description]
|
||||
* @param [type] $actor [description]
|
||||
* @return [type] [description]
|
||||
*/
|
||||
function get_inbox_by_actor( $actor ) {
|
||||
$metadata = \Activitypub\get_remote_metadata_by_actor( $actor );
|
||||
|
||||
if ( \is_wp_error( $metadata ) ) {
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
if ( isset( $metadata['endpoints'] ) && isset( $metadata['endpoints']['sharedInbox'] ) ) {
|
||||
return $metadata['endpoints']['sharedInbox'];
|
||||
}
|
||||
|
||||
if ( \array_key_exists( 'inbox', $metadata ) ) {
|
||||
return $metadata['inbox'];
|
||||
}
|
||||
|
||||
return new \WP_Error( 'activitypub_no_inbox', __( 'No "Inbox" found', 'activitypub' ), $metadata );
|
||||
}
|
||||
|
||||
/**
|
||||
* [get_inbox_by_actor description]
|
||||
* @param [type] $actor [description]
|
||||
* @return [type] [description]
|
||||
*/
|
||||
function get_publickey_by_actor( $actor, $key_id ) {
|
||||
$metadata = \Activitypub\get_remote_metadata_by_actor( $actor );
|
||||
|
||||
if ( \is_wp_error( $metadata ) ) {
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
if (
|
||||
isset( $metadata['publicKey'] ) &&
|
||||
isset( $metadata['publicKey']['id'] ) &&
|
||||
isset( $metadata['publicKey']['owner'] ) &&
|
||||
isset( $metadata['publicKey']['publicKeyPem'] ) &&
|
||||
$key_id === $metadata['publicKey']['id'] &&
|
||||
$actor === $metadata['publicKey']['owner']
|
||||
) {
|
||||
return $metadata['publicKey']['publicKeyPem'];
|
||||
}
|
||||
|
||||
return new \WP_Error( 'activitypub_no_public_key', \__( 'No "Public-Key" found', 'activitypub' ), $metadata );
|
||||
}
|
||||
|
||||
function get_follower_inboxes( $user_id ) {
|
||||
$followers = \Activitypub\Peer\Followers::get_followers( $user_id );
|
||||
$inboxes = array();
|
||||
|
||||
foreach ( $followers as $follower ) {
|
||||
$inbox = \Activitypub\get_inbox_by_actor( $follower );
|
||||
if ( ! $inbox || \is_wp_error( $inbox ) ) {
|
||||
continue;
|
||||
}
|
||||
// init array if empty
|
||||
if ( ! isset( $inboxes[ $inbox ] ) ) {
|
||||
$inboxes[ $inbox ] = array();
|
||||
}
|
||||
$inboxes[ $inbox ][] = $follower;
|
||||
}
|
||||
|
||||
return $inboxes;
|
||||
}
|
||||
|
||||
function get_identifier_settings( $user_id ) {
|
||||
?>
|
||||
<table class="form-table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label><?php \esc_html_e( 'Profile identifier', 'activitypub' ); ?></label>
|
||||
</th>
|
||||
<td>
|
||||
<p><code><?php echo \esc_html( \Activitypub\get_webfinger_resource( $user_id ) ); ?></code> or <code><?php echo \esc_url( \get_author_posts_url( $user_id ) ); ?></code></p>
|
||||
<?php // translators: the webfinger resource ?>
|
||||
<p class="description"><?php \printf( \esc_html__( 'Try to follow "@%s" in the Mastodon/Friendica search field.', 'activitypub' ), \esc_html( \Activitypub\get_webfinger_resource( $user_id ) ) ); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php
|
||||
}
|
||||
|
||||
function get_followers( $user_id ) {
|
||||
$followers = \Activitypub\Peer\Followers::get_followers( $user_id );
|
||||
|
||||
if ( ! $followers ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
return $followers;
|
||||
}
|
||||
|
||||
function count_followers( $user_id ) {
|
||||
$followers = \Activitypub\get_followers( $user_id );
|
||||
|
||||
return \count( $followers );
|
||||
}
|
||||
|
||||
/**
|
||||
* Examine a url and try to determine the author ID it represents.
|
||||
*
|
||||
* Checks are supposedly from the hosted site blog.
|
||||
*
|
||||
* @param string $url Permalink to check.
|
||||
*
|
||||
* @return int User ID, or 0 on failure.
|
||||
*/
|
||||
function url_to_authorid( $url ) {
|
||||
global $wp_rewrite;
|
||||
|
||||
// check if url hase the same host
|
||||
if ( wp_parse_url( site_url(), PHP_URL_HOST ) !== wp_parse_url( $url, PHP_URL_HOST ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// first, check to see if there is a 'author=N' to match against
|
||||
if ( \preg_match( '/[?&]author=(\d+)/i', $url, $values ) ) {
|
||||
$id = absint( $values[1] );
|
||||
if ( $id ) {
|
||||
return $id;
|
||||
}
|
||||
}
|
||||
|
||||
// check to see if we are using rewrite rules
|
||||
$rewrite = $wp_rewrite->wp_rewrite_rules();
|
||||
|
||||
// not using rewrite rules, and 'author=N' method failed, so we're out of options
|
||||
if ( empty( $rewrite ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// generate rewrite rule for the author url
|
||||
$author_rewrite = $wp_rewrite->get_author_permastruct();
|
||||
$author_regexp = \str_replace( '%author%', '', $author_rewrite );
|
||||
|
||||
// match the rewrite rule with the passed url
|
||||
if ( \preg_match( '/https?:\/\/(.+)' . \preg_quote( $author_regexp, '/' ) . '([^\/]+)/i', $url, $match ) ) {
|
||||
$user = get_user_by( 'slug', $match[2] );
|
||||
if ( $user ) {
|
||||
return $user->ID;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the blacklist from the WordPress options table
|
||||
*
|
||||
* @return array the list of blacklisted hosts
|
||||
*
|
||||
* @uses apply_filters() Calls 'activitypub_blacklist' filter
|
||||
*/
|
||||
function get_blacklist() {
|
||||
$blacklist = \get_option( 'activitypub_blacklist' );
|
||||
$blacklist_hosts = \explode( PHP_EOL, $blacklist );
|
||||
|
||||
// if no values have been set, revert to the defaults
|
||||
if ( ! $blacklist || ! $blacklist_hosts || ! \is_array( $blacklist_hosts ) ) {
|
||||
$blacklist_hosts = array(
|
||||
'gab.com',
|
||||
);
|
||||
}
|
||||
|
||||
// clean out any blank values
|
||||
foreach ( $blacklist_hosts as $key => $value ) {
|
||||
if ( empty( $value ) ) {
|
||||
unset( $blacklist_hosts[ $key ] );
|
||||
} else {
|
||||
$blacklist_hosts[ $key ] = \trim( $blacklist_hosts[ $key ] );
|
||||
}
|
||||
}
|
||||
|
||||
return \apply_filters( 'activitypub_blacklist', $blacklist_hosts );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an URL is blacklisted
|
||||
*
|
||||
* @param string $url an URL to check
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
function is_blacklisted( $url ) {
|
||||
foreach ( \ActivityPub\get_blacklist() as $blacklisted_host ) {
|
||||
if ( \strpos( $url, $blacklisted_host ) !== false ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
<?php
|
||||
namespace Activitypub\Model;
|
||||
|
||||
/**
|
||||
* ActivityPub Post Class
|
||||
*
|
||||
* @author Matthias Pfefferle
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitypub/
|
||||
*/
|
||||
class Activity {
|
||||
private $context = array( 'https://www.w3.org/ns/activitystreams' );
|
||||
private $published = '';
|
||||
private $id = '';
|
||||
private $type = 'Create';
|
||||
private $actor = '';
|
||||
private $to = array( 'https://www.w3.org/ns/activitystreams#Public' );
|
||||
private $cc = array( 'https://www.w3.org/ns/activitystreams#Public' );
|
||||
private $object = null;
|
||||
|
||||
const TYPE_SIMPLE = 'simple';
|
||||
const TYPE_FULL = 'full';
|
||||
const TYPE_NONE = 'none';
|
||||
|
||||
public function __construct( $type = 'Create', $context = self::TYPE_SIMPLE ) {
|
||||
if ( 'none' === $context ) {
|
||||
$this->context = null;
|
||||
} elseif ( 'full' === $context ) {
|
||||
$this->context = \Activitypub\get_context();
|
||||
}
|
||||
|
||||
$this->type = \ucfirst( $type );
|
||||
$this->published = \date( 'Y-m-d\TH:i:s\Z', \strtotime( 'now' ) );
|
||||
}
|
||||
|
||||
public function __call( $method, $params ) {
|
||||
$var = \strtolower( \substr( $method, 4 ) );
|
||||
|
||||
if ( \strncasecmp( $method, 'get', 3 ) === 0 ) {
|
||||
return $this->$var;
|
||||
}
|
||||
|
||||
if ( \strncasecmp( $method, 'set', 3 ) === 0 ) {
|
||||
$this->$var = $params[0];
|
||||
}
|
||||
}
|
||||
|
||||
public function from_post( $object ) {
|
||||
$this->object = $object;
|
||||
$this->published = $object['published'];
|
||||
$this->actor = $object['attributedTo'];
|
||||
$this->id = $object['id'];
|
||||
}
|
||||
|
||||
public function from_comment( $object ) {
|
||||
|
||||
}
|
||||
|
||||
public function to_array() {
|
||||
$array = \get_object_vars( $this );
|
||||
|
||||
if ( $this->context ) {
|
||||
$array = array( '@context' => $this->context ) + $array;
|
||||
}
|
||||
|
||||
unset( $array['context'] );
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
public function to_json() {
|
||||
return \wp_json_encode( $this->to_array(), JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_QUOT );
|
||||
}
|
||||
|
||||
public function to_simple_array() {
|
||||
$activity = array(
|
||||
'@context' => $this->context,
|
||||
'type' => $this->type,
|
||||
'actor' => $this->actor,
|
||||
'object' => $this->object,
|
||||
'to' => $this->to,
|
||||
'cc' => $this->cc,
|
||||
);
|
||||
|
||||
if ( $this->id ) {
|
||||
$activity['id'] = $this->id;
|
||||
}
|
||||
|
||||
return $activity;
|
||||
}
|
||||
|
||||
public function to_simple_json() {
|
||||
return \wp_json_encode( $this->to_simple_array(), JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_QUOT );
|
||||
}
|
||||
}
|
320
wp-content/plugins/activitypub/includes/model/class-post.php
Normal file
320
wp-content/plugins/activitypub/includes/model/class-post.php
Normal file
@ -0,0 +1,320 @@
|
||||
<?php
|
||||
namespace Activitypub\Model;
|
||||
|
||||
/**
|
||||
* ActivityPub Post Class
|
||||
*
|
||||
* @author Matthias Pfefferle
|
||||
*/
|
||||
class Post {
|
||||
private $post;
|
||||
|
||||
/**
|
||||
* Initialize the class, registering WordPress hooks
|
||||
*/
|
||||
public static function init() {
|
||||
\add_filter( 'activitypub_the_summary', array( '\Activitypub\Model\Post', 'add_backlink_to_content' ), 15, 2 );
|
||||
\add_filter( 'activitypub_the_content', array( '\Activitypub\Model\Post', 'add_backlink_to_content' ), 15, 2 );
|
||||
}
|
||||
|
||||
public function __construct( $post = null ) {
|
||||
$this->post = \get_post( $post );
|
||||
}
|
||||
|
||||
public function get_post() {
|
||||
return $this->post;
|
||||
}
|
||||
|
||||
public function get_post_author() {
|
||||
return $this->post->post_author;
|
||||
}
|
||||
|
||||
public function to_array() {
|
||||
$post = $this->post;
|
||||
|
||||
$array = array(
|
||||
'id' => \get_permalink( $post ),
|
||||
'type' => $this->get_object_type(),
|
||||
'published' => \date( 'Y-m-d\TH:i:s\Z', \strtotime( $post->post_date ) ),
|
||||
'attributedTo' => \get_author_posts_url( $post->post_author ),
|
||||
'summary' => $this->get_the_title(),
|
||||
'inReplyTo' => null,
|
||||
'content' => $this->get_the_content(),
|
||||
'contentMap' => array(
|
||||
\strstr( \get_locale(), '_', true ) => $this->get_the_content(),
|
||||
),
|
||||
'to' => array( 'https://www.w3.org/ns/activitystreams#Public' ),
|
||||
'cc' => array( 'https://www.w3.org/ns/activitystreams#Public' ),
|
||||
'attachment' => $this->get_attachments(),
|
||||
'tag' => $this->get_tags(),
|
||||
);
|
||||
|
||||
return \apply_filters( 'activitypub_post', $array );
|
||||
}
|
||||
|
||||
public function to_json() {
|
||||
return \wp_json_encode( $this->to_array(), JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_QUOT );
|
||||
}
|
||||
|
||||
public function get_attachments() {
|
||||
$max_images = \apply_filters( 'activitypub_max_images', 3 );
|
||||
|
||||
$images = array();
|
||||
|
||||
// max images can't be negative or zero
|
||||
if ( $max_images <= 0 ) {
|
||||
$max_images = 1;
|
||||
}
|
||||
|
||||
$id = $this->post->ID;
|
||||
|
||||
$image_ids = array();
|
||||
// list post thumbnail first if this post has one
|
||||
if ( \function_exists( 'has_post_thumbnail' ) && \has_post_thumbnail( $id ) ) {
|
||||
$image_ids[] = \get_post_thumbnail_id( $id );
|
||||
$max_images--;
|
||||
}
|
||||
// then list any image attachments
|
||||
$query = new \WP_Query(
|
||||
array(
|
||||
'post_parent' => $id,
|
||||
'post_status' => 'inherit',
|
||||
'post_type' => 'attachment',
|
||||
'post_mime_type' => 'image',
|
||||
'order' => 'ASC',
|
||||
'orderby' => 'menu_order ID',
|
||||
'posts_per_page' => $max_images,
|
||||
)
|
||||
);
|
||||
foreach ( $query->get_posts() as $attachment ) {
|
||||
if ( ! \in_array( $attachment->ID, $image_ids, true ) ) {
|
||||
$image_ids[] = $attachment->ID;
|
||||
}
|
||||
}
|
||||
|
||||
$image_ids = \array_unique( $image_ids );
|
||||
|
||||
// get URLs for each image
|
||||
foreach ( $image_ids as $id ) {
|
||||
$alt = \get_post_meta( $id, '_wp_attachment_image_alt', true );
|
||||
$thumbnail = \wp_get_attachment_image_src( $id, 'full' );
|
||||
$mimetype = \get_post_mime_type( $id );
|
||||
|
||||
if ( $thumbnail ) {
|
||||
$image = array(
|
||||
'type' => 'Image',
|
||||
'url' => $thumbnail[0],
|
||||
'mediaType' => $mimetype
|
||||
);
|
||||
if ( $alt ) {
|
||||
$image['name'] = $alt;
|
||||
}
|
||||
$images[] = $image;
|
||||
}
|
||||
}
|
||||
|
||||
return $images;
|
||||
}
|
||||
|
||||
public function get_tags() {
|
||||
$tags = array();
|
||||
|
||||
$post_tags = \get_the_tags( $this->post->ID );
|
||||
if ( $post_tags ) {
|
||||
foreach ( $post_tags as $post_tag ) {
|
||||
$tag = array(
|
||||
'type' => 'Hashtag',
|
||||
'href' => \get_tag_link( $post_tag->term_id ),
|
||||
'name' => '#' . $post_tag->slug,
|
||||
);
|
||||
$tags[] = $tag;
|
||||
}
|
||||
}
|
||||
|
||||
return $tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the as2 object-type for a given post
|
||||
*
|
||||
* @param string $type the object-type
|
||||
* @param Object $post the post-object
|
||||
*
|
||||
* @return string the object-type
|
||||
*/
|
||||
public function get_object_type() {
|
||||
if ( 'wordpress-post-format' !== \get_option( 'activitypub_object_type', 'note' ) ) {
|
||||
return \ucfirst( \get_option( 'activitypub_object_type', 'note' ) );
|
||||
}
|
||||
|
||||
$post_type = \get_post_type( $this->post );
|
||||
switch ( $post_type ) {
|
||||
case 'post':
|
||||
$post_format = \get_post_format( $this->post );
|
||||
switch ( $post_format ) {
|
||||
case 'aside':
|
||||
case 'status':
|
||||
case 'quote':
|
||||
case 'note':
|
||||
$object_type = 'Note';
|
||||
break;
|
||||
case 'gallery':
|
||||
case 'image':
|
||||
$object_type = 'Image';
|
||||
break;
|
||||
case 'video':
|
||||
$object_type = 'Video';
|
||||
break;
|
||||
case 'audio':
|
||||
$object_type = 'Audio';
|
||||
break;
|
||||
default:
|
||||
$object_type = 'Article';
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'page':
|
||||
$object_type = 'Page';
|
||||
break;
|
||||
case 'attachment':
|
||||
$mime_type = \get_post_mime_type();
|
||||
$media_type = \preg_replace( '/(\/[a-zA-Z]+)/i', '', $mime_type );
|
||||
switch ( $media_type ) {
|
||||
case 'audio':
|
||||
$object_type = 'Audio';
|
||||
break;
|
||||
case 'video':
|
||||
$object_type = 'Video';
|
||||
break;
|
||||
case 'image':
|
||||
$object_type = 'Image';
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$object_type = 'Article';
|
||||
break;
|
||||
}
|
||||
|
||||
return $object_type;
|
||||
}
|
||||
|
||||
public function get_the_content() {
|
||||
if ( 'excerpt' === \get_option( 'activitypub_post_content_type', 'content' ) ) {
|
||||
return $this->get_the_post_summary();
|
||||
}
|
||||
|
||||
if ( 'title' === \get_option( 'activitypub_post_content_type', 'content' ) ) {
|
||||
return $this->get_the_title();
|
||||
}
|
||||
|
||||
return $this->get_the_post_content();
|
||||
}
|
||||
|
||||
public function get_the_title() {
|
||||
if ( 'Article' === $this->get_object_type() ) {
|
||||
$title = \get_the_title( $this->post );
|
||||
|
||||
return \html_entity_decode( $title, ENT_QUOTES, 'UTF-8' );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the excerpt for a post for use outside of the loop.
|
||||
*
|
||||
* @param int Optional excerpt length.
|
||||
*
|
||||
* @return string The excerpt.
|
||||
*/
|
||||
public function get_the_post_excerpt( $excerpt_length = 400 ) {
|
||||
$post = $this->post;
|
||||
|
||||
$excerpt = \get_post_field( 'post_excerpt', $post );
|
||||
|
||||
if ( '' === $excerpt ) {
|
||||
|
||||
$content = \get_post_field( 'post_content', $post );
|
||||
|
||||
// An empty string will make wp_trim_excerpt do stuff we do not want.
|
||||
if ( '' !== $content ) {
|
||||
|
||||
$excerpt = \strip_shortcodes( $content );
|
||||
|
||||
/** This filter is documented in wp-includes/post-template.php */
|
||||
$excerpt = \apply_filters( 'the_content', $excerpt );
|
||||
$excerpt = \str_replace( ']]>', ']]>', $excerpt );
|
||||
|
||||
$excerpt_length = \apply_filters( 'excerpt_length', $excerpt_length );
|
||||
|
||||
/** This filter is documented in wp-includes/formatting.php */
|
||||
$excerpt_more = \apply_filters( 'excerpt_more', ' [...]' );
|
||||
|
||||
$excerpt = \wp_trim_words( $excerpt, $excerpt_length, $excerpt_more );
|
||||
}
|
||||
}
|
||||
|
||||
return $excerpt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the content for a post for use outside of the loop.
|
||||
*
|
||||
* @return string The content.
|
||||
*/
|
||||
public function get_the_post_content() {
|
||||
$post = $this->post;
|
||||
|
||||
$content = \get_post_field( 'post_content', $post );
|
||||
|
||||
$filtered_content = \apply_filters( 'the_content', $content );
|
||||
$filtered_content = \apply_filters( 'activitypub_the_content', $filtered_content, $this->post );
|
||||
|
||||
$decoded_content = \html_entity_decode( $filtered_content, ENT_QUOTES, 'UTF-8' );
|
||||
|
||||
$allowed_html = \apply_filters( 'activitypub_allowed_html', '<a><p><ul><ol><li><code><blockquote><pre>' );
|
||||
|
||||
return \trim( \preg_replace( '/[\r\n]{2,}/', '', \strip_tags( $decoded_content, $allowed_html ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the excerpt for a post for use outside of the loop.
|
||||
*
|
||||
* @param int Optional excerpt length.
|
||||
*
|
||||
* @return string The excerpt.
|
||||
*/
|
||||
public function get_the_post_summary( $summary_length = 400 ) {
|
||||
$summary = $this->get_the_post_excerpt( $summary_length );
|
||||
|
||||
$filtered_summary = \apply_filters( 'the_excerpt', $summary );
|
||||
$filtered_summary = \apply_filters( 'activitypub_the_summary', $filtered_summary, $this->post );
|
||||
|
||||
$decoded_summary = \html_entity_decode( $filtered_summary, ENT_QUOTES, 'UTF-8' );
|
||||
|
||||
$allowed_html = \apply_filters( 'activitypub_allowed_html', '<a><p>' );
|
||||
|
||||
return \trim( \preg_replace( '/[\r\n]{2,}/', '', \strip_tags( $decoded_summary, $allowed_html ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a backlink to the post/summary content
|
||||
*
|
||||
* @param string $content
|
||||
* @param WP_Post $post
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function add_backlink_to_content( $content, $post ) {
|
||||
$link = '';
|
||||
|
||||
if ( \get_option( 'activitypub_use_shortlink', 0 ) ) {
|
||||
$link = \esc_url( \wp_get_shortlink( $post->ID ) );
|
||||
} else {
|
||||
$link = \esc_url( \get_permalink( $post->ID ) );
|
||||
}
|
||||
|
||||
return $content . '<p><a href="' . $link . '">' . $link . '</a></p>';
|
||||
}
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
namespace Activitypub\Peer;
|
||||
|
||||
/**
|
||||
* ActivityPub Followers DB-Class
|
||||
*
|
||||
* @author Matthias Pfefferle
|
||||
*/
|
||||
class Followers {
|
||||
|
||||
public static function get_followers( $author_id ) {
|
||||
$followers = \get_user_option( 'activitypub_followers', $author_id );
|
||||
|
||||
if ( ! $followers ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
foreach ( $followers as $key => $follower ) {
|
||||
if (
|
||||
\is_array( $follower ) &&
|
||||
isset( $follower['type'] ) &&
|
||||
'Person' === $follower['type'] &&
|
||||
isset( $follower['id'] ) &&
|
||||
false !== \filter_var( $follower['id'], FILTER_VALIDATE_URL )
|
||||
) {
|
||||
$followers[ $key ] = $follower['id'];
|
||||
}
|
||||
}
|
||||
|
||||
return $followers;
|
||||
}
|
||||
|
||||
public static function count_followers( $author_id ) {
|
||||
$followers = self::get_followers( $author_id );
|
||||
|
||||
return \count( $followers );
|
||||
}
|
||||
|
||||
public static function add_follower( $actor, $author_id ) {
|
||||
$followers = \get_user_option( 'activitypub_followers', $author_id );
|
||||
|
||||
if ( ! \is_string( $actor ) ) {
|
||||
if (
|
||||
\is_array( $actor ) &&
|
||||
isset( $actor['type'] ) &&
|
||||
'Person' === $actor['type'] &&
|
||||
isset( $actor['id'] ) &&
|
||||
false !== \filter_var( $actor['id'], FILTER_VALIDATE_URL )
|
||||
) {
|
||||
$actor = $actor['id'];
|
||||
}
|
||||
|
||||
return new \WP_Error( 'invalid_actor_object', \__( 'Unknown Actor schema', 'activitypub' ), array(
|
||||
'status' => 404,
|
||||
) );
|
||||
}
|
||||
|
||||
if ( ! \is_array( $followers ) ) {
|
||||
$followers = array( $actor );
|
||||
} else {
|
||||
$followers[] = $actor;
|
||||
}
|
||||
|
||||
$followers = \array_unique( $followers );
|
||||
|
||||
\update_user_meta( $author_id, 'activitypub_followers', $followers );
|
||||
}
|
||||
|
||||
public static function remove_follower( $actor, $author_id ) {
|
||||
$followers = \get_user_option( 'activitypub_followers', $author_id );
|
||||
|
||||
foreach ( $followers as $key => $value ) {
|
||||
if ( $value === $actor ) {
|
||||
unset( $followers[ $key ] );
|
||||
}
|
||||
}
|
||||
|
||||
\update_user_meta( $author_id, 'activitypub_followers', $followers );
|
||||
}
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
namespace Activitypub\Rest;
|
||||
|
||||
/**
|
||||
* ActivityPub Followers REST-Class
|
||||
*
|
||||
* @author Matthias Pfefferle
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitypub/#followers
|
||||
*/
|
||||
class Followers {
|
||||
/**
|
||||
* Initialize the class, registering WordPress hooks
|
||||
*/
|
||||
public static function init() {
|
||||
\add_action( 'rest_api_init', array( '\Activitypub\Rest\Followers', 'register_routes' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register routes
|
||||
*/
|
||||
public static function register_routes() {
|
||||
\register_rest_route(
|
||||
'activitypub/1.0', '/users/(?P<id>\d+)/followers', array(
|
||||
array(
|
||||
'methods' => \WP_REST_Server::READABLE,
|
||||
'callback' => array( '\Activitypub\Rest\Followers', 'get' ),
|
||||
'args' => self::request_parameters(),
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle GET request
|
||||
*
|
||||
* @param WP_REST_Request $request
|
||||
*
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public static function get( $request ) {
|
||||
$user_id = $request->get_param( 'id' );
|
||||
$user = \get_user_by( 'ID', $user_id );
|
||||
|
||||
if ( ! $user ) {
|
||||
return new \WP_Error( 'rest_invalid_param', \__( 'User not found', 'activitypub' ), array(
|
||||
'status' => 404,
|
||||
'params' => array(
|
||||
'user_id' => \__( 'User not found', 'activitypub' ),
|
||||
),
|
||||
) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Action triggerd prior to the ActivityPub profile being created and sent to the client
|
||||
*/
|
||||
\do_action( 'activitypub_outbox_pre' );
|
||||
|
||||
$json = new \stdClass();
|
||||
|
||||
$json->{'@context'} = \Activitypub\get_context();
|
||||
|
||||
$json->partOf = \get_rest_url( null, "/activitypub/1.0/users/$user_id/followers" ); // phpcs:ignore
|
||||
$json->totalItems = \Activitypub\count_followers( $user_id ); // phpcs:ignore
|
||||
$json->orderedItems = \Activitypub\Peer\Followers::get_followers( $user_id ); // phpcs:ignore
|
||||
|
||||
$json->first = $json->partOf; // phpcs:ignore
|
||||
|
||||
$json->first = \get_rest_url( null, "/activitypub/1.0/users/$user_id/followers" );
|
||||
|
||||
$response = new \WP_REST_Response( $json, 200 );
|
||||
$response->header( 'Content-Type', 'application/activity+json' );
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* The supported parameters
|
||||
*
|
||||
* @return array list of parameters
|
||||
*/
|
||||
public static function request_parameters() {
|
||||
$params = array();
|
||||
|
||||
$params['page'] = array(
|
||||
'type' => 'integer',
|
||||
);
|
||||
|
||||
$params['id'] = array(
|
||||
'required' => true,
|
||||
'type' => 'integer',
|
||||
);
|
||||
|
||||
return $params;
|
||||
}
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
namespace Activitypub\Rest;
|
||||
|
||||
/**
|
||||
* ActivityPub Following REST-Class
|
||||
*
|
||||
* @author Matthias Pfefferle
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitypub/#following
|
||||
*/
|
||||
class Following {
|
||||
/**
|
||||
* Initialize the class, registering WordPress hooks
|
||||
*/
|
||||
public static function init() {
|
||||
\add_action( 'rest_api_init', array( '\Activitypub\Rest\Following', 'register_routes' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register routes
|
||||
*/
|
||||
public static function register_routes() {
|
||||
\register_rest_route(
|
||||
'activitypub/1.0', '/users/(?P<id>\d+)/following', array(
|
||||
array(
|
||||
'methods' => \WP_REST_Server::READABLE,
|
||||
'callback' => array( '\Activitypub\Rest\Following', 'get' ),
|
||||
'args' => self::request_parameters(),
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle GET request
|
||||
*
|
||||
* @param WP_REST_Request $request
|
||||
*
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public static function get( $request ) {
|
||||
$user_id = $request->get_param( 'id' );
|
||||
$user = \get_user_by( 'ID', $user_id );
|
||||
|
||||
if ( ! $user ) {
|
||||
return new \WP_Error( 'rest_invalid_param', \__( 'User not found', 'activitypub' ), array(
|
||||
'status' => 404,
|
||||
'params' => array(
|
||||
'user_id' => \__( 'User not found', 'activitypub' ),
|
||||
),
|
||||
) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Action triggerd prior to the ActivityPub profile being created and sent to the client
|
||||
*/
|
||||
\do_action( 'activitypub_outbox_pre' );
|
||||
|
||||
$json = new \stdClass();
|
||||
|
||||
$json->{'@context'} = \Activitypub\get_context();
|
||||
|
||||
$json->partOf = \get_rest_url( null, "/activitypub/1.0/users/$user_id/following" ); // phpcs:ignore
|
||||
$json->totalItems = 0; // phpcs:ignore
|
||||
$json->orderedItems = array(); // phpcs:ignore
|
||||
|
||||
$json->first = $json->partOf; // phpcs:ignore
|
||||
|
||||
$json->first = \get_rest_url( null, "/activitypub/1.0/users/$user_id/following" );
|
||||
|
||||
$response = new \WP_REST_Response( $json, 200 );
|
||||
$response->header( 'Content-Type', 'application/activity+json' );
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* The supported parameters
|
||||
*
|
||||
* @return array list of parameters
|
||||
*/
|
||||
public static function request_parameters() {
|
||||
$params = array();
|
||||
|
||||
$params['page'] = array(
|
||||
'type' => 'integer',
|
||||
);
|
||||
|
||||
$params['id'] = array(
|
||||
'required' => true,
|
||||
'type' => 'integer',
|
||||
);
|
||||
|
||||
return $params;
|
||||
}
|
||||
}
|
271
wp-content/plugins/activitypub/includes/rest/class-inbox.php
Normal file
271
wp-content/plugins/activitypub/includes/rest/class-inbox.php
Normal file
@ -0,0 +1,271 @@
|
||||
<?php
|
||||
namespace Activitypub\Rest;
|
||||
|
||||
/**
|
||||
* ActivityPub Inbox REST-Class
|
||||
*
|
||||
* @author Matthias Pfefferle
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitypub/#inbox
|
||||
*/
|
||||
class Inbox {
|
||||
/**
|
||||
* Initialize the class, registering WordPress hooks
|
||||
*/
|
||||
public static function init() {
|
||||
\add_action( 'rest_api_init', array( '\Activitypub\Rest\Inbox', 'register_routes' ) );
|
||||
\add_filter( 'rest_pre_serve_request', array( '\Activitypub\Rest\Inbox', 'serve_request' ), 11, 4 );
|
||||
\add_action( 'activitypub_inbox_follow', array( '\Activitypub\Rest\Inbox', 'handle_follow' ), 10, 2 );
|
||||
\add_action( 'activitypub_inbox_unfollow', array( '\Activitypub\Rest\Inbox', 'handle_unfollow' ), 10, 2 );
|
||||
//\add_action( 'activitypub_inbox_like', array( '\Activitypub\Rest\Inbox', 'handle_reaction' ), 10, 2 );
|
||||
//\add_action( 'activitypub_inbox_announce', array( '\Activitypub\Rest\Inbox', 'handle_reaction' ), 10, 2 );
|
||||
\add_action( 'activitypub_inbox_create', array( '\Activitypub\Rest\Inbox', 'handle_create' ), 10, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register routes
|
||||
*/
|
||||
public static function register_routes() {
|
||||
\register_rest_route(
|
||||
'activitypub/1.0', '/inbox', array(
|
||||
array(
|
||||
'methods' => \WP_REST_Server::EDITABLE,
|
||||
'callback' => array( '\Activitypub\Rest\Inbox', 'shared_inbox' ),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
\register_rest_route(
|
||||
'activitypub/1.0', '/users/(?P<user_id>\d+)/inbox', array(
|
||||
array(
|
||||
'methods' => \WP_REST_Server::EDITABLE,
|
||||
'callback' => array( '\Activitypub\Rest\Inbox', 'user_inbox' ),
|
||||
'args' => self::request_parameters(),
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hooks into the REST API request to verify the signature.
|
||||
*
|
||||
* @param bool $served Whether the request has already been served.
|
||||
* @param WP_HTTP_ResponseInterface $result Result to send to the client. Usually a WP_REST_Response.
|
||||
* @param WP_REST_Request $request Request used to generate the response.
|
||||
* @param WP_REST_Server $server Server instance.
|
||||
*
|
||||
* @return true
|
||||
*/
|
||||
public static function serve_request( $served, $result, $request, $server ) {
|
||||
if ( '/activitypub' !== \substr( $request->get_route(), 0, 12 ) ) {
|
||||
return $served;
|
||||
}
|
||||
|
||||
$signature = $request->get_header( 'signature' );
|
||||
|
||||
if ( ! $signature ) {
|
||||
return $served;
|
||||
}
|
||||
|
||||
$headers = $request->get_headers();
|
||||
|
||||
// verify signature
|
||||
//\Activitypub\Signature::verify_signature( $headers, $key );
|
||||
|
||||
return $served;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the user-inbox
|
||||
*
|
||||
* @param WP_REST_Request $request
|
||||
*
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public static function user_inbox( $request ) {
|
||||
$user_id = $request->get_param( 'user_id' );
|
||||
|
||||
$data = $request->get_params();
|
||||
$type = $request->get_param( 'type' );
|
||||
|
||||
\do_action( 'activitypub_inbox', $data, $user_id, $type );
|
||||
\do_action( "activitypub_inbox_{$type}", $data, $user_id );
|
||||
|
||||
return new \WP_REST_Response( array(), 202 );
|
||||
}
|
||||
|
||||
/**
|
||||
* The shared inbox
|
||||
*
|
||||
* @param [type] $request [description]
|
||||
*
|
||||
* @return WP_Error not yet implemented
|
||||
*/
|
||||
public static function shared_inbox( $request ) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The supported parameters
|
||||
*
|
||||
* @return array list of parameters
|
||||
*/
|
||||
public static function request_parameters() {
|
||||
$params = array();
|
||||
|
||||
$params['page'] = array(
|
||||
'type' => 'integer',
|
||||
);
|
||||
|
||||
$params['user_id'] = array(
|
||||
'required' => true,
|
||||
'type' => 'integer',
|
||||
);
|
||||
|
||||
$params['id'] = array(
|
||||
'required' => true,
|
||||
'type' => 'string',
|
||||
'validate_callback' => function( $param, $request, $key ) {
|
||||
if ( ! \is_string( $param ) ) {
|
||||
$param = $param['id'];
|
||||
}
|
||||
return ! \Activitypub\is_blacklisted( $param );
|
||||
},
|
||||
'sanitize_callback' => 'esc_url_raw',
|
||||
);
|
||||
|
||||
$params['actor'] = array(
|
||||
'required' => true,
|
||||
'type' => array( 'object', 'string' ),
|
||||
'validate_callback' => function( $param, $request, $key ) {
|
||||
if ( ! \is_string( $param ) ) {
|
||||
$param = $param['id'];
|
||||
}
|
||||
return ! \Activitypub\is_blacklisted( $param );
|
||||
},
|
||||
'sanitize_callback' => function( $param, $request, $key ) {
|
||||
if ( ! \is_string( $param ) ) {
|
||||
$param = $param['id'];
|
||||
}
|
||||
return \esc_url_raw( $param );
|
||||
},
|
||||
);
|
||||
|
||||
$params['type'] = array(
|
||||
'required' => true,
|
||||
'type' => 'enum',
|
||||
'enum' => array( 'Create' ),
|
||||
'sanitize_callback' => function( $param, $request, $key ) {
|
||||
return \strtolower( $param );
|
||||
},
|
||||
);
|
||||
|
||||
$params['object'] = array(
|
||||
'required' => true,
|
||||
'type' => 'object',
|
||||
);
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles "Follow" requests
|
||||
*
|
||||
* @param array $object The activity-object
|
||||
* @param int $user_id The id of the local blog-user
|
||||
*/
|
||||
public static function handle_follow( $object, $user_id ) {
|
||||
// save follower
|
||||
\Activitypub\Peer\Followers::add_follower( $object['actor'], $user_id );
|
||||
|
||||
// get inbox
|
||||
$inbox = \Activitypub\get_inbox_by_actor( $object['actor'] );
|
||||
|
||||
// send "Accept" activity
|
||||
$activity = new \Activitypub\Model\Activity( 'Accept', \Activitypub\Model\Activity::TYPE_SIMPLE );
|
||||
$activity->set_object( $object );
|
||||
$activity->set_actor( \get_author_posts_url( $user_id ) );
|
||||
$activity->set_to( $object['actor'] );
|
||||
$activity->set_id( \get_author_posts_url( $user_id ) . '#follow' . \preg_replace( '~^https?://~', '', $object['actor'] ) );
|
||||
|
||||
$activity = $activity->to_simple_json();
|
||||
|
||||
$response = \Activitypub\safe_remote_post( $inbox, $activity, $user_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles "Unfollow" requests
|
||||
*
|
||||
* @param array $object The activity-object
|
||||
* @param int $user_id The id of the local blog-user
|
||||
*/
|
||||
public static function handle_unfollow( $object, $user_id ) {
|
||||
\Activitypub\Peer\Followers::remove_follower( $object['actor'], $user_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles "Reaction" requests
|
||||
*
|
||||
* @param array $object The activity-object
|
||||
* @param int $user_id The id of the local blog-user
|
||||
*/
|
||||
public static function handle_reaction( $object, $user_id ) {
|
||||
$meta = \Activitypub\get_remote_metadata_by_actor( $object['actor'] );
|
||||
|
||||
$commentdata = array(
|
||||
'comment_post_ID' => \url_to_postid( $object['object'] ),
|
||||
'comment_author' => \esc_attr( $meta['name'] ),
|
||||
'comment_author_email' => '',
|
||||
'comment_author_url' => \esc_url_raw( $object['actor'] ),
|
||||
'comment_content' => \esc_url_raw( $object['actor'] ),
|
||||
'comment_type' => \esc_attr( \strtolower( $object['type'] ) ),
|
||||
'comment_parent' => 0,
|
||||
'comment_meta' => array(
|
||||
'source_url' => \esc_url_raw( $object['id'] ),
|
||||
'avatar_url' => \esc_url_raw( $meta['icon']['url'] ),
|
||||
'protocol' => 'activitypub',
|
||||
),
|
||||
);
|
||||
|
||||
// disable flood control
|
||||
\remove_action( 'check_comment_flood', 'check_comment_flood_db', 10 );
|
||||
|
||||
$state = \wp_new_comment( $commentdata, true );
|
||||
|
||||
// re-add flood control
|
||||
\add_action( 'check_comment_flood', 'check_comment_flood_db', 10, 4 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles "Create" requests
|
||||
*
|
||||
* @param array $object The activity-object
|
||||
* @param int $user_id The id of the local blog-user
|
||||
*/
|
||||
public static function handle_create( $object, $user_id ) {
|
||||
$meta = \Activitypub\get_remote_metadata_by_actor( $object['actor'] );
|
||||
|
||||
$commentdata = array(
|
||||
'comment_post_ID' => \url_to_postid( $object['object']['inReplyTo'] ),
|
||||
'comment_author' => \esc_attr( $meta['name'] ),
|
||||
'comment_author_url' => \esc_url_raw( $object['actor'] ),
|
||||
'comment_content' => \wp_filter_kses( $object['object']['content'] ),
|
||||
'comment_type' => '',
|
||||
'comment_author_email' => '',
|
||||
'comment_parent' => 0,
|
||||
'comment_meta' => array(
|
||||
'source_url' => \esc_url_raw( $object['object']['url'] ),
|
||||
'avatar_url' => \esc_url_raw( $meta['icon']['url'] ),
|
||||
'protocol' => 'activitypub',
|
||||
),
|
||||
);
|
||||
|
||||
// disable flood control
|
||||
\remove_action( 'check_comment_flood', 'check_comment_flood_db', 10 );
|
||||
|
||||
$state = \wp_new_comment( $commentdata, true );
|
||||
|
||||
// re-add flood control
|
||||
\add_action( 'check_comment_flood', 'check_comment_flood_db', 10, 4 );
|
||||
}
|
||||
}
|
191
wp-content/plugins/activitypub/includes/rest/class-nodeinfo.php
Normal file
191
wp-content/plugins/activitypub/includes/rest/class-nodeinfo.php
Normal file
@ -0,0 +1,191 @@
|
||||
<?php
|
||||
namespace Activitypub\Rest;
|
||||
|
||||
/**
|
||||
* ActivityPub NodeInfo REST-Class
|
||||
*
|
||||
* @author Matthias Pfefferle
|
||||
*
|
||||
* @see http://nodeinfo.diaspora.software/
|
||||
*/
|
||||
class Nodeinfo {
|
||||
/**
|
||||
* Initialize the class, registering WordPress hooks
|
||||
*/
|
||||
public static function init() {
|
||||
\add_action( 'rest_api_init', array( '\Activitypub\Rest\Nodeinfo', 'register_routes' ) );
|
||||
\add_filter( 'nodeinfo_data', array( '\Activitypub\Rest\Nodeinfo', 'add_nodeinfo_discovery' ), 10, 2 );
|
||||
\add_filter( 'nodeinfo2_data', array( '\Activitypub\Rest\Nodeinfo', 'add_nodeinfo2_discovery' ), 10 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register routes
|
||||
*/
|
||||
public static function register_routes() {
|
||||
\register_rest_route(
|
||||
'activitypub/1.0', '/nodeinfo/discovery', array(
|
||||
array(
|
||||
'methods' => \WP_REST_Server::READABLE,
|
||||
'callback' => array( '\Activitypub\Rest\Nodeinfo', 'discovery' ),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
\register_rest_route(
|
||||
'activitypub/1.0', '/nodeinfo', array(
|
||||
array(
|
||||
'methods' => \WP_REST_Server::READABLE,
|
||||
'callback' => array( '\Activitypub\Rest\Nodeinfo', 'nodeinfo' ),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
\register_rest_route(
|
||||
'activitypub/1.0', '/nodeinfo2', array(
|
||||
array(
|
||||
'methods' => \WP_REST_Server::READABLE,
|
||||
'callback' => array( '\Activitypub\Rest\Nodeinfo', 'nodeinfo2' ),
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render NodeInfo file
|
||||
*
|
||||
* @param WP_REST_Request $request
|
||||
*
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public static function nodeinfo( $request ) {
|
||||
$nodeinfo = array();
|
||||
|
||||
$nodeinfo['version'] = '2.0';
|
||||
$nodeinfo['software'] = array(
|
||||
'name' => 'wordpress',
|
||||
'version' => \get_bloginfo( 'version' ),
|
||||
);
|
||||
|
||||
$users = \count_users();
|
||||
$posts = \wp_count_posts();
|
||||
$comments = \wp_count_comments();
|
||||
|
||||
$nodeinfo['usage'] = array(
|
||||
'users' => array(
|
||||
'total' => (int) $users['total_users'],
|
||||
),
|
||||
'localPosts' => (int) $posts->publish,
|
||||
'localComments' => (int) $comments->approved,
|
||||
);
|
||||
|
||||
$nodeinfo['openRegistrations'] = false;
|
||||
$nodeinfo['protocols'] = array( 'activitypub' );
|
||||
|
||||
$nodeinfo['services'] = array(
|
||||
'inbound' => array(),
|
||||
'outbound' => array(),
|
||||
);
|
||||
|
||||
$nodeinfo['metadata'] = array(
|
||||
'email' => \get_option( 'admin_email' ),
|
||||
);
|
||||
|
||||
return new \WP_REST_Response( $nodeinfo, 200 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Render NodeInfo file
|
||||
*
|
||||
* @param WP_REST_Request $request
|
||||
*
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public static function nodeinfo2( $request ) {
|
||||
$nodeinfo = array();
|
||||
|
||||
$nodeinfo['version'] = '1.0';
|
||||
$nodeinfo['server'] = array(
|
||||
'baseUrl' => home_url( '/' ),
|
||||
'name' => \get_bloginfo( 'name' ),
|
||||
'software' => 'wordpress',
|
||||
'version' => \get_bloginfo( 'version' ),
|
||||
);
|
||||
|
||||
$users = \count_users();
|
||||
$posts = \wp_count_posts();
|
||||
$comments = \wp_count_comments();
|
||||
|
||||
$nodeinfo['usage'] = array(
|
||||
'users' => array(
|
||||
'total' => (int) $users['total_users'],
|
||||
),
|
||||
'localPosts' => (int) $posts->publish,
|
||||
'localComments' => (int) $comments->approved,
|
||||
);
|
||||
|
||||
$nodeinfo['openRegistrations'] = false;
|
||||
$nodeinfo['protocols'] = array( 'activitypub' );
|
||||
|
||||
$nodeinfo['services'] = array(
|
||||
'inbound' => array(),
|
||||
'outbound' => array(),
|
||||
);
|
||||
|
||||
$nodeinfo['metadata'] = array(
|
||||
'email' => \get_option( 'admin_email' ),
|
||||
);
|
||||
|
||||
return new \WP_REST_Response( $nodeinfo, 200 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Render NodeInfo discovery file
|
||||
*
|
||||
* @param WP_REST_Request $request
|
||||
*
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public static function discovery( $request ) {
|
||||
$discovery = array();
|
||||
$discovery['links'] = array(
|
||||
array(
|
||||
'rel' => 'http://nodeinfo.diaspora.software/ns/schema/2.0',
|
||||
'href' => \get_rest_url( null, 'activitypub/1.0/nodeinfo' ),
|
||||
),
|
||||
);
|
||||
|
||||
return new \WP_REST_Response( $discovery, 200 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend NodeInfo data
|
||||
*
|
||||
* @param array $nodeinfo NodeInfo data
|
||||
* @param string The NodeInfo Version
|
||||
*
|
||||
* @return array The extended array
|
||||
*/
|
||||
public static function add_nodeinfo_discovery( $nodeinfo, $version ) {
|
||||
if ( '2.0' === $version ) {
|
||||
$nodeinfo['protocols'][] = 'activitypub';
|
||||
} else {
|
||||
$nodeinfo['protocols']['inbound'][] = 'activitypub';
|
||||
$nodeinfo['protocols']['outbound'][] = 'activitypub';
|
||||
}
|
||||
|
||||
return $nodeinfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend NodeInfo2 data
|
||||
*
|
||||
* @param array $nodeinfo NodeInfo2 data
|
||||
*
|
||||
* @return array The extended array
|
||||
*/
|
||||
public static function add_nodeinfo2_discovery( $nodeinfo ) {
|
||||
$nodeinfo['protocols'][] = 'activitypub';
|
||||
|
||||
return $nodeinfo;
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
namespace Activitypub\Rest;
|
||||
|
||||
/**
|
||||
* ActivityPub OStatus REST-Class
|
||||
*
|
||||
* @author Matthias Pfefferle
|
||||
*
|
||||
* @see https://www.w3.org/community/ostatus/
|
||||
*/
|
||||
class Ostatus {
|
||||
/**
|
||||
* Register routes
|
||||
*/
|
||||
public static function register_routes() {
|
||||
\register_rest_route(
|
||||
'activitypub/1.0', '/ostatus/remote-follow', array(
|
||||
array(
|
||||
'methods' => \WP_REST_Server::READABLE,
|
||||
'callback' => array( '\Activitypub\Rest\Ostatus', 'get' ),
|
||||
// 'args' => self::request_parameters(),
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public static function get() {
|
||||
// @todo implement
|
||||
}
|
||||
}
|
126
wp-content/plugins/activitypub/includes/rest/class-outbox.php
Normal file
126
wp-content/plugins/activitypub/includes/rest/class-outbox.php
Normal file
@ -0,0 +1,126 @@
|
||||
<?php
|
||||
namespace Activitypub\Rest;
|
||||
|
||||
/**
|
||||
* ActivityPub Outbox REST-Class
|
||||
*
|
||||
* @author Matthias Pfefferle
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitypub/#outbox
|
||||
*/
|
||||
class Outbox {
|
||||
/**
|
||||
* Initialize the class, registering WordPress hooks
|
||||
*/
|
||||
public static function init() {
|
||||
\add_action( 'rest_api_init', array( '\Activitypub\Rest\Outbox', 'register_routes' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register routes
|
||||
*/
|
||||
public static function register_routes() {
|
||||
\register_rest_route(
|
||||
'activitypub/1.0', '/users/(?P<id>\d+)/outbox', array(
|
||||
array(
|
||||
'methods' => \WP_REST_Server::READABLE,
|
||||
'callback' => array( '\Activitypub\Rest\Outbox', 'user_outbox' ),
|
||||
'args' => self::request_parameters(),
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the user-outbox
|
||||
*
|
||||
* @param WP_REST_Request $request
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public static function user_outbox( $request ) {
|
||||
$user_id = $request->get_param( 'id' );
|
||||
$author = \get_user_by( 'ID', $user_id );
|
||||
|
||||
if ( ! $author ) {
|
||||
return new \WP_Error( 'rest_invalid_param', __( 'User not found', 'activitypub' ), array(
|
||||
'status' => 404,
|
||||
'params' => array(
|
||||
'user_id' => \__( 'User not found', 'activitypub' ),
|
||||
),
|
||||
) );
|
||||
}
|
||||
|
||||
$page = $request->get_param( 'page', 0 );
|
||||
|
||||
/*
|
||||
* Action triggerd prior to the ActivityPub profile being created and sent to the client
|
||||
*/
|
||||
\do_action( 'activitypub_outbox_pre' );
|
||||
|
||||
$json = new \stdClass();
|
||||
|
||||
$json->{'@context'} = \Activitypub\get_context();
|
||||
$json->id = \home_url( \add_query_arg( null, null ) );
|
||||
$json->generator = 'http://wordpress.org/?v=' . \get_bloginfo_rss( 'version' );
|
||||
$json->actor = \get_author_posts_url( $user_id );
|
||||
$json->type = 'OrderedCollectionPage';
|
||||
$json->partOf = \get_rest_url( null, "/activitypub/1.0/users/$user_id/outbox" ); // phpcs:ignore
|
||||
|
||||
$count_posts = \wp_count_posts();
|
||||
$json->totalItems = \intval( $count_posts->publish ); // phpcs:ignore
|
||||
|
||||
$posts = \get_posts( array(
|
||||
'posts_per_page' => 10,
|
||||
'author' => $user_id,
|
||||
'offset' => $page * 10,
|
||||
) );
|
||||
|
||||
$json->first = \add_query_arg( 'page', 0, $json->partOf ); // phpcs:ignore
|
||||
$json->last = \add_query_arg( 'page', ( \ceil ( $json->totalItems / 10 ) ) - 1, $json->partOf ); // phpcs:ignore
|
||||
|
||||
if ( ( \ceil ( $json->totalItems / 10 ) ) - 1 > $page ) { // phpcs:ignore
|
||||
$json->next = \add_query_arg( 'page', ++$page, $json->partOf ); // phpcs:ignore
|
||||
}
|
||||
|
||||
foreach ( $posts as $post ) {
|
||||
$activitypub_post = new \Activitypub\Model\Post( $post );
|
||||
$activitypub_activity = new \Activitypub\Model\Activity( 'Create', \Activitypub\Model\Activity::TYPE_NONE );
|
||||
$activitypub_activity->from_post( $activitypub_post->to_array() );
|
||||
$json->orderedItems[] = $activitypub_activity->to_array(); // phpcs:ignore
|
||||
}
|
||||
|
||||
// filter output
|
||||
$json = \apply_filters( 'activitypub_outbox_array', $json );
|
||||
|
||||
/*
|
||||
* Action triggerd after the ActivityPub profile has been created and sent to the client
|
||||
*/
|
||||
\do_action( 'activitypub_outbox_post' );
|
||||
|
||||
$response = new \WP_REST_Response( $json, 200 );
|
||||
|
||||
$response->header( 'Content-Type', 'application/activity+json' );
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* The supported parameters
|
||||
*
|
||||
* @return array list of parameters
|
||||
*/
|
||||
public static function request_parameters() {
|
||||
$params = array();
|
||||
|
||||
$params['page'] = array(
|
||||
'type' => 'integer',
|
||||
);
|
||||
|
||||
$params['id'] = array(
|
||||
'required' => true,
|
||||
'type' => 'integer',
|
||||
);
|
||||
|
||||
return $params;
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
namespace Activitypub\Rest;
|
||||
|
||||
/**
|
||||
* Custom (hopefully temporary) ActivityPub Rest Server
|
||||
*
|
||||
* @author Matthias Pfefferle
|
||||
*/
|
||||
class Server extends \WP_REST_Server {
|
||||
/**
|
||||
* Overwrite dispatch function to quick fix missing subtype featur
|
||||
*
|
||||
* @see https://core.trac.wordpress.org/ticket/49404
|
||||
*
|
||||
* @param WP_REST_Request $request Request to attempt dispatching.
|
||||
* @return WP_REST_Response Response returned by the callback.
|
||||
*/
|
||||
public function dispatch( $request ) {
|
||||
$content_type = $request->get_content_type();
|
||||
|
||||
// check for content-sub-types like 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'
|
||||
if ( \preg_match( '/application\/([a-zA-Z+_-]+\+)json/', $content_type['value'] ) ) {
|
||||
$request->set_header( 'Content-Type', 'application/json' );
|
||||
}
|
||||
|
||||
// make request filterable
|
||||
$request = apply_filters( 'activitypub_pre_dispatch_request', $request );
|
||||
|
||||
return parent::dispatch( $request );
|
||||
}
|
||||
}
|
119
wp-content/plugins/activitypub/includes/rest/class-webfinger.php
Normal file
119
wp-content/plugins/activitypub/includes/rest/class-webfinger.php
Normal file
@ -0,0 +1,119 @@
|
||||
<?php
|
||||
namespace Activitypub\Rest;
|
||||
|
||||
/**
|
||||
* ActivityPub WebFinger REST-Class
|
||||
*
|
||||
* @author Matthias Pfefferle
|
||||
*
|
||||
* @see https://webfinger.net/
|
||||
*/
|
||||
class Webfinger {
|
||||
/**
|
||||
* Initialize the class, registering WordPress hooks
|
||||
*/
|
||||
public static function init() {
|
||||
\add_action( 'rest_api_init', array( '\Activitypub\Rest\Webfinger', 'register_routes' ) );
|
||||
\add_action( 'webfinger_user_data', array( '\Activitypub\Rest\Webfinger', 'add_webfinger_discovery' ), 10, 3 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register routes
|
||||
*/
|
||||
public static function register_routes() {
|
||||
\register_rest_route(
|
||||
'activitypub/1.0', '/webfinger', array(
|
||||
array(
|
||||
'methods' => \WP_REST_Server::READABLE,
|
||||
'callback' => array( '\Activitypub\Rest\Webfinger', 'webfinger' ),
|
||||
'args' => self::request_parameters(),
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render JRD file
|
||||
*
|
||||
* @param WP_REST_Request $request
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public static function webfinger( $request ) {
|
||||
$resource = $request->get_param( 'resource' );
|
||||
|
||||
$matches = array();
|
||||
$matched = \preg_match( '/^acct:([^@]+)@(.+)$/', $resource, $matches );
|
||||
|
||||
if ( ! $matched ) {
|
||||
return new \WP_Error( 'activitypub_unsupported_resource', \__( 'Resource is invalid', 'activitypub' ), array( 'status' => 400 ) );
|
||||
}
|
||||
|
||||
$resource_identifier = $matches[1];
|
||||
$resource_host = $matches[2];
|
||||
|
||||
if ( \wp_parse_url( \home_url( '/' ), PHP_URL_HOST ) !== $resource_host ) {
|
||||
return new \WP_Error( 'activitypub_wrong_host', \__( 'Resource host does not match blog host', 'activitypub' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
$user = \get_user_by( 'login', \esc_sql( $resource_identifier ) );
|
||||
|
||||
if ( ! $user ) {
|
||||
return new \WP_Error( 'activitypub_user_not_found', \__( 'User not found', 'activitypub' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
$json = array(
|
||||
'subject' => $resource,
|
||||
'aliases' => array(
|
||||
\get_author_posts_url( $user->ID ),
|
||||
),
|
||||
'links' => array(
|
||||
array(
|
||||
'rel' => 'self',
|
||||
'type' => 'application/activity+json',
|
||||
'href' => \get_author_posts_url( $user->ID ),
|
||||
),
|
||||
array(
|
||||
'rel' => 'http://webfinger.net/rel/profile-page',
|
||||
'type' => 'text/html',
|
||||
'href' => \get_author_posts_url( $user->ID ),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return new \WP_REST_Response( $json, 200 );
|
||||
}
|
||||
|
||||
/**
|
||||
* The supported parameters
|
||||
*
|
||||
* @return array list of parameters
|
||||
*/
|
||||
public static function request_parameters() {
|
||||
$params = array();
|
||||
|
||||
$params['resource'] = array(
|
||||
'required' => true,
|
||||
'type' => 'string',
|
||||
'pattern' => '^acct:([^@]+)@(.+)$',
|
||||
);
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add WebFinger discovery links
|
||||
*
|
||||
* @param array $array the jrd array
|
||||
* @param string $resource the WebFinger resource
|
||||
* @param WP_User $user the WordPress user
|
||||
*/
|
||||
public static function add_webfinger_discovery( $array, $resource, $user ) {
|
||||
$array['links'][] = array(
|
||||
'rel' => 'self',
|
||||
'type' => 'application/activity+json',
|
||||
'href' => \get_author_posts_url( $user->ID ),
|
||||
);
|
||||
|
||||
return $array;
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
namespace Activitypub\Table;
|
||||
|
||||
if ( ! \class_exists( '\WP_List_Table' ) ) {
|
||||
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
|
||||
}
|
||||
|
||||
class Followers_List extends \WP_List_Table {
|
||||
public function get_columns() {
|
||||
return array(
|
||||
'identifier' => \__( 'Identifier', 'activitypub' ),
|
||||
);
|
||||
}
|
||||
|
||||
public function get_sortable_columns() {
|
||||
return array();
|
||||
}
|
||||
|
||||
public function prepare_items() {
|
||||
$columns = $this->get_columns();
|
||||
$hidden = array();
|
||||
|
||||
$this->process_action();
|
||||
$this->_column_headers = array( $columns, $hidden, $this->get_sortable_columns() );
|
||||
|
||||
$this->items = array();
|
||||
|
||||
foreach ( \Activitypub\Peer\Followers::get_followers( \get_current_user_id() ) as $follower ) {
|
||||
$this->items[]['identifier'] = \esc_attr( $follower );
|
||||
}
|
||||
}
|
||||
|
||||
public function column_default( $item, $column_name ) {
|
||||
return $item[ $column_name ];
|
||||
}
|
||||
}
|
307
wp-content/plugins/activitypub/languages/activitypub.pot
Normal file
307
wp-content/plugins/activitypub/languages/activitypub.pot
Normal file
@ -0,0 +1,307 @@
|
||||
# Copyright (C) 2020 Matthias Pfefferle
|
||||
# This file is distributed under the MIT.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: ActivityPub 0.10.0\n"
|
||||
"Report-Msgid-Bugs-To: "
|
||||
"https://wordpress.org/support/plugin/wordpress-activitypub\n"
|
||||
"POT-Creation-Date: 2020-03-15 19:34:14+00:00\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"PO-Revision-Date: 2020-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"X-Generator: grunt-wp-i18n 1.0.3\n"
|
||||
|
||||
#: includes/class-admin.php:33
|
||||
msgid "Followers"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-admin.php:33 templates/followers-list.php:2
|
||||
msgid "Followers (Fediverse)"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-admin.php:59
|
||||
msgid "Use title and link, summary or full content"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-admin.php:71
|
||||
msgid "The Activity-Object-Type"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-admin.php:83 templates/settings.php:36
|
||||
msgid "Use the Shortlink instead of the permalink"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-admin.php:90
|
||||
msgid ""
|
||||
"Add hashtags in the content as native tags and replace the #tag with the "
|
||||
"tag-link"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-admin.php:97
|
||||
msgid "Add all tags as hashtags at the end of each activity"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-admin.php:104
|
||||
msgid "Enable ActivityPub support for post types"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-admin.php:112
|
||||
msgid "Block fediverse instances"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-admin.php:123
|
||||
msgid "Overview"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-admin.php:125
|
||||
msgid ""
|
||||
"ActivityPub is a decentralized social networking protocol based on the "
|
||||
"ActivityStreams 2.0 data format. ActivityPub is an official W3C recommended "
|
||||
"standard published by the W3C Social Web Working Group. It provides a "
|
||||
"client to server API for creating, updating and deleting content, as well "
|
||||
"as a federated server to server API for delivering notifications and "
|
||||
"subscribing to content."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-admin.php:130
|
||||
msgid "For more information:"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-admin.php:131
|
||||
msgid "<a href=\"https://activitypub.rocks/\">Test Suite</a>"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-admin.php:132
|
||||
msgid "<a href=\"https://www.w3.org/TR/activitypub/\">W3C Spec</a>"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-admin.php:133
|
||||
msgid ""
|
||||
"<a href=\"https://github.com/pfefferle/wordpress-activitypub/issues\">Give "
|
||||
"us feedback</a>"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-admin.php:135
|
||||
msgid "<a href=\"https://notiz.blog/donate\">Donate</a>"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-admin.php:145
|
||||
msgid "Fediverse"
|
||||
msgstr ""
|
||||
|
||||
#: includes/functions.php:110
|
||||
msgid "The \"actor\" is no valid URL"
|
||||
msgstr ""
|
||||
|
||||
#: includes/functions.php:132
|
||||
msgid "No valid JSON data"
|
||||
msgstr ""
|
||||
|
||||
#: includes/functions.php:160
|
||||
msgid "No \"Inbox\" found"
|
||||
msgstr ""
|
||||
|
||||
#: includes/functions.php:186
|
||||
msgid "No \"Public-Key\" found"
|
||||
msgstr ""
|
||||
|
||||
#: includes/functions.php:214
|
||||
msgid "Profile identifier"
|
||||
msgstr ""
|
||||
|
||||
#: includes/functions.php:219
|
||||
#. translators: the webfinger resource
|
||||
msgid "Try to follow \"@%s\" in the Mastodon/Friendica search field."
|
||||
msgstr ""
|
||||
|
||||
#: includes/peer/class-followers.php:53
|
||||
msgid "Unknown Actor schema"
|
||||
msgstr ""
|
||||
|
||||
#: includes/rest/class-followers.php:46 includes/rest/class-followers.php:49
|
||||
#: includes/rest/class-following.php:46 includes/rest/class-following.php:49
|
||||
#: includes/rest/class-outbox.php:45 includes/rest/class-outbox.php:48
|
||||
#: includes/rest/class-webfinger.php:61
|
||||
msgid "User not found"
|
||||
msgstr ""
|
||||
|
||||
#: includes/rest/class-webfinger.php:48
|
||||
msgid "Resource is invalid"
|
||||
msgstr ""
|
||||
|
||||
#: includes/rest/class-webfinger.php:55
|
||||
msgid "Resource host does not match blog host"
|
||||
msgstr ""
|
||||
|
||||
#: includes/table/followers-list.php:11
|
||||
msgid "Identifier"
|
||||
msgstr ""
|
||||
|
||||
#: templates/followers-list.php:4
|
||||
msgid "You currently have %s followers."
|
||||
msgstr ""
|
||||
|
||||
#: templates/json-author.php:48
|
||||
msgid "Blog"
|
||||
msgstr ""
|
||||
|
||||
#: templates/json-author.php:58
|
||||
msgid "Profile"
|
||||
msgstr ""
|
||||
|
||||
#: templates/json-author.php:69
|
||||
msgid "Website"
|
||||
msgstr ""
|
||||
|
||||
#: templates/settings.php:2
|
||||
msgid "ActivityPub Settings"
|
||||
msgstr ""
|
||||
|
||||
#: templates/settings.php:4
|
||||
msgid ""
|
||||
"ActivityPub turns your blog into a federated social network. This means you "
|
||||
"can share and talk to everyone using the ActivityPub protocol, including "
|
||||
"users of Friendica, Pleroma and Mastodon."
|
||||
msgstr ""
|
||||
|
||||
#: templates/settings.php:9
|
||||
msgid "Activities"
|
||||
msgstr ""
|
||||
|
||||
#: templates/settings.php:11
|
||||
msgid "All activity related settings."
|
||||
msgstr ""
|
||||
|
||||
#: templates/settings.php:17
|
||||
msgid "Post-Content"
|
||||
msgstr ""
|
||||
|
||||
#: templates/settings.php:21
|
||||
msgid "Title and link"
|
||||
msgstr ""
|
||||
|
||||
#: templates/settings.php:21
|
||||
msgid "Only the title and a link."
|
||||
msgstr ""
|
||||
|
||||
#: templates/settings.php:24
|
||||
msgid "Excerpt"
|
||||
msgstr ""
|
||||
|
||||
#: templates/settings.php:24
|
||||
msgid "A content summary, shortened to 400 characters and without markup."
|
||||
msgstr ""
|
||||
|
||||
#: templates/settings.php:27
|
||||
msgid "Content (default)"
|
||||
msgstr ""
|
||||
|
||||
#: templates/settings.php:27
|
||||
msgid "The full content."
|
||||
msgstr ""
|
||||
|
||||
#: templates/settings.php:33
|
||||
msgid "Backlink"
|
||||
msgstr ""
|
||||
|
||||
#: templates/settings.php:42
|
||||
msgid "Activity-Object-Type"
|
||||
msgstr ""
|
||||
|
||||
#: templates/settings.php:46
|
||||
msgid "Note (default)"
|
||||
msgstr ""
|
||||
|
||||
#: templates/settings.php:46
|
||||
msgid "Should work with most platforms."
|
||||
msgstr ""
|
||||
|
||||
#: templates/settings.php:49
|
||||
msgid "Article"
|
||||
msgstr ""
|
||||
|
||||
#: templates/settings.php:49
|
||||
msgid ""
|
||||
"The presentation of the \"Article\" might change on different platforms. "
|
||||
"Mastodon for example shows the \"Article\" type as a simple link."
|
||||
msgstr ""
|
||||
|
||||
#: templates/settings.php:52
|
||||
msgid "WordPress Post-Format"
|
||||
msgstr ""
|
||||
|
||||
#: templates/settings.php:52
|
||||
msgid "Maps the WordPress Post-Format to the ActivityPub Object Type."
|
||||
msgstr ""
|
||||
|
||||
#: templates/settings.php:57
|
||||
msgid "Supported post types"
|
||||
msgstr ""
|
||||
|
||||
#: templates/settings.php:60
|
||||
msgid "Enable ActivityPub support for the following post types:"
|
||||
msgstr ""
|
||||
|
||||
#: templates/settings.php:77
|
||||
msgid "Hashtags"
|
||||
msgstr ""
|
||||
|
||||
#: templates/settings.php:81
|
||||
msgid ""
|
||||
"Add hashtags in the content as native tags and replace the "
|
||||
"<code>#tag</code> with the tag-link."
|
||||
msgstr ""
|
||||
|
||||
#: templates/settings.php:84
|
||||
msgid "Add all tags as hashtags to the end of each activity."
|
||||
msgstr ""
|
||||
|
||||
#: templates/settings.php:93
|
||||
msgid "Server"
|
||||
msgstr ""
|
||||
|
||||
#: templates/settings.php:95
|
||||
msgid "Server related settings."
|
||||
msgstr ""
|
||||
|
||||
#: templates/settings.php:106
|
||||
msgid "Blacklist"
|
||||
msgstr ""
|
||||
|
||||
#: templates/settings.php:110
|
||||
msgid ""
|
||||
"A list of hosts, you want to block, one host per line. Please use only the "
|
||||
"host/domain of the server you want to block, without <code>http://</code> "
|
||||
"and without <code>www.</code>. For example <code>example.com</code>."
|
||||
msgstr ""
|
||||
|
||||
#: templates/settings.php:124
|
||||
msgid ""
|
||||
"If you like this plugin, what about a small <a "
|
||||
"href=\"https://notiz.blog/donate\">donation</a>?"
|
||||
msgstr ""
|
||||
|
||||
#. Plugin Name of the plugin/theme
|
||||
msgid "ActivityPub"
|
||||
msgstr ""
|
||||
|
||||
#. Plugin URI of the plugin/theme
|
||||
msgid "https://github.com/pfefferle/wordpress-activitypub/"
|
||||
msgstr ""
|
||||
|
||||
#. Description of the plugin/theme
|
||||
msgid ""
|
||||
"The ActivityPub protocol is a decentralized social networking protocol "
|
||||
"based upon the ActivityStreams 2.0 data format."
|
||||
msgstr ""
|
||||
|
||||
#. Author of the plugin/theme
|
||||
msgid "Matthias Pfefferle"
|
||||
msgstr ""
|
||||
|
||||
#. Author URI of the plugin/theme
|
||||
msgid "https://notiz.blog/"
|
||||
msgstr ""
|
276
wp-content/plugins/activitypub/readme.txt
Normal file
276
wp-content/plugins/activitypub/readme.txt
Normal file
@ -0,0 +1,276 @@
|
||||
=== ActivityPub ===
|
||||
Contributors: pfefferle
|
||||
Donate link: https://notiz.blog/donate/
|
||||
Tags: OStatus, fediverse, activitypub, activitystream
|
||||
Requires at least: 4.7
|
||||
Tested up to: 5.3
|
||||
Stable tag: 0.10.0
|
||||
Requires PHP: 5.6
|
||||
License: MIT
|
||||
License URI: http://opensource.org/licenses/MIT
|
||||
|
||||
The ActivityPub protocol is a decentralized social networking protocol based upon the ActivityStreams 2.0 data format.
|
||||
|
||||
== Description ==
|
||||
|
||||
This is **BETA** software, see the FAQ to see the current feature set or rather what is still planned.
|
||||
|
||||
The plugin implements the ActivityPub protocol for your blog. Your readers will be able to follow your blogposts on Mastodon and other federated platforms that support ActivityPub.
|
||||
|
||||
The plugin works with the following federated platforms:
|
||||
|
||||
* [Mastodon](https://joinmastodon.org/)
|
||||
* [Pleroma](https://pleroma.social/)
|
||||
* [Friendica](https://friendi.ca/)
|
||||
* [HubZilla](https://hubzilla.org/)
|
||||
* [Pixelfed](https://pixelfed.org/)
|
||||
* [SocialHome](https://socialhome.network/)
|
||||
* [Misskey](https://join.misskey.page/)
|
||||
|
||||
== Frequently Asked Questions ==
|
||||
|
||||
= What is the status of this plugin? =
|
||||
|
||||
Implemented:
|
||||
|
||||
* profile pages (JSON representation)
|
||||
* custom links
|
||||
* functional inbox/outbox
|
||||
* follow (accept follows)
|
||||
* share posts
|
||||
* receive comments/reactions
|
||||
|
||||
To implement:
|
||||
|
||||
* signature verification
|
||||
* better WordPress integration
|
||||
* better configuration possibilities
|
||||
* threaded comments support
|
||||
|
||||
= What is "ActivityPub for WordPress" =
|
||||
|
||||
*ActivityPub for WordPress* extends WordPress with some Fediverse features, but it does not compete with platforms like Friendica or Mastodon. If you want to run a **decentralized social network**, please use [Mastodon](https://joinmastodon.org/) or [GNU social](https://gnu.io/social/).
|
||||
|
||||
= What are the differences between this plugin and Pterotype? =
|
||||
|
||||
**Compatibility**
|
||||
|
||||
*ActivityPub for WordPress* is compatible with OStatus and IndieWeb plugin suites. *Pterotype* is incompatible with the standalone [WebFinger plugin](https://wordpress.org/plugins/webfinger/), so it can't be run together with OStatus.
|
||||
|
||||
**Custom tables**
|
||||
|
||||
*Pterotype* creates/uses a bunch of custom tables, *ActivityPub for WordPress* only uses the native tables and adds as little meta data as possible.
|
||||
|
||||
= What if you are running your blog in a subdirectory? =
|
||||
|
||||
In order for webfinger to work, it must be mapped to the root directory of the URL on which your blog resides.
|
||||
|
||||
**Apache**
|
||||
|
||||
Add the following to the .htaccess file in the root directory:
|
||||
|
||||
RedirectMatch "^\/\.well-known(.*)$" "\/blog\/\.well-known$1"
|
||||
|
||||
Where 'blog' is the path to the subdirectory at which your blog resides.
|
||||
|
||||
**Nginx**
|
||||
|
||||
Add the following to the site.conf in sites-available:
|
||||
|
||||
location ~* /.well-known {
|
||||
allow all;
|
||||
try_files $uri $uri/ /blog/?$args;
|
||||
}
|
||||
|
||||
Where 'blog' is the path to the subdirectory at which your blog resides.
|
||||
|
||||
== Changelog ==
|
||||
|
||||
Project maintained on GitHub at [pfefferle/wordpress-activitypub](https://github.com/pfefferle/wordpress-activitypub).
|
||||
|
||||
= 0.10.0 =
|
||||
|
||||
* add image alt text to the ActivityStreams attachment property in a format that Mastodon can read. props [@BenLubar](https://github.com/BenLubar)
|
||||
* use the "summary" property for a title as Mastodon does. props [@BenLubar](https://github.com/BenLubar)
|
||||
* support authorized fetch to avoid having comments from "Anonymous". props [@BenLubar](https://github.com/BenLubar)
|
||||
* add new post type: "title and link only". props [@bgcarlisle](https://github.com/bgcarlisle)
|
||||
|
||||
= 0.9.1 =
|
||||
|
||||
* disable shared inbox
|
||||
* disable delete activity
|
||||
|
||||
= 0.9.0 =
|
||||
|
||||
* some code refactorings
|
||||
* fix #73
|
||||
|
||||
= 0.8.3 =
|
||||
|
||||
* fixed accept header bug
|
||||
|
||||
= 0.8.2 =
|
||||
|
||||
* add all required accept header
|
||||
* better/simpler accept-header handling
|
||||
* add debugging mechanism
|
||||
* Add setting to enable AP for different (public) Post-Types
|
||||
* explicit use of global functions
|
||||
|
||||
= 0.8.1 =
|
||||
|
||||
* fixed PHP warnings
|
||||
|
||||
= 0.8.0 =
|
||||
|
||||
* Moved followers list to user-menu
|
||||
|
||||
= 0.7.4 =
|
||||
|
||||
* added admin_email to metadata, to be able to "Manage your instance" on https://fediverse.network/manage/
|
||||
|
||||
= 0.7.3 =
|
||||
|
||||
* refactorings
|
||||
* fixed PHP warnings
|
||||
* better hashtag regex
|
||||
|
||||
= 0.7.2 =
|
||||
|
||||
* fixed JSON representation of posts https://merveilles.town/@xuv/101907542498716956
|
||||
|
||||
= 0.7.1 =
|
||||
|
||||
* fixed inbox problems with pleroma
|
||||
|
||||
= 0.7.0 =
|
||||
|
||||
* finally fixed pleroma compatibility
|
||||
* added "following" endpoint
|
||||
* simplified "followers" endpoint
|
||||
* fixed default value problem
|
||||
|
||||
= 0.6.0 =
|
||||
|
||||
* add tags as hashtags to the end of each activity
|
||||
* fixed pleroma following issue
|
||||
* followers-list improvements
|
||||
|
||||
= 0.5.1 =
|
||||
|
||||
* fixed name-collision that caused an infinite loop
|
||||
|
||||
= 0.5.0 =
|
||||
|
||||
* complete refactoring
|
||||
* fixed bug #30: Password-protected posts are federated
|
||||
* only send Activites when ActivityPub is enabled for this post-type
|
||||
|
||||
= 0.4.4 =
|
||||
|
||||
* show avatars
|
||||
|
||||
= 0.4.3 =
|
||||
|
||||
* finally fixed backlink in excerpt/summary posts
|
||||
|
||||
= 0.4.2 =
|
||||
|
||||
* fixed backlink in excerpt/summary posts (thanks @depone)
|
||||
|
||||
= 0.4.1 =
|
||||
|
||||
* finally fixed contact list
|
||||
|
||||
= 0.4.0 =
|
||||
|
||||
* added settings to enable/disable hashtag support
|
||||
* fixed follower list
|
||||
* send activities only for new posts, otherwise send updates
|
||||
|
||||
= 0.3.2 =
|
||||
|
||||
* added "followers" endpoint
|
||||
* change activity content from blog 'excerpt' to blog 'content'
|
||||
|
||||
= 0.3.1 =
|
||||
|
||||
* better json encoding
|
||||
|
||||
= 0.3.0 =
|
||||
|
||||
* basic hashtag support
|
||||
* temporarily deactivated likes and boosts
|
||||
* added support for actor objects
|
||||
* fixed encoding issue
|
||||
|
||||
= 0.2.1 =
|
||||
|
||||
* customizable backlink (permalink or shorturl)
|
||||
* show profile-identifiers also on profile settings
|
||||
|
||||
= 0.2.0 =
|
||||
|
||||
* added option to switch between content and excerpt
|
||||
* removed html and duplicate new-lines
|
||||
|
||||
= 0.1.1 =
|
||||
|
||||
* fixed "excerpt" in AS JSON
|
||||
* added settings for the activity-summary and for the activity-object-type
|
||||
|
||||
= 0.1.0 =
|
||||
|
||||
* added basic WebFinger support
|
||||
* added basic NodeInfo support
|
||||
* fully functional "follow" activity
|
||||
* send new posts to your followers
|
||||
* receive comments from your followers
|
||||
|
||||
= 0.0.2 =
|
||||
|
||||
* refactoring
|
||||
* functional inbox
|
||||
* nicer profile views
|
||||
|
||||
= 0.0.1 =
|
||||
|
||||
* initial
|
||||
|
||||
== Installation ==
|
||||
|
||||
Follow the normal instructions for [installing WordPress plugins](https://wordpress.org/support/article/managing-plugins/).
|
||||
|
||||
= Automatic Plugin Installation =
|
||||
|
||||
To add a WordPress Plugin using the [built-in plugin installer](https://codex.wordpress.org/Administration_Screens#Add_New_Plugins):
|
||||
|
||||
1. Go to [Plugins](https://codex.wordpress.org/Administration_Screens#Plugins) > [Add New](https://codex.wordpress.org/Plugins_Add_New_Screen).
|
||||
1. Type "`activitypub`" into the **Search Plugins** box.
|
||||
1. Find the WordPress Plugin you wish to install.
|
||||
1. Click **Details** for more information about the Plugin and instructions you may wish to print or save to help setup the Plugin.
|
||||
1. Click **Install Now** to install the WordPress Plugin.
|
||||
1. The resulting installation screen will list the installation as successful or note any problems during the install.
|
||||
1. If successful, click **Activate Plugin** to activate it, or **Return to Plugin Installer** for further actions.
|
||||
|
||||
= Manual Plugin Installation =
|
||||
|
||||
There are a few cases when manually installing a WordPress Plugin is appropriate.
|
||||
|
||||
* If you wish to control the placement and the process of installing a WordPress Plugin.
|
||||
* If your server does not permit automatic installation of a WordPress Plugin.
|
||||
* If you want to try the [latest development version](https://github.com/pfefferle/wordpress-activitypub).
|
||||
|
||||
Installation of a WordPress Plugin manually requires FTP familiarity and the awareness that you may put your site at risk if you install a WordPress Plugin incompatible with the current version or from an unreliable source.
|
||||
|
||||
Backup your site completely before proceeding.
|
||||
|
||||
To install a WordPress Plugin manually:
|
||||
|
||||
* Download your WordPress Plugin to your desktop.
|
||||
* Download from [the WordPress directory](https://wordpress.org/plugins/activitypub/)
|
||||
* Download from [GitHub](https://github.com/pfefferle/wordpress-activitypub/releases)
|
||||
* If downloaded as a zip archive, extract the Plugin folder to your desktop.
|
||||
* With your FTP program, upload the Plugin folder to the `wp-content/plugins` folder in your WordPress directory online.
|
||||
* Go to [Plugins screen](https://codex.wordpress.org/Administration_Screens#Plugins) and find the newly uploaded Plugin in the list.
|
||||
* Click **Activate** to activate it.
|
15
wp-content/plugins/activitypub/templates/followers-list.php
Normal file
15
wp-content/plugins/activitypub/templates/followers-list.php
Normal file
@ -0,0 +1,15 @@
|
||||
<div class="wrap">
|
||||
<h1><?php \esc_html_e( 'Followers (Fediverse)', 'activitypub' ); ?></h1>
|
||||
|
||||
<p><?php \printf( \__( 'You currently have %s followers.', 'activitypub' ), \esc_attr( \Activitypub\Peer\Followers::count_followers( \get_current_user_id() ) ) ); ?></p>
|
||||
|
||||
<?php $token_table = new \Activitypub\Table\Followers_List(); ?>
|
||||
|
||||
<form method="get">
|
||||
<input type="hidden" name="page" value="indieauth_user_token" />
|
||||
<?php
|
||||
$token_table->prepare_items();
|
||||
$token_table->display();
|
||||
?>
|
||||
</form>
|
||||
</div>
|
113
wp-content/plugins/activitypub/templates/json-author.php
Normal file
113
wp-content/plugins/activitypub/templates/json-author.php
Normal file
@ -0,0 +1,113 @@
|
||||
<?php
|
||||
$author_id = \get_the_author_meta( 'ID' );
|
||||
|
||||
$json = new \stdClass();
|
||||
|
||||
$json->{'@context'} = \Activitypub\get_context();
|
||||
$json->id = \get_author_posts_url( $author_id );
|
||||
$json->type = 'Person';
|
||||
$json->name = \get_the_author_meta( 'display_name', $author_id );
|
||||
$json->summary = \html_entity_decode(
|
||||
\get_the_author_meta( 'description', $author_id ),
|
||||
ENT_QUOTES,
|
||||
'UTF-8'
|
||||
);
|
||||
$json->preferredUsername = \get_the_author_meta( 'login', $author_id ); // phpcs:ignore
|
||||
$json->url = \get_author_posts_url( $author_id );
|
||||
$json->icon = array(
|
||||
'type' => 'Image',
|
||||
'url' => \get_avatar_url( $author_id, array( 'size' => 120 ) ),
|
||||
);
|
||||
|
||||
if ( \has_header_image() ) {
|
||||
$json->image = array(
|
||||
'type' => 'Image',
|
||||
'url' => \get_header_image(),
|
||||
);
|
||||
}
|
||||
|
||||
$json->inbox = \get_rest_url( null, "/activitypub/1.0/users/$author_id/inbox" );
|
||||
$json->outbox = \get_rest_url( null, "/activitypub/1.0/users/$author_id/outbox" );
|
||||
$json->followers = \get_rest_url( null, "/activitypub/1.0/users/$author_id/followers" );
|
||||
$json->following = \get_rest_url( null, "/activitypub/1.0/users/$author_id/following" );
|
||||
|
||||
$json->manuallyApprovesFollowers = \apply_filters( 'activitypub_json_manually_approves_followers', __return_false() ); // phpcs:ignore
|
||||
|
||||
// phpcs:ignore
|
||||
$json->publicKey = array(
|
||||
'id' => \get_author_posts_url( $author_id ) . '#main-key',
|
||||
'owner' => \get_author_posts_url( $author_id ),
|
||||
'publicKeyPem' => \trim( \Activitypub\Signature::get_public_key( $author_id ) ),
|
||||
);
|
||||
|
||||
$json->tag = array();
|
||||
$json->attachment = array();
|
||||
|
||||
$json->attachment[] = array(
|
||||
'type' => 'PropertyValue',
|
||||
'name' => __( 'Blog', 'activitypub' ),
|
||||
'value' => \html_entity_decode(
|
||||
'<a rel="me" title="' . \esc_attr( \home_url( '/' ) ) . '" target="_blank" href="' . \home_url( '/' ) . '">' . \wp_parse_url( \home_url( '/' ), PHP_URL_HOST ) . '</a>',
|
||||
ENT_QUOTES,
|
||||
'UTF-8'
|
||||
),
|
||||
);
|
||||
|
||||
$json->attachment[] = array(
|
||||
'type' => 'PropertyValue',
|
||||
'name' => __( 'Profile', 'activitypub' ),
|
||||
'value' => \html_entity_decode(
|
||||
'<a rel="me" title="' . \esc_attr( \get_author_posts_url( $author_id ) ) . '" target="_blank" href="' . \get_author_posts_url( $author_id ) . '">' . \wp_parse_url( \get_author_posts_url( $author_id ), PHP_URL_HOST ) . '</a>',
|
||||
ENT_QUOTES,
|
||||
'UTF-8'
|
||||
),
|
||||
);
|
||||
|
||||
if ( \get_the_author_meta( 'user_url', $author_id ) ) {
|
||||
$json->attachment[] = array(
|
||||
'type' => 'PropertyValue',
|
||||
'name' => __( 'Website', 'activitypub' ),
|
||||
'value' => \html_entity_decode(
|
||||
'<a rel="me" title="' . \esc_attr( \get_the_author_meta( 'user_url', $author_id ) ) . '" target="_blank" href="' . \get_the_author_meta( 'user_url', $author_id ) . '">' . \wp_parse_url( \get_the_author_meta( 'user_url', $author_id ), PHP_URL_HOST ) . '</a>',
|
||||
ENT_QUOTES,
|
||||
'UTF-8'
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
$json->endpoints = array(
|
||||
'sharedInbox' => \get_rest_url( null, '/activitypub/1.0/inbox' ),
|
||||
);
|
||||
*/
|
||||
|
||||
// filter output
|
||||
$json = \apply_filters( 'activitypub_json_author_array', $json );
|
||||
|
||||
/*
|
||||
* Action triggerd prior to the ActivityPub profile being created and sent to the client
|
||||
*/
|
||||
\do_action( 'activitypub_json_author_pre' );
|
||||
|
||||
$options = 0;
|
||||
// JSON_PRETTY_PRINT added in PHP 5.4
|
||||
if ( \get_query_var( 'pretty' ) ) {
|
||||
$options |= JSON_PRETTY_PRINT; // phpcs:ignore
|
||||
}
|
||||
|
||||
$options |= JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_QUOT;
|
||||
|
||||
/*
|
||||
* Options to be passed to json_encode()
|
||||
*
|
||||
* @param int $options The current options flags
|
||||
*/
|
||||
$options = \apply_filters( 'activitypub_json_author_options', $options );
|
||||
|
||||
\header( 'Content-Type: application/activity+json' );
|
||||
echo \wp_json_encode( $json, $options );
|
||||
|
||||
/*
|
||||
* Action triggerd after the ActivityPub profile has been created and sent to the client
|
||||
*/
|
||||
\do_action( 'activitypub_json_author_post' );
|
36
wp-content/plugins/activitypub/templates/json-post.php
Normal file
36
wp-content/plugins/activitypub/templates/json-post.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
$post = \get_post();
|
||||
|
||||
$activitypub_post = new \Activitypub\Model\Post( $post );
|
||||
$json = \array_merge( array( '@context' => \Activitypub\get_context() ), $activitypub_post->to_array() );
|
||||
|
||||
// filter output
|
||||
$json = \apply_filters( 'activitypub_json_post_array', $json );
|
||||
|
||||
/*
|
||||
* Action triggerd prior to the ActivityPub profile being created and sent to the client
|
||||
*/
|
||||
\do_action( 'activitypub_json_post_pre' );
|
||||
|
||||
$options = 0;
|
||||
// JSON_PRETTY_PRINT added in PHP 5.4
|
||||
if ( \get_query_var( 'pretty' ) ) {
|
||||
$options |= JSON_PRETTY_PRINT; // phpcs:ignore
|
||||
}
|
||||
|
||||
$options |= JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_QUOT;
|
||||
|
||||
/*
|
||||
* Options to be passed to json_encode()
|
||||
*
|
||||
* @param int $options The current options flags
|
||||
*/
|
||||
$options = \apply_filters( 'activitypub_json_post_options', $options );
|
||||
|
||||
\header( 'Content-Type: application/activity+json' );
|
||||
echo \wp_json_encode( $json, $options );
|
||||
|
||||
/*
|
||||
* Action triggerd after the ActivityPub profile has been created and sent to the client
|
||||
*/
|
||||
\do_action( 'activitypub_json_post_post' );
|
126
wp-content/plugins/activitypub/templates/settings.php
Normal file
126
wp-content/plugins/activitypub/templates/settings.php
Normal file
@ -0,0 +1,126 @@
|
||||
<div class="wrap">
|
||||
<h1><?php \esc_html_e( 'ActivityPub Settings', 'activitypub' ); ?></h1>
|
||||
|
||||
<p><?php \esc_html_e( 'ActivityPub turns your blog into a federated social network. This means you can share and talk to everyone using the ActivityPub protocol, including users of Friendica, Pleroma and Mastodon.', 'activitypub' ); ?></p>
|
||||
|
||||
<form method="post" action="options.php">
|
||||
<?php \settings_fields( 'activitypub' ); ?>
|
||||
|
||||
<h2><?php \esc_html_e( 'Activities', 'activitypub' ); ?></h2>
|
||||
|
||||
<p><?php \esc_html_e( 'All activity related settings.', 'activitypub' ); ?></p>
|
||||
|
||||
<table class="form-table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<?php esc_html_e( 'Post-Content', 'activitypub' ); ?>
|
||||
</th>
|
||||
<td>
|
||||
<p>
|
||||
<label><input type="radio" name="activitypub_post_content_type" id="activitypub_post_content_type_title_link" value="title" <?php echo \checked( 'title', \get_option( 'activitypub_post_content_type', 'content' ) ); ?> /> <?php \esc_html_e( 'Title and link', 'activitypub' ); ?></label> - <span class="description"><?php \esc_html_e( 'Only the title and a link.', 'activitypub' ); ?></span>
|
||||
</p>
|
||||
<p>
|
||||
<label><input type="radio" name="activitypub_post_content_type" id="activitypub_post_content_type_excerpt" value="excerpt" <?php echo \checked( 'excerpt', \get_option( 'activitypub_post_content_type', 'content' ) ); ?> /> <?php \esc_html_e( 'Excerpt', 'activitypub' ); ?></label> - <span class="description"><?php \esc_html_e( 'A content summary, shortened to 400 characters and without markup.', 'activitypub' ); ?></span>
|
||||
</p>
|
||||
<p>
|
||||
<label><input type="radio" name="activitypub_post_content_type" id="activitypub_post_content_type_content" value="content" <?php echo \checked( 'content', \get_option( 'activitypub_post_content_type', 'content' ) ); ?> /> <?php \esc_html_e( 'Content (default)', 'activitypub' ); ?></label> - <span class="description"><?php \esc_html_e( 'The full content.', 'activitypub' ); ?></span>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<?php \esc_html_e( 'Backlink', 'activitypub' ); ?>
|
||||
</th>
|
||||
<td>
|
||||
<p><label><input type="checkbox" name="activitypub_use_shortlink" id="activitypub_use_shortlink" value="1" <?php echo \checked( '1', \get_option( 'activitypub_use_shortlink', '0' ) ); ?> /> <?php \esc_html_e( 'Use the Shortlink instead of the permalink', 'activitypub' ); ?></label></p>
|
||||
<p class="description"><?php \printf( esc_html( 'I can recommend %sHum%s, to prettify the Shortlinks', 'activitypub' ), '<a href="https://wordpress.org/plugins/hum/" target="_blank">', '</a>' ); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<?php \esc_html_e( 'Activity-Object-Type', 'activitypub' ); ?>
|
||||
</th>
|
||||
<td>
|
||||
<p>
|
||||
<label><input type="radio" name="activitypub_object_type" id="activitypub_object_type_note" value="note" <?php echo \checked( 'note', \get_option( 'activitypub_object_type', 'note' ) ); ?> /> <?php \esc_html_e( 'Note (default)', 'activitypub' ); ?></label> - <span class="description"><?php \esc_html_e( 'Should work with most platforms.', 'activitypub' ); ?></span>
|
||||
</p>
|
||||
<p>
|
||||
<label><input type="radio" name="activitypub_object_type" id="activitypub_object_type_article" value="article" <?php echo \checked( 'article', \get_option( 'activitypub_object_type', 'note' ) ); ?> /> <?php \esc_html_e( 'Article', 'activitypub' ); ?></label> - <span class="description"><?php \esc_html_e( 'The presentation of the "Article" might change on different platforms. Mastodon for example shows the "Article" type as a simple link.', 'activitypub' ); ?></span>
|
||||
</p>
|
||||
<p>
|
||||
<label><input type="radio" name="activitypub_object_type" id="activitypub_object_type" value="wordpress-post-format" <?php echo \checked( 'wordpress-post-format', \get_option( 'activitypub_object_type', 'note' ) ); ?> /> <?php \esc_html_e( 'WordPress Post-Format', 'activitypub' ); ?></label> - <span class="description"><?php \esc_html_e( 'Maps the WordPress Post-Format to the ActivityPub Object Type.', 'activitypub' ); ?></span>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><?php \esc_html_e( 'Supported post types', 'activitypub' ); ?></th>
|
||||
<td>
|
||||
<fieldset>
|
||||
<?php \esc_html_e( 'Enable ActivityPub support for the following post types:', 'activitypub' ); ?>
|
||||
|
||||
<?php $post_types = \get_post_types( array( 'public' => true ), 'objects' ); ?>
|
||||
<?php $support_post_types = \get_option( 'activitypub_support_post_types', array( 'post', 'page' ) ) ? \get_option( 'activitypub_support_post_types', array( 'post', 'page' ) ) : array(); ?>
|
||||
<ul>
|
||||
<?php foreach ( $post_types as $post_type ) { ?>
|
||||
<li>
|
||||
<input type="checkbox" id="activitypub_support_post_types" name="activitypub_support_post_types[]" value="<?php echo \esc_attr( $post_type->name ); ?>" <?php echo \checked( true, \in_array( $post_type->name, $support_post_types, true ) ); ?> />
|
||||
<label for="<?php echo \esc_attr( $post_type->name ); ?>"><?php echo \esc_html( $post_type->label ); ?></label>
|
||||
</li>
|
||||
<?php } ?>
|
||||
</ul>
|
||||
</fieldset>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<?php \esc_html_e( 'Hashtags', 'activitypub' ); ?>
|
||||
</th>
|
||||
<td>
|
||||
<p>
|
||||
<label><input type="checkbox" name="activitypub_use_hashtags" id="activitypub_use_hashtags" value="1" <?php echo \checked( '1', \get_option( 'activitypub_use_hashtags', '1' ) ); ?> /> <?php \_e( 'Add hashtags in the content as native tags and replace the <code>#tag</code> with the tag-link.', 'activitypub' ); ?></label>
|
||||
</p>
|
||||
<p>
|
||||
<label><input type="checkbox" name="activitypub_add_tags_as_hashtags" id="activitypub_add_tags_as_hashtags" value="1" <?php echo \checked( '1', \get_option( 'activitypub_add_tags_as_hashtags', '0' ) ); ?> /> <?php \_e( 'Add all tags as hashtags to the end of each activity.', 'activitypub' ); ?></label>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<?php \do_settings_fields( 'activitypub', 'activity' ); ?>
|
||||
|
||||
<h2><?php \esc_html_e( 'Server', 'activitypub' ); ?></h2>
|
||||
|
||||
<p><?php \esc_html_e( 'Server related settings.', 'activitypub' ); ?></p>
|
||||
|
||||
<?php
|
||||
// load the existing blacklist from the WordPress options table
|
||||
$activitypub_blacklist = \trim( \implode( PHP_EOL, \ActivityPub\get_blacklist() ), PHP_EOL );
|
||||
?>
|
||||
|
||||
<table class="form-table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<?php \esc_html_e( 'Blacklist', 'activitypub' ); ?>
|
||||
</th>
|
||||
<td>
|
||||
<textarea name="activitypub_blacklist" id="activitypub_blacklist" rows="10" cols="50" class="large-text"><?php echo $activitypub_blacklist; ?></textarea>
|
||||
<p class="description"><?php \_e( 'A list of hosts, you want to block, one host per line. Please use only the host/domain of the server you want to block, without <code>http://</code> and without <code>www.</code>. For example <code>example.com</code>.', 'activitypub' ); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<?php \do_settings_fields( 'activitypub', 'server' ); ?>
|
||||
|
||||
<?php \do_settings_sections( 'activitypub' ); ?>
|
||||
|
||||
<?php \submit_button(); ?>
|
||||
</form>
|
||||
|
||||
<p>
|
||||
<small><?php _e( 'If you like this plugin, what about a small <a href="https://notiz.blog/donate">donation</a>?', 'activitypub' ); ?></small>
|
||||
</p>
|
||||
</div>
|
83
wp-content/plugins/authLdap-2.3.1/.ci/50-init.ldif
Normal file
83
wp-content/plugins/authLdap-2.3.1/.ci/50-init.ldif
Normal file
@ -0,0 +1,83 @@
|
||||
dn: dc=test space,{{ LDAP_BASE_DN }}
|
||||
changetype: add
|
||||
dc: test space
|
||||
description: LDAP Example with space
|
||||
objectClass: dcObject
|
||||
objectClass: organization
|
||||
o: test space
|
||||
|
||||
dn: cn=Manager,{{ LDAP_BASE_DN }}
|
||||
changetype: add
|
||||
cn: Manager
|
||||
objectClass: organizationalRole
|
||||
|
||||
dn: ou=test,{{ LDAP_BASE_DN }}
|
||||
changetype: add
|
||||
objectClass: organizationalUnit
|
||||
ou: test
|
||||
|
||||
dn: uid=user1,{{ LDAP_BASE_DN }}
|
||||
changetype: add
|
||||
objectClass: account
|
||||
objectClass: simpleSecurityObject
|
||||
uid: user1
|
||||
userPassword: user1
|
||||
|
||||
dn: cn=group1,{{ LDAP_BASE_DN }}
|
||||
changetype: add
|
||||
objectclass: groupOfUniqueNames
|
||||
cn: group1
|
||||
uniqueMember: uid=user1,{{ LDAP_BASE_DN }}
|
||||
|
||||
dn: uid=user2,{{ LDAP_BASE_DN }}
|
||||
changetype: add
|
||||
objectClass: account
|
||||
objectClass: simpleSecurityObject
|
||||
uid: user2
|
||||
userPassword: user2
|
||||
|
||||
dn: cn=group2,{{ LDAP_BASE_DN }}
|
||||
changetype: add
|
||||
objectclass: groupOfUniqueNames
|
||||
cn: group2
|
||||
uniqueMember: uid=user2,{{ LDAP_BASE_DN }}
|
||||
|
||||
dn: uid=user3,{{ LDAP_BASE_DN }}
|
||||
changetype: add
|
||||
objectClass: account
|
||||
objectClass: simpleSecurityObject
|
||||
uid: user3
|
||||
userPassword: user!"
|
||||
|
||||
dn: cn=group3,{{ LDAP_BASE_DN }}
|
||||
changetype: add
|
||||
objectclass: groupOfUniqueNames
|
||||
cn: group3
|
||||
uniqueMember: uid=user2,{{ LDAP_BASE_DN }}
|
||||
uniqueMember: uid=user3,{{ LDAP_BASE_DN }}
|
||||
|
||||
dn: uid=user 4,{{ LDAP_BASE_DN }}
|
||||
changetype: add
|
||||
objectClass: account
|
||||
objectClass: simpleSecurityObject
|
||||
uid: user 4
|
||||
userPassword: user!"
|
||||
|
||||
dn: cn=group4,{{ LDAP_BASE_DN }}
|
||||
changetype: add
|
||||
objectclass: groupOfUniqueNames
|
||||
cn: group4
|
||||
uniqueMember: uid=user 4,{{ LDAP_BASE_DN }}
|
||||
|
||||
dn: uid=user 5,dc=test space,{{ LDAP_BASE_DN }}
|
||||
changetype: add
|
||||
objectClass: account
|
||||
objectClass: simpleSecurityObject
|
||||
uid: user 5
|
||||
userPassword: user!"
|
||||
|
||||
dn: cn=group5,{{ LDAP_BASE_DN }}
|
||||
changetype: add
|
||||
objectclass: groupOfUniqueNames
|
||||
cn: group5
|
||||
uniqueMember: uid=user 5,dc=test space,{{ LDAP_BASE_DN }}
|
42
wp-content/plugins/authLdap-2.3.1/.ci/OpenLDAP/slapd.conf
Normal file
42
wp-content/plugins/authLdap-2.3.1/.ci/OpenLDAP/slapd.conf
Normal file
@ -0,0 +1,42 @@
|
||||
##
|
||||
# Global Directives
|
||||
##
|
||||
|
||||
# Schema and objectClass definitions
|
||||
include /etc/ldap/schema/core.schema
|
||||
include /etc/ldap/schema/cosine.schema
|
||||
include /etc/ldap/schema/nis.schema
|
||||
include /etc/ldap/schema/inetorgperson.schema
|
||||
|
||||
moduleload back_hdb
|
||||
|
||||
disallow bind_anon
|
||||
|
||||
##
|
||||
# Test DB
|
||||
##
|
||||
|
||||
database hdb
|
||||
|
||||
suffix "dc=example,dc=com"
|
||||
|
||||
rootdn "cn=Manager,dc=example,dc=com"
|
||||
rootpw insecure
|
||||
|
||||
# The database directory MUST exist prior to running slapd AND
|
||||
# change path as necessary
|
||||
directory /tmp/ldap_db/
|
||||
|
||||
##
|
||||
# ACL
|
||||
##
|
||||
|
||||
# The userPassword by default can be changed
|
||||
# by the entry owning it if they are authenticated.
|
||||
# Others should not be able to see it, except the
|
||||
# admin entry below
|
||||
# These access lines apply to database #1 only
|
||||
access to attrs=userPassword,shadowLastChange
|
||||
by anonymous auth
|
||||
by self write
|
||||
by * none
|
16
wp-content/plugins/authLdap-2.3.1/.ci/OpenLDAP_run.sh
Normal file
16
wp-content/plugins/authLdap-2.3.1/.ci/OpenLDAP_run.sh
Normal file
@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
LDAP_DB=/tmp/ldap_db
|
||||
|
||||
echo "Creating database directory"
|
||||
|
||||
rm -rf ${LDAP_DB} && mkdir ${LDAP_DB} && cp /usr/share/doc/slapd/examples/DB_CONFIG ${LDAP_DB}
|
||||
|
||||
echo "Launching OpenLDAP ..."
|
||||
|
||||
# Start slapd with non root privileges
|
||||
slapd -h "ldap://0.0.0.0:3890/" -f ${DIR}/OpenLDAP/slapd.conf
|
||||
|
||||
# Wait for LDAP to start
|
||||
sleep 1
|
@ -0,0 +1,6 @@
|
||||
dn: dc=example,dc=com
|
||||
dc: example
|
||||
description: LDAP Example
|
||||
objectClass: dcObject
|
||||
objectClass: organization
|
||||
o: example
|
@ -0,0 +1,6 @@
|
||||
dn: dc=test space,dc=example,dc=com
|
||||
dc: test space
|
||||
description: LDAP Example with space
|
||||
objectClass: dcObject
|
||||
objectClass: organization
|
||||
o: test space
|
@ -0,0 +1,3 @@
|
||||
dn: cn=Manager,dc=example,dc=com
|
||||
cn: Manager
|
||||
objectClass: organizationalRole
|
@ -0,0 +1,3 @@
|
||||
dn: ou=test,dc=example,dc=com
|
||||
objectClass: organizationalUnit
|
||||
ou: test
|
@ -0,0 +1,5 @@
|
||||
dn: uid=user1,dc=example,dc=com
|
||||
objectClass: account
|
||||
objectClass: simpleSecurityObject
|
||||
uid: user1
|
||||
userPassword: user1
|
@ -0,0 +1,16 @@
|
||||
dn: cn=group1,dc=example,dc=com
|
||||
objectclass: groupOfUniqueNames
|
||||
cn: group1
|
||||
uniqueMember: uid=user1,dc=example,dc=com
|
||||
|
||||
dn: uid=user2,dc=example,dc=com
|
||||
objectClass: account
|
||||
objectClass: simpleSecurityObject
|
||||
uid: user2
|
||||
userPassword: user2
|
||||
|
||||
dn: cn=group2,dc=example,dc=com
|
||||
objectclass: groupOfUniqueNames
|
||||
cn: group2
|
||||
uniqueMember: uid=user2,dc=example,dc=com
|
||||
|
@ -0,0 +1,14 @@
|
||||
dn: cn=group3,dc=example,dc=com
|
||||
objectclass: groupOfUniqueNames
|
||||
cn: group3
|
||||
uniqueMember: uid=user2,dc=example,dc=com
|
||||
uniqueMember: uid=user3,dc=example,dc=com
|
||||
|
||||
dn: uid=user3,dc=example,dc=com
|
||||
objectClass: account
|
||||
objectClass: simpleSecurityObject
|
||||
uid: user3
|
||||
userPassword: user!"
|
||||
|
||||
|
||||
|
@ -0,0 +1,13 @@
|
||||
dn: cn=group4,dc=example,dc=com
|
||||
objectclass: groupOfUniqueNames
|
||||
cn: group4
|
||||
uniqueMember: uid=user 4,dc=example,dc=com
|
||||
|
||||
dn: uid=user 4,dc=example,dc=com
|
||||
objectClass: account
|
||||
objectClass: simpleSecurityObject
|
||||
uid: user 4
|
||||
userPassword: user!"
|
||||
|
||||
|
||||
|
@ -0,0 +1,13 @@
|
||||
dn: cn=group5,dc=example,dc=com
|
||||
objectclass: groupOfUniqueNames
|
||||
cn: group5
|
||||
uniqueMember: uid=user 5,dc=test space,dc=example,dc=com
|
||||
|
||||
dn: uid=user 5,dc=test space,dc=example,dc=com
|
||||
objectClass: account
|
||||
objectClass: simpleSecurityObject
|
||||
uid: user 5
|
||||
userPassword: user!"
|
||||
|
||||
|
||||
|
13
wp-content/plugins/authLdap-2.3.1/.ci/load_fixtures.sh
Normal file
13
wp-content/plugins/authLdap-2.3.1/.ci/load_fixtures.sh
Normal file
@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
FIXTURES_DIR="$DIR/ldif"
|
||||
|
||||
load_fixture () {
|
||||
ldapadd -x -H ldap://127.0.0.1:3890/ -D "cn=Manager,dc=example,dc=com" -w insecure -f $1
|
||||
}
|
||||
|
||||
for FIXTURE in `ls ${FIXTURES_DIR}`
|
||||
do
|
||||
load_fixture "${FIXTURES_DIR}/${FIXTURE}"
|
||||
done;
|
1
wp-content/plugins/authLdap-2.3.1/.ci/php.ini
Normal file
1
wp-content/plugins/authLdap-2.3.1/.ci/php.ini
Normal file
@ -0,0 +1 @@
|
||||
extension=ldap.so
|
3
wp-content/plugins/authLdap-2.3.1/.gitignore
vendored
Normal file
3
wp-content/plugins/authLdap-2.3.1/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
vendor
|
||||
composer.lock
|
||||
.svnAccess
|
26
wp-content/plugins/authLdap-2.3.1/.rsyncIgnore
Normal file
26
wp-content/plugins/authLdap-2.3.1/.rsyncIgnore
Normal file
@ -0,0 +1,26 @@
|
||||
svn
|
||||
build.xml
|
||||
tests
|
||||
VERSION
|
||||
Vagrantfile
|
||||
phpunit.*
|
||||
composer.*
|
||||
vendor
|
||||
tests
|
||||
report*
|
||||
build
|
||||
bin
|
||||
*~
|
||||
.*
|
||||
.gitignore
|
||||
.travis*
|
||||
composer.json
|
||||
docker-compose-mu.yml
|
||||
patchcoverage
|
||||
phpunit*
|
||||
tests
|
||||
wp-app
|
||||
wp-data
|
||||
dockersetup
|
||||
config
|
||||
docker-compose.yml
|
2
wp-content/plugins/authLdap-2.3.1/.svnAccess.dist
Normal file
2
wp-content/plugins/authLdap-2.3.1/.svnAccess.dist
Normal file
@ -0,0 +1,2 @@
|
||||
username = svnUsername
|
||||
password = svnPassword
|
6
wp-content/plugins/authLdap-2.3.1/.travis.after.sh
Normal file
6
wp-content/plugins/authLdap-2.3.1/.travis.after.sh
Normal file
@ -0,0 +1,6 @@
|
||||
set -x
|
||||
if [ "$TRAVIS_PHP_VERSION" = '5.6' ] ; then
|
||||
./vendor/bin/test-reporter --stdout > codeclimate.json
|
||||
curl -X POST -d @codeclimate.json -H "Content-Type: application/json" -H "User-Agent: Code Climate (PHP Test Reporter v1.0.1-dev)" https://codeclimate.com/test_reports
|
||||
php vendor/bin/coveralls
|
||||
fi
|
9
wp-content/plugins/authLdap-2.3.1/.travis.install.sh
Normal file
9
wp-content/plugins/authLdap-2.3.1/.travis.install.sh
Normal file
@ -0,0 +1,9 @@
|
||||
set -x
|
||||
if [ "$TRAVIS_PHP_VERSION" = 'hhvm' ] || [ "$TRAVIS_PHP_VERSION" = 'hhvm-nightly' ] ; then
|
||||
curl -sS https://getcomposer.org/installer > composer-installer.php
|
||||
hhvm composer-installer.php
|
||||
hhvm -v ResourceLimit.SocketDefaultTimeout=30 -v Http.SlowQueryThreshold=30000 composer.phar update --prefer-source
|
||||
else
|
||||
composer self-update
|
||||
composer update --prefer-source
|
||||
fi
|
42
wp-content/plugins/authLdap-2.3.1/.travis.yml
Normal file
42
wp-content/plugins/authLdap-2.3.1/.travis.yml
Normal file
@ -0,0 +1,42 @@
|
||||
# Travic-CI-Config file for authLdap
|
||||
#
|
||||
language: php
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- slapd
|
||||
- ldap-utils
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
include:
|
||||
- php: 5.4
|
||||
- php: 5.5
|
||||
- php: 5.6
|
||||
- php: 7.0
|
||||
- php: 7.1
|
||||
- php: 7.2
|
||||
- php: 7.3
|
||||
- php: hhvm
|
||||
- php: nightly
|
||||
allow_failures:
|
||||
- php: 5.4
|
||||
- php: 5.5
|
||||
- php: nightly
|
||||
- php: hhvm
|
||||
|
||||
before_script:
|
||||
- ./.travis.install.sh
|
||||
- phpenv config-add .ci/php.ini || return 0
|
||||
- .ci/OpenLDAP_run.sh
|
||||
- .ci/load_fixtures.sh
|
||||
- composer dumpautoload
|
||||
|
||||
script:
|
||||
# - ./vendor/bin/phpcs --standard=PSR2 ldap.php authLdap.php tests/
|
||||
- ./vendor/bin/phpunit --configuration=phpunit.travis.xml
|
||||
|
||||
after_script:
|
||||
- ./.travis.after.sh
|
||||
|
7
wp-content/plugins/authLdap-2.3.1/LICENSE.md
Normal file
7
wp-content/plugins/authLdap-2.3.1/LICENSE.md
Normal file
@ -0,0 +1,7 @@
|
||||
Copyright <YEAR> <COPYRIGHT HOLDER>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
95
wp-content/plugins/authLdap-2.3.1/README.md
Normal file
95
wp-content/plugins/authLdap-2.3.1/README.md
Normal file
@ -0,0 +1,95 @@
|
||||
# authLDAP
|
||||
|
||||
[](https://gitter.im/heiglandreas/authLdap?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
Use your existing LDAP as authentication-backend for your wordpress!
|
||||
|
||||
[](https://travis-ci.org/heiglandreas/authLdap)
|
||||
[](https://wordpress.org/plugins/authldap/stats/)
|
||||
[](https://wordpress.org/plugins/authldap/)
|
||||
[](https://wordpress.org/plugins/authldap/)
|
||||
[](https://codeclimate.com/github/heiglandreas/authLdap)
|
||||
[](https://codeclimate.com/github/heiglandreas/authLdap)
|
||||
|
||||
So what are the differences to other Wordpress-LDAP-Authentication-Plugins?
|
||||
|
||||
* **Flexible**: You are totaly free in which LDAP-backend to use. Due to the extensive configuration you can
|
||||
freely decide how to do the authentication of your users. It simply depends on your
|
||||
filters
|
||||
* **Independent**: As soon as a user logs in, it is added/updated to the Wordpress' user-database
|
||||
to allow wordpress to always use the correct data. You only have to administer your users once.
|
||||
* **Failsafe**: Due to the users being created in Wordpress' User-database they can
|
||||
also log in when the LDAP-backend currently is gone.
|
||||
* **Role-Aware**: You can map Wordpress' roles to values of an existing LDAP-attribute.
|
||||
|
||||
## How does the plugin work?
|
||||
|
||||
Well, as a matter of fact it is rather simple. The plugin verifies, that the user
|
||||
seeking authentification can bind to the LDAP using the provided password.
|
||||
|
||||
If that is so, the user is either created or updated in the wordpress-user-database.
|
||||
This update includes the provided password (so the wordpress can authenticate users
|
||||
even without the LDAP), the users name according to the authLDAP-preferences and
|
||||
the status of the user depending on the groups-settings of the authLDAP-preferences
|
||||
|
||||
Writing this plugin would not have been as easy as it has been, without the
|
||||
wonderfull plugin of Alistair Young from http://www.weblogs.uhi.ac.uk/sm00ay/?p=45
|
||||
|
||||
## Configuration
|
||||
|
||||
### Usage Settings
|
||||
|
||||
* **Enable Authentication via LDAP** Whether you want to enable authLdap for login or not
|
||||
* **debug authLdap** When you have problems with authentication via LDAP you can enable a debugging mode here.
|
||||
* **Save entered Password** Decide whether passwords will be cached in your wordpress-installation. **Attention:** Without the cache your users will not be able to log into your site when your LDAP is down!
|
||||
|
||||
### Server Settings
|
||||
|
||||
* **LDAP Uri** This is the URI where your ldap-backend can be reached. More information are actually on the Configuration page
|
||||
* **Filter** This is the real McCoy! The filter you define here specifies how a user will be found. Before applying the filter a %s will be replaced with the given username. This means, when a user logs in using ‘foobar’ as username the following happens:
|
||||
|
||||
* **uid=%1$s** check for any LDAP-Entry that has an attribute ‘uid’ with value ‘foobar’
|
||||
* **(&(objectclass=posixAccount)(|(uid=%1$s)(mail=%1$s)))** check for any LDAP-Entry that has an attribute ‘objectclass’ with value ‘posixAccout’ and either a UID- or a mail-attribute with value ‘foobar’
|
||||
|
||||
This filter is rather powerfull if used wisely.
|
||||
|
||||
### Creating Users
|
||||
|
||||
* **Name-Attribute** Which Attribute from the LDAP contains the Full or the First name of the user trying to log in. This defaults to name
|
||||
* **Second Name Attribute** If the above Name-Attribute only contains the First Name of the user you can here specify an Attribute that contains the second name. This field is empty by default
|
||||
* **User-ID Attribute** This field will be used as login-name for wordpress. Please give the Attribute, that is used to identify the user. This should be the same as you used in the above Filter-Option. This field defaults to uid
|
||||
* **Mail Attribute** Which Attribute holds the eMail-Address of the user? If more than one eMail-Address are stored in the LDAP, only the first given is used. This field defaults to mail
|
||||
* **Web-Attribute** If your users have a personal page (URI) stored in the LDAP, it can be provided here. This field is empty by default
|
||||
|
||||
### User-Groups for Roles
|
||||
|
||||
* **Group-Attribute** This is the attribute that defines the Group-ID that can be matched against the Groups defined further down This field defaults to gidNumber.
|
||||
* **Group-Filter** Here you can add the filter for selecting groups for the currentlly logged in user The Filter should contain the string %s which will be replaced by the login-name of the currently logged in
|
||||
|
||||
|
||||
## FAQ
|
||||
|
||||
<dl>
|
||||
<dt>Can I change a users password with this plugin?</dt>
|
||||
<dd>Short Answer: <strong>No</strong>!<br>Long Answer: As the users credentials are not
|
||||
only used for a wordpress-site when you authenticate against an LDAP but for
|
||||
many other services also chances are great that there is a centralized place
|
||||
where password-changes shall be made. We'll later allow inclusion of a link
|
||||
to such a place but currently it's not available. And as password-hashing and
|
||||
where to store it requires deeper insight into the LDAP-Server then most users
|
||||
have and admins are willing to give, password changes are out of scope of this
|
||||
plugin. If you know exactyl what you do, you might want to have a look at
|
||||
<a href="https://github.com/heiglandreas/authLdap/issues/54#issuecomment-125851029">
|
||||
issue 54</a>
|
||||
wherer a way of adding it is described!
|
||||
</dd>
|
||||
<dt>Can I add a user to the LDAP when she creates a user-account on wordpress?</dt>
|
||||
<dd>Short Answer: <strong>No</strong>!<br>Long Answer: Even though that is technically possible
|
||||
it's not in the scope of this plugin. As creating a user in an LDAP often involves
|
||||
an administrative process that has already been implemented in your departments
|
||||
administration it doesn't make sense to rebuild that - in most cases highly
|
||||
individual - process in this plugin. If you know exactly what you do, have a look at
|
||||
<a href="https://github.com/heiglandreas/authLdap/issues/65">issue 65</a>
|
||||
where <a href="https://github.com/wtfiwtz">wtfiwtz</a> shows how to implement that feature.
|
||||
</dd>
|
||||
</dl>
|
1
wp-content/plugins/authLdap-2.3.1/VERSION
Normal file
1
wp-content/plugins/authLdap-2.3.1/VERSION
Normal file
@ -0,0 +1 @@
|
||||
2.3.1
|
28
wp-content/plugins/authLdap-2.3.1/Vagrantfile
vendored
Normal file
28
wp-content/plugins/authLdap-2.3.1/Vagrantfile
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
# -*- mode: ruby -*-
|
||||
# vi: set ft=ruby :
|
||||
|
||||
$install_ldap = <<SCRIPT
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get -yq update
|
||||
apt-get -yq --no-install-suggests --no-install-recommends --force-yes install slapd ldap-utils apparmor-utils
|
||||
sudo aa-complain /usr/sbin/slapd
|
||||
SCRIPT
|
||||
|
||||
$setup_vagrant_user_environment = <<SCRIPT
|
||||
if ! grep "cd /vagrant" /home/vagrant/.profile > /dev/null; then
|
||||
echo "cd /vagrant" >> /home/vagrant/.profile
|
||||
fi
|
||||
SCRIPT
|
||||
|
||||
Vagrant.configure(2) do |config|
|
||||
config.vm.box = 'bento/ubuntu-14.04'
|
||||
config.vm.box_check_update = false
|
||||
|
||||
# LDAP port
|
||||
config.vm.network 'forwarded_port', guest: 3890, host: 3890
|
||||
|
||||
config.vm.provision 'shell', inline: $install_ldap
|
||||
config.vm.provision 'shell', privileged: false, inline: '/vagrant/.ci/OpenLDAP_run.sh', :run => 'always'
|
||||
config.vm.provision 'shell', privileged: false, inline: '/vagrant/.ci/load_fixtures.sh', :run => 'always'
|
||||
config.vm.provision 'shell', inline: $setup_vagrant_user_environment
|
||||
end
|
9
wp-content/plugins/authLdap-2.3.1/authLdap.css
Normal file
9
wp-content/plugins/authLdap-2.3.1/authLdap.css
Normal file
@ -0,0 +1,9 @@
|
||||
.row {
|
||||
overflow: hidden;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.element {
|
||||
float: right;
|
||||
text-align: left;
|
||||
}
|
835
wp-content/plugins/authLdap-2.3.1/authLdap.php
Normal file
835
wp-content/plugins/authLdap-2.3.1/authLdap.php
Normal file
@ -0,0 +1,835 @@
|
||||
<?php
|
||||
/*
|
||||
Plugin Name: AuthLDAP
|
||||
Plugin URI: https://github.com/heiglandreas/authLdap
|
||||
Description: This plugin allows you to use your existing LDAP as authentication base for WordPress
|
||||
Version: 2.3.1
|
||||
Author: Andreas Heigl <andreas@heigl.org>
|
||||
Author URI: http://andreas.heigl.org
|
||||
License: MIT
|
||||
License URI: https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
require_once dirname(__FILE__) . '/ldap.php';
|
||||
|
||||
function authLdap_debug($message)
|
||||
{
|
||||
if (authLdap_get_option('Debug')) {
|
||||
error_log('[AuthLDAP] ' . $message, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function authLdap_addmenu()
|
||||
{
|
||||
if (! is_multisite()) {
|
||||
add_options_page('AuthLDAP', 'AuthLDAP', 'manage_options', basename(__FILE__), 'authLdap_options_panel');
|
||||
} else {
|
||||
add_submenu_page('settings.php', 'AuthLDAP', 'AuthLDAP', 'manage_options', 'authldap', 'authLdap_options_panel');
|
||||
}
|
||||
}
|
||||
|
||||
function authLdap_get_post($name, $default = '')
|
||||
{
|
||||
return isset($_POST[$name]) ? $_POST[$name] : $default;
|
||||
}
|
||||
|
||||
function authLdap_options_panel()
|
||||
{
|
||||
// inclusde style sheet
|
||||
wp_enqueue_style('authLdap-style', plugin_dir_url(__FILE__) . 'authLdap.css');
|
||||
|
||||
if (($_SERVER['REQUEST_METHOD'] == 'POST') && array_key_exists('ldapOptionsSave', $_POST)) {
|
||||
$new_options = array(
|
||||
'Enabled' => authLdap_get_post('authLDAPAuth', false),
|
||||
'CachePW' => authLdap_get_post('authLDAPCachePW', false),
|
||||
'URI' => authLdap_get_post('authLDAPURI'),
|
||||
'URISeparator' => authLdap_get_post('authLDAPURISeparator'),
|
||||
'StartTLS' => authLdap_get_post('authLDAPStartTLS', false),
|
||||
'Filter' => authLdap_get_post('authLDAPFilter'),
|
||||
'NameAttr' => authLdap_get_post('authLDAPNameAttr'),
|
||||
'SecName' => authLdap_get_post('authLDAPSecName'),
|
||||
'UidAttr' => authLdap_get_post('authLDAPUidAttr'),
|
||||
'MailAttr' => authLdap_get_post('authLDAPMailAttr'),
|
||||
'WebAttr' => authLdap_get_post('authLDAPWebAttr'),
|
||||
'Groups' => authLdap_get_post('authLDAPGroups', array()),
|
||||
'GroupSeparator'=> authLdap_get_post('authLDAPGroupSeparator', ','),
|
||||
'Debug' => authLdap_get_post('authLDAPDebug', false),
|
||||
'GroupBase' => authLdap_get_post('authLDAPGroupBase'),
|
||||
'GroupAttr' => authLdap_get_post('authLDAPGroupAttr'),
|
||||
'GroupFilter' => authLdap_get_post('authLDAPGroupFilter'),
|
||||
'DefaultRole' => authLdap_get_post('authLDAPDefaultRole'),
|
||||
'GroupEnable' => authLdap_get_post('authLDAPGroupEnable', false),
|
||||
'GroupOverUser' => authLdap_get_post('authLDAPGroupOverUser', false),
|
||||
'DoNotOverwriteNonLdapUsers' => authLdap_get_post('authLDAPDoNotOverwriteNonLdapUsers', false),
|
||||
);
|
||||
if (authLdap_set_options($new_options)) {
|
||||
echo "<div class='updated'><p>Saved Options!</p></div>";
|
||||
} else {
|
||||
echo "<div class='error'><p>Could not save Options!</p></div>";
|
||||
}
|
||||
}
|
||||
|
||||
// Do some initialization for the admin-view
|
||||
$authLDAP = authLdap_get_option('Enabled');
|
||||
$authLDAPCachePW = authLdap_get_option('CachePW');
|
||||
$authLDAPURI = authLdap_get_option('URI');
|
||||
$authLDAPURISeparator = authLdap_get_option('URISeparator');
|
||||
$authLDAPStartTLS = authLdap_get_option('StartTLS');
|
||||
$authLDAPFilter = authLdap_get_option('Filter');
|
||||
$authLDAPNameAttr = authLdap_get_option('NameAttr');
|
||||
$authLDAPSecName = authLdap_get_option('SecName');
|
||||
$authLDAPMailAttr = authLdap_get_option('MailAttr');
|
||||
$authLDAPUidAttr = authLdap_get_option('UidAttr');
|
||||
$authLDAPWebAttr = authLdap_get_option('WebAttr');
|
||||
$authLDAPGroups = authLdap_get_option('Groups');
|
||||
$authLDAPGroupSeparator= authLdap_get_option('GroupSeparator');
|
||||
$authLDAPDebug = authLdap_get_option('Debug');
|
||||
$authLDAPGroupBase = authLdap_get_option('GroupBase');
|
||||
$authLDAPGroupAttr = authLdap_get_option('GroupAttr');
|
||||
$authLDAPGroupFilter = authLdap_get_option('GroupFilter');
|
||||
$authLDAPDefaultRole = authLdap_get_option('DefaultRole');
|
||||
$authLDAPGroupEnable = authLdap_get_option('GroupEnable');
|
||||
$authLDAPGroupOverUser = authLdap_get_option('GroupOverUser');
|
||||
$authLDAPDoNotOverwriteNonLdapUsers = authLdap_get_option('DoNotOverwriteNonLdapUsers');
|
||||
|
||||
$tChecked = ($authLDAP) ? ' checked="checked"' : '';
|
||||
$tDebugChecked = ($authLDAPDebug) ? ' checked="checked"' : '';
|
||||
$tPWChecked = ($authLDAPCachePW) ? ' checked="checked"' : '';
|
||||
$tGroupChecked = ($authLDAPGroupEnable) ? ' checked="checked"' : '';
|
||||
$tGroupOverUserChecked = ($authLDAPGroupOverUser) ? ' checked="checked"' : '';
|
||||
$tStartTLSChecked = ($authLDAPStartTLS) ? ' checked="checked"' : '';
|
||||
$tDoNotOverwriteNonLdapUsers = ($authLDAPDoNotOverwriteNonLdapUsers) ? ' checked="checked"' : '';
|
||||
|
||||
$roles = new WP_Roles();
|
||||
|
||||
$action = $_SERVER['REQUEST_URI'];
|
||||
if (! extension_loaded('ldap')) {
|
||||
echo '<div class="warning">The LDAP-Extension is not available on your '
|
||||
. 'WebServer. Therefore Everything you can alter here does not '
|
||||
. 'make any sense!</div>';
|
||||
}
|
||||
|
||||
include dirname(__FILE__) . '/view/admin.phtml';
|
||||
}
|
||||
|
||||
/**
|
||||
* get a LDAP server object
|
||||
*
|
||||
* throws exception if there is a problem connecting
|
||||
*
|
||||
* @conf boolean authLDAPDebug true, if debugging should be turned on
|
||||
* @conf string authLDAPURI LDAP server URI
|
||||
*
|
||||
* @return Org_Heigl\AuthLdap\LDAP LDAP server object
|
||||
*/
|
||||
function authLdap_get_server()
|
||||
{
|
||||
static $_ldapserver = null;
|
||||
if (is_null($_ldapserver)) {
|
||||
$authLDAPDebug = authLdap_get_option('Debug');
|
||||
$authLDAPURI = explode(
|
||||
authLdap_get_option('URISeparator', ' '),
|
||||
authLdap_get_option('URI')
|
||||
);
|
||||
$authLDAPStartTLS = authLdap_get_option('StartTLS');
|
||||
|
||||
//$authLDAPURI = 'ldap:/foo:bar@server/trallala';
|
||||
authLdap_debug('connect to LDAP server');
|
||||
require_once dirname(__FILE__) . '/src/LdapList.php';
|
||||
$_ldapserver = new \Org_Heigl\AuthLdap\LdapList();
|
||||
foreach ($authLDAPURI as $uri) {
|
||||
$_ldapserver->addLdap(new \Org_Heigl\AuthLdap\LDAP($uri, $authLDAPDebug, $authLDAPStartTLS));
|
||||
}
|
||||
}
|
||||
return $_ldapserver;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method authenticates a user using either the LDAP or, if LDAP is not
|
||||
* available, the local database
|
||||
*
|
||||
* For this we store the hashed passwords in the WP_Database to ensure working
|
||||
* conditions even without an LDAP-Connection
|
||||
*
|
||||
* @param null|WP_User|WP_Error
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param boolean $already_md5
|
||||
* @return boolean true, if login was successfull or false, if it wasn't
|
||||
* @conf boolean authLDAP true, if authLDAP should be used, false if not. Defaults to false
|
||||
* @conf string authLDAPFilter LDAP filter to use to find correct user, defaults to '(uid=%s)'
|
||||
* @conf string authLDAPNameAttr LDAP attribute containing user (display) name, defaults to 'name'
|
||||
* @conf string authLDAPSecName LDAP attribute containing second name, defaults to ''
|
||||
* @conf string authLDAPMailAttr LDAP attribute containing user e-mail, defaults to 'mail'
|
||||
* @conf string authLDAPUidAttr LDAP attribute containing user id (the username we log on with), defaults to 'uid'
|
||||
* @conf string authLDAPWebAttr LDAP attribute containing user website, defaults to ''
|
||||
* @conf string authLDAPDefaultRole default role for authenticated user, defaults to ''
|
||||
* @conf boolean authLDAPGroupEnable true, if we try to map LDAP groups to Wordpress roles
|
||||
* @conf boolean authLDAPGroupOverUser true, if LDAP Groups have precedence over existing user roles
|
||||
*/
|
||||
function authLdap_login($user, $username, $password, $already_md5 = false)
|
||||
{
|
||||
// don't do anything when authLDAP is disabled
|
||||
if (! authLdap_get_option('Enabled')) {
|
||||
authLdap_debug('LDAP disabled in AuthLDAP plugin options (use the first option in the AuthLDAP options to enable it)');
|
||||
return $user;
|
||||
}
|
||||
|
||||
// If the user has already been authenticated (only in that case we get a
|
||||
// WP_User-Object as $user) we skip LDAP-authentication and simply return
|
||||
// the existing user-object
|
||||
if ($user instanceof WP_User) {
|
||||
authLdap_debug(sprintf(
|
||||
'User %s has already been authenticated - skipping LDAP-Authentication',
|
||||
$user->get('nickname')));
|
||||
return $user;
|
||||
}
|
||||
|
||||
authLdap_debug("User '$username' logging in");
|
||||
|
||||
if ($username == 'admin') {
|
||||
authLdap_debug('Doing nothing for possible local user admin');
|
||||
return $user;
|
||||
}
|
||||
|
||||
global $wpdb, $error;
|
||||
try {
|
||||
$authLDAP = authLdap_get_option('Enabled');
|
||||
$authLDAPFilter = authLdap_get_option('Filter');
|
||||
$authLDAPNameAttr = authLdap_get_option('NameAttr');
|
||||
$authLDAPSecName = authLdap_get_option('SecName');
|
||||
$authLDAPMailAttr = authLdap_get_option('MailAttr');
|
||||
$authLDAPUidAttr = authLdap_get_option('UidAttr');
|
||||
$authLDAPWebAttr = authLdap_get_option('WebAttr');
|
||||
$authLDAPDefaultRole = authLdap_get_option('DefaultRole');
|
||||
$authLDAPGroupEnable = authLdap_get_option('GroupEnable');
|
||||
$authLDAPGroupOverUser = authLdap_get_option('GroupOverUser');
|
||||
|
||||
if (! $username) {
|
||||
authLdap_debug('Username not supplied: return false');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $password) {
|
||||
authLdap_debug('Password not supplied: return false');
|
||||
$error = __('<strong>Error</strong>: The password field is empty.');
|
||||
return false;
|
||||
}
|
||||
// First check for valid values and set appropriate defaults
|
||||
if (! $authLDAPFilter) {
|
||||
$authLDAPFilter = '(uid=%s)';
|
||||
}
|
||||
if (! $authLDAPNameAttr) {
|
||||
$authLDAPNameAttr = 'name';
|
||||
}
|
||||
if (! $authLDAPMailAttr) {
|
||||
$authLDAPMailAttr = 'mail';
|
||||
}
|
||||
if (! $authLDAPUidAttr) {
|
||||
$authLDAPUidAttr = 'uid';
|
||||
}
|
||||
|
||||
// If already_md5 is TRUE, then we're getting the user/password from the cookie. As we don't want to store LDAP passwords in any
|
||||
// form, we've already replaced the password with the hashed username and LDAP_COOKIE_MARKER
|
||||
if ($already_md5) {
|
||||
if ($password == md5($username).md5($ldapCookieMarker)) {
|
||||
authLdap_debug('cookie authentication');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove slashes as noted on https://github.com/heiglandreas/authLdap/issues/108
|
||||
$password = stripslashes_deep($password);
|
||||
|
||||
// No cookie, so have to authenticate them via LDAP
|
||||
$result = false;
|
||||
try {
|
||||
authLdap_debug('about to do LDAP authentication');
|
||||
$result = authLdap_get_server()->Authenticate($username, $password, $authLDAPFilter);
|
||||
} catch (Exception $e) {
|
||||
authLdap_debug('LDAP authentication failed with exception: ' . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Rebind with the default credentials after the user has been loged in
|
||||
// Otherwise the credentials of the user trying to login will be used
|
||||
// This fixes #55
|
||||
authLdap_get_server()->bind();
|
||||
|
||||
if (true !== $result) {
|
||||
authLdap_debug('LDAP authentication failed');
|
||||
// TODO what to return? WP_User object, true, false, even an WP_Error object... all seem to fall back to normal wp user authentication
|
||||
return;
|
||||
}
|
||||
|
||||
authLdap_debug('LDAP authentication successfull');
|
||||
$attributes = array_values(
|
||||
array_filter(
|
||||
array(
|
||||
$authLDAPNameAttr,
|
||||
$authLDAPSecName,
|
||||
$authLDAPMailAttr,
|
||||
$authLDAPWebAttr,
|
||||
$authLDAPUidAttr
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
try {
|
||||
$attribs = authLdap_get_server()->search(
|
||||
sprintf($authLDAPFilter, $username),
|
||||
$attributes
|
||||
);
|
||||
// First get all the relevant group informations so we can see if
|
||||
// whether have been changes in group association of the user
|
||||
if (! isset($attribs[0]['dn'])) {
|
||||
authLdap_debug('could not get user attributes from LDAP');
|
||||
throw new UnexpectedValueException('dn has not been returned');
|
||||
}
|
||||
if (! isset($attribs[0][strtolower($authLDAPUidAttr)][0])) {
|
||||
authLdap_debug('could not get user attributes from LDAP');
|
||||
throw new UnexpectedValueException('The user-ID attribute has not been returned');
|
||||
|
||||
}
|
||||
|
||||
$dn = $attribs[0]['dn'];
|
||||
$realuid = $attribs[0][strtolower($authLDAPUidAttr)][0];
|
||||
} catch (Exception $e) {
|
||||
authLdap_debug('Exception getting LDAP user: ' . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
$uid = authLdap_get_uid($realuid);
|
||||
|
||||
// This fixes #172
|
||||
if (true == authLdap_get_option('DoNotOverwriteNonLdapUsers', false)) {
|
||||
if (! get_user_meta($uid, 'authLDAP')) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
$role = '';
|
||||
|
||||
// we only need this if either LDAP groups are disabled or
|
||||
// if the WordPress role of the user overrides LDAP groups
|
||||
if (!$authLDAPGroupEnable || !$authLDAPGroupOverUser) {
|
||||
$role = authLdap_user_role($uid);
|
||||
}
|
||||
|
||||
// do LDAP group mapping if needed
|
||||
// (if LDAP groups override worpress user role, $role is still empty)
|
||||
if (empty($role) && $authLDAPGroupEnable) {
|
||||
$role = authLdap_groupmap($realuid, $dn);
|
||||
authLdap_debug('role from group mapping: ' . $role);
|
||||
}
|
||||
|
||||
// if we don't have a role yet, use default role
|
||||
if (empty($role) && !empty($authLDAPDefaultRole)) {
|
||||
authLdap_debug('no role yet, set default role');
|
||||
$role = $authLDAPDefaultRole;
|
||||
}
|
||||
|
||||
if (empty($role)) {
|
||||
// Sorry, but you are not in any group that is allowed access
|
||||
trigger_error('no group found');
|
||||
authLdap_debug('user is not in any group that is allowed access');
|
||||
return false;
|
||||
} else {
|
||||
$roles = new WP_Roles();
|
||||
// not sure if this is needed, but it can't hurt
|
||||
if (!$roles->is_role($role)) {
|
||||
trigger_error('no group found');
|
||||
authLdap_debug('role is invalid');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// from here on, the user has access!
|
||||
// now, lets update some user details
|
||||
$user_info = array();
|
||||
$user_info['user_login'] = $realuid;
|
||||
$user_info['role'] = $role;
|
||||
$user_info['user_email'] = '';
|
||||
|
||||
// first name
|
||||
if (isset($attribs[0][strtolower($authLDAPNameAttr)][0])) {
|
||||
$user_info['first_name'] = $attribs[0][strtolower($authLDAPNameAttr)][0];
|
||||
}
|
||||
|
||||
// last name
|
||||
if (isset($attribs[0][strtolower($authLDAPSecName)][0])) {
|
||||
$user_info['last_name'] = $attribs[0][strtolower($authLDAPSecName)][0];
|
||||
}
|
||||
|
||||
// mail address
|
||||
if (isset($attribs[0][strtolower($authLDAPMailAttr)][0])) {
|
||||
$user_info['user_email'] = $attribs[0][strtolower($authLDAPMailAttr)][0];
|
||||
}
|
||||
|
||||
// website
|
||||
if (isset($attribs[0][strtolower($authLDAPWebAttr)][0])) {
|
||||
$user_info['user_url'] = $attribs[0][strtolower($authLDAPWebAttr)][0];
|
||||
}
|
||||
// display name, nickname, nicename
|
||||
if (array_key_exists('first_name', $user_info)) {
|
||||
$user_info['display_name'] = $user_info['first_name'];
|
||||
$user_info['nickname'] = $user_info['first_name'];
|
||||
$user_info['user_nicename'] = sanitize_title_with_dashes($user_info['first_name']);
|
||||
if (array_key_exists('last_name', $user_info)) {
|
||||
$user_info['display_name'] .= ' ' . $user_info['last_name'];
|
||||
$user_info['nickname'] .= ' ' . $user_info['last_name'];
|
||||
$user_info['user_nicename'] .= '_' . sanitize_title_with_dashes($user_info['last_name']);
|
||||
}
|
||||
}
|
||||
$user_info['user_nicename'] = substr($user_info['user_nicename'], 0, 50);
|
||||
|
||||
// optionally store the password into the wordpress database
|
||||
if (authLdap_get_option('CachePW')) {
|
||||
// Password will be hashed inside wp_update_user or wp_insert_user
|
||||
$user_info['user_pass'] = $password;
|
||||
} else {
|
||||
// clear the password
|
||||
$user_info['user_pass'] = '';
|
||||
}
|
||||
|
||||
// add uid if user exists
|
||||
if ($uid) {
|
||||
// found user in the database
|
||||
authLdap_debug('The LDAP user has an entry in the WP-Database');
|
||||
$user_info['ID'] = $uid;
|
||||
unset ($user_info['display_name'], $user_info['nickname']);
|
||||
$userid = wp_update_user($user_info);
|
||||
} else {
|
||||
// new wordpress account will be created
|
||||
authLdap_debug('The LDAP user does not have an entry in the WP-Database, a new WP account will be created');
|
||||
|
||||
$userid = wp_insert_user($user_info);
|
||||
}
|
||||
|
||||
// if the user exists, wp_insert_user will update the existing user record
|
||||
if (is_wp_error($userid)) {
|
||||
authLdap_debug('Error creating user : ' . $userid->get_error_message());
|
||||
trigger_error('Error creating user: ' . $userid->get_error_message());
|
||||
return $userid;
|
||||
}
|
||||
|
||||
authLdap_debug('user id = ' . $userid);
|
||||
|
||||
// flag the user as an ldap user so we can hide the password fields in the user profile
|
||||
update_user_meta($userid, 'authLDAP', true);
|
||||
|
||||
// return a user object upon positive authorization
|
||||
return new WP_User($userid);
|
||||
} catch (Exception $e) {
|
||||
authLdap_debug($e->getMessage() . '. Exception thrown in line ' . $e->getLine());
|
||||
trigger_error($e->getMessage() . '. Exception thrown in line ' . $e->getLine());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user's user id
|
||||
*
|
||||
* Returns null if username not found
|
||||
*
|
||||
* @param string $username username
|
||||
* @param string user id, null if not found
|
||||
*/
|
||||
function authLdap_get_uid($username)
|
||||
{
|
||||
global $wpdb;
|
||||
|
||||
// find out whether the user is already present in the database
|
||||
$uid = $wpdb->get_var(
|
||||
$wpdb->prepare(
|
||||
"SELECT ID FROM {$wpdb->users} WHERE user_login = %s",
|
||||
$username
|
||||
)
|
||||
);
|
||||
if ($uid) {
|
||||
authLdap_debug("Existing user, uid = {$uid}");
|
||||
return $uid;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user's current role
|
||||
*
|
||||
* Returns empty string if not found.
|
||||
*
|
||||
* @param int $uid wordpress user id
|
||||
* @return string role, empty if none found
|
||||
*/
|
||||
function authLdap_user_role($uid)
|
||||
{
|
||||
global $wpdb;
|
||||
|
||||
if (!$uid) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$meta_value = $wpdb->get_var("SELECT meta_value FROM {$wpdb->usermeta} WHERE meta_key = '{$wpdb->prefix}capabilities' AND user_id = {$uid}");
|
||||
|
||||
if (!$meta_value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$capabilities = unserialize($meta_value);
|
||||
$roles = is_array($capabilities) ? array_keys($capabilities) : array('');
|
||||
$role = $roles[0];
|
||||
|
||||
authLdap_debug("Existing user's role: {$role}");
|
||||
return $role;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get LDAP groups for user and map to role
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $dn
|
||||
* @return string role, empty string if no mapping found, first found role otherwise
|
||||
* @conf array authLDAPGroups, associative array, role => ldap_group
|
||||
* @conf string authLDAPGroupBase, base dn to look up groups
|
||||
* @conf string authLDAPGroupAttr, ldap attribute that holds name of group
|
||||
* @conf string authLDAPGroupFilter, LDAP filter to find groups. can contain %s and %dn% placeholders
|
||||
*/
|
||||
function authLdap_groupmap($username, $dn)
|
||||
{
|
||||
$authLDAPGroups = authLdap_sort_roles_by_capabilities(
|
||||
authLdap_get_option('Groups')
|
||||
);
|
||||
$authLDAPGroupBase = authLdap_get_option('GroupBase');
|
||||
$authLDAPGroupAttr = authLdap_get_option('GroupAttr');
|
||||
$authLDAPGroupFilter = authLdap_get_option('GroupFilter');
|
||||
$authLDAPGroupSeparator = authLdap_get_option('GroupSeparator');
|
||||
if (! $authLDAPGroupAttr) {
|
||||
$authLDAPGroupAttr = 'gidNumber';
|
||||
}
|
||||
if (! $authLDAPGroupFilter) {
|
||||
$authLDAPGroupFilter = '(&(objectClass=posixGroup)(memberUid=%s))';
|
||||
}
|
||||
if (! $authLDAPGroupSeparator) {
|
||||
$authLDAPGroupSeparator = ',';
|
||||
}
|
||||
|
||||
if (!is_array($authLDAPGroups) || count(array_filter(array_values($authLDAPGroups))) == 0) {
|
||||
authLdap_debug('No group names defined');
|
||||
return '';
|
||||
}
|
||||
|
||||
try {
|
||||
// To allow searches based on the DN instead of the uid, we replace the
|
||||
// string %dn% with the users DN.
|
||||
$authLDAPGroupFilter = str_replace(
|
||||
'%dn%',
|
||||
ldap_escape($dn, '', LDAP_ESCAPE_FILTER),
|
||||
$authLDAPGroupFilter
|
||||
);
|
||||
authLdap_debug('Group Filter: ' . json_encode($authLDAPGroupFilter));
|
||||
authLdap_debug('Group Base: ' . $authLDAPGroupBase);
|
||||
$groups = authLdap_get_server()->search(
|
||||
sprintf($authLDAPGroupFilter, ldap_escape($username, '', LDAP_ESCAPE_FILTER)),
|
||||
array($authLDAPGroupAttr),
|
||||
$authLDAPGroupBase
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
authLdap_debug('Exception getting LDAP group attributes: ' . $e->getMessage());
|
||||
return '';
|
||||
}
|
||||
|
||||
$grp = array();
|
||||
for ($i = 0; $i < $groups ['count']; $i++) {
|
||||
for ($k = 0; $k < $groups[$i][strtolower($authLDAPGroupAttr)]['count']; $k++) {
|
||||
$grp[] = $groups[$i][strtolower($authLDAPGroupAttr)][$k];
|
||||
}
|
||||
}
|
||||
|
||||
authLdap_debug('LDAP groups: ' . json_encode($grp));
|
||||
|
||||
// Check whether the user is member of one of the groups that are
|
||||
// allowed acces to the blog. If the user is not member of one of
|
||||
// The groups throw her out! ;-)
|
||||
// If the user is member of more than one group only the first one
|
||||
// will be taken into account!
|
||||
|
||||
$role = '';
|
||||
foreach ($authLDAPGroups as $key => $val) {
|
||||
$currentGroup = explode($authLDAPGroupSeparator, $val);
|
||||
// Remove whitespaces around the group-ID
|
||||
$currentGroup = array_map('trim', $currentGroup);
|
||||
if (0 < count(array_intersect($currentGroup, $grp))) {
|
||||
$role = $key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
authLdap_debug("Role from LDAP group: {$role}");
|
||||
return $role;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function disables the password-change fields in the users preferences.
|
||||
*
|
||||
* It does not make sense to authenticate via LDAP and then allow the user to
|
||||
* change the password only in the wordpress database. And changing the password
|
||||
* LDAP-wide can not be the scope of Wordpress!
|
||||
*
|
||||
* Whether the user is an LDAP-User or not is determined using the authLDAP-Flag
|
||||
* of the users meta-informations
|
||||
*
|
||||
* @return false, if the user whose prefs are viewed is an LDAP-User, true if
|
||||
* he isn't
|
||||
* @conf boolean authLDAP
|
||||
*/
|
||||
function authLdap_show_password_fields($return, $user)
|
||||
{
|
||||
if (! $user) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (get_user_meta($user->ID, 'authLDAP')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function disables the password reset for a user.
|
||||
*
|
||||
* It does not make sense to authenticate via LDAP and then allow the user to
|
||||
* reset the password only in the wordpress database. And changing the password
|
||||
* LDAP-wide can not be the scope of Wordpress!
|
||||
*
|
||||
* Whether the user is an LDAP-User or not is determined using the authLDAP-Flag
|
||||
* of the users meta-informations
|
||||
*
|
||||
* @author chaplina (https://github.com/chaplina)
|
||||
* @conf boolean authLDAP
|
||||
* @return false, if the user is an LDAP-User, true if he isn't
|
||||
*/
|
||||
function authLdap_allow_password_reset($return, $userid)
|
||||
{
|
||||
if (!(isset($userid))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (get_user_meta($userid, 'authLDAP')) {
|
||||
return false;
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the given roles by number of capabilities
|
||||
*
|
||||
* @param array $roles
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function authLdap_sort_roles_by_capabilities($roles)
|
||||
{
|
||||
global $wpdb;
|
||||
$myRoles = get_option($wpdb->get_blog_prefix() . 'user_roles');
|
||||
|
||||
authLdap_debug(print_r($roles, true));
|
||||
uasort($myRoles, 'authLdap_sortByCapabilitycount');
|
||||
|
||||
$return = array();
|
||||
|
||||
foreach ($myRoles as $key => $role) {
|
||||
if (isset($roles[$key])) {
|
||||
$return[$key] = $roles[$key];
|
||||
}
|
||||
}
|
||||
|
||||
authLdap_debug(print_r($return, true));
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort according to the number of capabilities
|
||||
*
|
||||
* @param $a
|
||||
* @param $b
|
||||
*/
|
||||
function authLdap_sortByCapabilitycount($a, $b)
|
||||
{
|
||||
if (count($a['capabilities']) > count($b['capabilities'])) {
|
||||
return -1;
|
||||
}
|
||||
if (count($a['capabilities']) < count($b['capabilities'])) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load AuthLDAP Options
|
||||
*
|
||||
* Sets and stores defaults if options are not up to date
|
||||
*/
|
||||
function authLdap_load_options($reload = false)
|
||||
{
|
||||
static $options = null;
|
||||
|
||||
// the current version for options
|
||||
$option_version_plugin = 1;
|
||||
|
||||
$optionFunction = 'get_option';
|
||||
if (is_multisite()) {
|
||||
$optionFunction = 'get_site_option';
|
||||
}
|
||||
if (is_null($options) || $reload) {
|
||||
$options = $optionFunction('authLDAPOptions', array());
|
||||
}
|
||||
|
||||
// check if option version has changed (or if it's there at all)
|
||||
if (!isset($options['Version']) || ($options['Version'] != $option_version_plugin)) {
|
||||
// defaults for all options
|
||||
$options_default = array(
|
||||
'Enabled' => false,
|
||||
'CachePW' => false,
|
||||
'URI' => '',
|
||||
'URISeparator' => ' ',
|
||||
'Filter' => '', // '(uid=%s)'
|
||||
'NameAttr' => '', // 'name'
|
||||
'SecName' => '',
|
||||
'UidAttr' => '', // 'uid'
|
||||
'MailAttr' => '', // 'mail'
|
||||
'WebAttr' => '',
|
||||
'Groups' => array(),
|
||||
'Debug' => false,
|
||||
'GroupAttr' => '', // 'gidNumber'
|
||||
'GroupFilter' => '', // '(&(objectClass=posixGroup)(memberUid=%s))'
|
||||
'DefaultRole' => '',
|
||||
'GroupEnable' => true,
|
||||
'GroupOverUser' => true,
|
||||
'Version' => $option_version_plugin,
|
||||
'DoNotOverwriteNonLdapUsers' => false,
|
||||
);
|
||||
|
||||
// check if we got a version
|
||||
if (!isset($options['Version'])) {
|
||||
// we just changed to the new option format
|
||||
// read old options, then delete them
|
||||
$old_option_new_option = array(
|
||||
'authLDAP' => 'Enabled',
|
||||
'authLDAPCachePW' => 'CachePW',
|
||||
'authLDAPURI' => 'URI',
|
||||
'authLDAPFilter' => 'Filter',
|
||||
'authLDAPNameAttr' => 'NameAttr',
|
||||
'authLDAPSecName' => 'SecName',
|
||||
'authLDAPUidAttr' => 'UidAttr',
|
||||
'authLDAPMailAttr' => 'MailAttr',
|
||||
'authLDAPWebAttr' => 'WebAttr',
|
||||
'authLDAPGroups' => 'Groups',
|
||||
'authLDAPDebug' => 'Debug',
|
||||
'authLDAPGroupAttr' => 'GroupAttr',
|
||||
'authLDAPGroupFilter' => 'GroupFilter',
|
||||
'authLDAPDefaultRole' => 'DefaultRole',
|
||||
'authLDAPGroupEnable' => 'GroupEnable',
|
||||
'authLDAPGroupOverUser' => 'GroupOverUser',
|
||||
);
|
||||
foreach ($old_option_new_option as $old_option => $new_option) {
|
||||
$value = get_option($old_option, null);
|
||||
if (!is_null($value)) {
|
||||
$options[$new_option] = $value;
|
||||
}
|
||||
delete_option($old_option);
|
||||
}
|
||||
delete_option('authLDAPCookieMarker');
|
||||
delete_option('authLDAPCookierMarker');
|
||||
}
|
||||
|
||||
// set default for all options that are missing
|
||||
foreach ($options_default as $key => $default) {
|
||||
if (!isset($options[$key])) {
|
||||
$options[$key] = $default;
|
||||
}
|
||||
}
|
||||
|
||||
// set new version and save
|
||||
$options['Version'] = $option_version_plugin;
|
||||
update_option('authLDAPOptions', $options);
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an individual option
|
||||
*/
|
||||
function authLdap_get_option($optionname, $default = null)
|
||||
{
|
||||
$options = authLdap_load_options();
|
||||
if (isset($options[$optionname]) && $options[$optionname]) {
|
||||
return $options[$optionname];
|
||||
}
|
||||
|
||||
if (null !== $default) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
//authLdap_debug('option name invalid: ' . $optionname);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set new options
|
||||
*/
|
||||
function authLdap_set_options($new_options = array())
|
||||
{
|
||||
// initialize the options with what we currently have
|
||||
$options = authLdap_load_options();
|
||||
|
||||
// set the new options supplied
|
||||
foreach ($new_options as $key => $value) {
|
||||
$options[$key] = $value;
|
||||
}
|
||||
|
||||
// store options
|
||||
$optionFunction = 'update_option';
|
||||
if (is_multisite()) {
|
||||
$optionFunction = 'update_site_option';
|
||||
}
|
||||
if ($optionFunction('authLDAPOptions', $options)) {
|
||||
// reload the option cache
|
||||
authLdap_load_options(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// could not set options
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not send an email after changing the password or the email of the user!
|
||||
*
|
||||
* @param boolean $result The initial resturn value
|
||||
* @param array $user The old userdata
|
||||
* @param array $newUserData The changed userdata
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function authLdap_send_change_email($result, $user, $newUserData)
|
||||
{
|
||||
if (get_usermeta($user['ID'], 'authLDAP')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
$hook = is_multisite() ? 'network_' : '';
|
||||
add_action($hook . 'admin_menu', 'authLdap_addmenu');
|
||||
add_filter('show_password_fields', 'authLdap_show_password_fields', 10, 2);
|
||||
add_filter('allow_password_reset', 'authLdap_allow_password_reset', 10, 2);
|
||||
add_filter('authenticate', 'authLdap_login', 10, 3);
|
||||
/** This only works from WP 4.3.0 on */
|
||||
add_filter('send_password_change_email', 'authLdap_send_change_email', 10, 3);
|
||||
add_filter('send_email_change_email', 'authLdap_send_change_email', 10, 3);
|
95
wp-content/plugins/authLdap-2.3.1/build.xml
Normal file
95
wp-content/plugins/authLdap-2.3.1/build.xml
Normal file
@ -0,0 +1,95 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<project name="ajaxComments" default="build" basedir=".">
|
||||
<php expression="include('vendor/autoload.php')"/>
|
||||
<loadfile property = "version" file = "VERSION">
|
||||
<filterchain>
|
||||
<striplinebreaks/>
|
||||
</filterchain>
|
||||
</loadfile>
|
||||
<target name="bumpversion">
|
||||
<echo>Bumping version to ${version}</echo>
|
||||
<reflexive>
|
||||
<fileset dir=".">
|
||||
<include name="index.php"/>
|
||||
<include name="authLdap.php"/>
|
||||
</fileset>
|
||||
<filterchain>
|
||||
<replaceregexp>
|
||||
<regexp pattern="Version:.*" replace="Version: ${version}"/>
|
||||
</replaceregexp>
|
||||
</filterchain>
|
||||
</reflexive>
|
||||
</target>
|
||||
<target name="build" depends="bumpversion,deploy.git,deploy.svn"/>
|
||||
<target name="sync.svn">
|
||||
<filesync
|
||||
rsyncPath="rsync"
|
||||
destinationDir="${project.basedir}/svn/trunk"
|
||||
sourceDir="${project.basedir}/"
|
||||
verbose="true"
|
||||
excludeFile="${project.basedir}/.rsyncIgnore"
|
||||
/>
|
||||
</target>
|
||||
<target name="deploy.svn" depends="sync.svn">
|
||||
<property override="true" file="${project.basedir}/.svnAccess" prefix="svnaccess" />
|
||||
<foreach param="dirname" target="svn.addFile">
|
||||
<fileset dir="${project.basedir}/svn/trunk">
|
||||
<include name="**/*"/>
|
||||
</fileset>
|
||||
</foreach>
|
||||
<echo message="${svnaccess.username}"/>
|
||||
<exec outputProperty="committedrevision" executable="svn" dir="${project.basedir}/svn/trunk">
|
||||
<arg value="commit"/>
|
||||
<arg value="--username"/>
|
||||
<arg value="${svnaccess.username}"/>
|
||||
<arg value="--password"/>
|
||||
<arg value="${svnaccess.password}"/>
|
||||
<arg value="--message"/>
|
||||
<arg value="Bumps version to ${version}"/>
|
||||
<arg value="--no-auth-cache"/>
|
||||
<arg value="--quiet"/>
|
||||
</exec>
|
||||
<!--svncommit
|
||||
username="${svnaccess.username}"
|
||||
password="${svnaccess.password}"
|
||||
workingcopy="${project.basedir}/svn"
|
||||
message="Bumps version to ${version}"
|
||||
nocache="true"
|
||||
/-->
|
||||
<echo message="Committed revision: ${committedrevision}"/>
|
||||
</target>
|
||||
|
||||
<target name="svn.addFile">
|
||||
<trycatch>
|
||||
<try>
|
||||
<svninfo workingcopy="${project.basedir}/svn/trunk/${dirname}"/>
|
||||
</try>
|
||||
<catch>
|
||||
<exec command="svn add ${project.basedir}/svn/trunk/${dirname}"/>
|
||||
<echo>${dirname}</echo>
|
||||
</catch>
|
||||
<finally>
|
||||
|
||||
</finally>
|
||||
</trycatch>
|
||||
<echo>${svn.info}</echo>
|
||||
</target>
|
||||
<target name="deploy.git">
|
||||
<exec executable="git" dir=".">
|
||||
<arg value="-m"/>
|
||||
<arg value="Bumps version to ${version}"/>
|
||||
</exec>
|
||||
<exec executable="git" dir=".">
|
||||
<arg value="tag"/>
|
||||
<arg value="-s"/>
|
||||
<arg value="-m"/>
|
||||
<arg value="Version ${version}"/>
|
||||
<arg value="${version}"/>
|
||||
</exec>
|
||||
<exec executable="git" dir=".">
|
||||
<arg value="push"/>
|
||||
<arg value="--tags"/>
|
||||
<arg value="origin"/>
|
||||
</exec>
|
||||
</target>
|
||||
</project>
|
41
wp-content/plugins/authLdap-2.3.1/composer.json
Normal file
41
wp-content/plugins/authLdap-2.3.1/composer.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"name" : "org_heigl/authLdap",
|
||||
"type" : "library",
|
||||
"description": "Enables wordpress-authentication via LDAP",
|
||||
"keywords": ["ldap","authenticate", "auth", "wordpress"],
|
||||
"homepage": "http://github.com/heiglandreas/authLdap",
|
||||
"license": "MIT",
|
||||
"authors": [{
|
||||
"name": "Andreas Heigl",
|
||||
"email": "andreas@heigl.org",
|
||||
"homepage": "http://andreas.heigl.org",
|
||||
"role": "Developer"
|
||||
}],
|
||||
"require" : {
|
||||
"php": ">=5.4",
|
||||
"phing/phing": "^2.16"
|
||||
},
|
||||
"require-dev": {
|
||||
"php-mock/php-mock": "^1.0",
|
||||
"phpunit/phpunit": "~4.5",
|
||||
"mockery/mockery": "0.9.*",
|
||||
"codeclimate/php-test-reporter": "0.1.*",
|
||||
"squizlabs/php_codesniffer": "~2.3",
|
||||
"pear/versioncontrol_svn": "^0.5.2",
|
||||
"pear/pear": "dev-master"
|
||||
},
|
||||
"autoload" : {
|
||||
"classmap" : [
|
||||
"ldap.php",
|
||||
"authLdap.php"
|
||||
],
|
||||
"psr-4" : {
|
||||
"Org_Heigl\\AuthLdap\\" : "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev" : {
|
||||
"psr-4" : {
|
||||
"Org_Heigl\\AuthLdapTest\\" : "tests/"
|
||||
}
|
||||
}
|
||||
}
|
67
wp-content/plugins/authLdap-2.3.1/docker-compose.yml
Normal file
67
wp-content/plugins/authLdap-2.3.1/docker-compose.yml
Normal file
@ -0,0 +1,67 @@
|
||||
version: "3.5"
|
||||
|
||||
services:
|
||||
wp:
|
||||
# image: authldap:latest
|
||||
build:
|
||||
context: dockersetup
|
||||
dockerfile: Dockerfile_wordpress
|
||||
ports:
|
||||
- 80:80 # change ip if required
|
||||
volumes:
|
||||
- ./config/php.conf.ini:/usr/local/etc/php/conf.d/conf.ini
|
||||
- ./wp-app:/var/www/html # Full wordpress project
|
||||
- .:/var/www/html/wp-content/plugins/authldap # Plugin development
|
||||
#- ./theme-name/trunk/:/var/www/html/wp-content/themes/theme-name # Theme development
|
||||
environment:
|
||||
WORDPRESS_DB_HOST: db
|
||||
WORDPRESS_DB_NAME: "wordpress"
|
||||
WORDPRESS_DB_USER: root
|
||||
WORDPRESS_DB_PASSWORD: "wppasswd"
|
||||
depends_on:
|
||||
- db
|
||||
links:
|
||||
- db
|
||||
|
||||
wpcli:
|
||||
image: wordpress:cli
|
||||
volumes:
|
||||
- ./config/php.conf.ini:/usr/local/etc/php/conf.d/conf.ini
|
||||
- ./wp-app:/var/www/html
|
||||
depends_on:
|
||||
- db
|
||||
- wp
|
||||
|
||||
db:
|
||||
image: mysql:latest # https://hub.docker.com/_/mysql/ - or mariadb https://hub.docker.com/_/mariadb
|
||||
ports:
|
||||
- 3306:3306 # change ip if required
|
||||
command: [
|
||||
'--default_authentication_plugin=mysql_native_password',
|
||||
'--character-set-server=utf8mb4',
|
||||
'--collation-server=utf8mb4_unicode_ci'
|
||||
]
|
||||
volumes:
|
||||
- ./wp-data:/docker-entrypoint-initdb.d
|
||||
- db_data:/var/lib/mysql
|
||||
environment:
|
||||
MYSQL_DATABASE: "wordpress"
|
||||
MYSQL_ROOT_PASSWORD: "wppasswd"
|
||||
|
||||
openldap:
|
||||
image: osixia/openldap:latest
|
||||
# build:
|
||||
# context: dockersetup
|
||||
# dockerfile: Dockerfile_ldap
|
||||
ports:
|
||||
- 389:389
|
||||
volumes:
|
||||
- ./.ci/50-init.ldif:/container/service/slapd/assets/config/bootstrap/ldif/custom/50-bootstrap.ldif
|
||||
command: "--copy-service --loglevel debug"
|
||||
restart: always
|
||||
environment:
|
||||
LDAP_LOG_LEVEL: "0"
|
||||
LDAP_TLS: "false"
|
||||
|
||||
volumes:
|
||||
db_data:
|
@ -0,0 +1,9 @@
|
||||
FROM wordpress:latest
|
||||
|
||||
RUN set -x \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y libldap2-dev \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& docker-php-ext-configure ldap --with-libdir=lib/x86_64-linux-gnu/ \
|
||||
&& docker-php-ext-install ldap \
|
||||
&& apt-get purge -y --auto-remove libldap2-dev
|
280
wp-content/plugins/authLdap-2.3.1/ldap.php
Normal file
280
wp-content/plugins/authLdap-2.3.1/ldap.php
Normal file
@ -0,0 +1,280 @@
|
||||
<?php
|
||||
/**
|
||||
* $Id: ldap.php 381646 2011-05-06 09:37:31Z heiglandreas $
|
||||
*
|
||||
* authLdap - Authenticate Wordpress against an LDAP-Backend.
|
||||
* Copyright (c) 2008 Andreas Heigl<andreas@heigl.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* This file handles the basic LDAP-Tasks
|
||||
*
|
||||
* @author Andreas Heigl<andreas@heigl.org>
|
||||
* @package authLdap
|
||||
* @category authLdap
|
||||
* @since 2008
|
||||
*/
|
||||
namespace Org_Heigl\AuthLdap;
|
||||
|
||||
use Exception;
|
||||
|
||||
class LDAP
|
||||
{
|
||||
private $_server = '';
|
||||
|
||||
private $_scheme = 'ldap';
|
||||
|
||||
private $_port = 389;
|
||||
|
||||
private $_baseDn = '';
|
||||
|
||||
private $_debug = false;
|
||||
/**
|
||||
* This property contains the connection handle to the ldap-server
|
||||
*
|
||||
* @var Ressource
|
||||
*/
|
||||
private $_ch = null;
|
||||
|
||||
private $_username = '';
|
||||
|
||||
private $_password = '';
|
||||
|
||||
private $_starttls = false;
|
||||
|
||||
public function __construct($URI, $debug = false, $starttls = false)
|
||||
{
|
||||
$this->_debug=$debug;
|
||||
$array = parse_url($URI);
|
||||
if (! is_array($array)) {
|
||||
throw new Exception($URI . ' seems not to be a valid URI');
|
||||
}
|
||||
$url = array_map(function ($item) {
|
||||
return urldecode($item);
|
||||
}, $array);
|
||||
|
||||
if (false === $url) {
|
||||
throw new Exception($URI . ' is an invalid URL');
|
||||
}
|
||||
if (! isset ( $url['scheme'] )) {
|
||||
throw new Exception($URI . ' does not provide a scheme');
|
||||
}
|
||||
if (0 !== strpos($url['scheme'], 'ldap')) {
|
||||
throw new Exception($URI . ' is an invalid LDAP-URI');
|
||||
}
|
||||
if (! isset ( $url['host'] )) {
|
||||
throw new Exception($URI . ' does not provide a server');
|
||||
}
|
||||
if (! isset ( $url['path'] )) {
|
||||
throw new Exception($URI . ' does not provide a search-base');
|
||||
}
|
||||
if (1 == strlen($url['path'])) {
|
||||
throw new Exception($URI . ' does not provide a valid search-base');
|
||||
}
|
||||
$this -> _server = $url['host'];
|
||||
$this -> _scheme = $url['scheme'];
|
||||
$this -> _baseDn = substr($url['path'], 1);
|
||||
if (isset ( $url['user'] )) {
|
||||
$this -> _username = $url['user'];
|
||||
}
|
||||
if ('' == trim($this -> _username)) {
|
||||
$this -> _username = 'anonymous';
|
||||
}
|
||||
if (isset ( $url['pass'] )) {
|
||||
$this -> _password = $url['pass'];
|
||||
}
|
||||
if (isset ( $url['port'] )) {
|
||||
$this -> _port = $url['port'];
|
||||
}
|
||||
$this->_starttls = $starttls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to the given LDAP-Server
|
||||
*
|
||||
* @return LDAP
|
||||
* @throws AuthLdap_Exception
|
||||
*/
|
||||
public function connect()
|
||||
{
|
||||
$this -> disconnect();
|
||||
if ('ldaps' == $this->_scheme && 389 == $this->_port) {
|
||||
$this->_port = 636;
|
||||
}
|
||||
|
||||
$this->_ch = @ldap_connect($this->_scheme . '://' . $this->_server . ':' . $this -> _port);
|
||||
if (! $this->_ch) {
|
||||
throw new AuthLDAP_Exception('Could not connect to the server');
|
||||
}
|
||||
ldap_set_option($this->_ch, LDAP_OPT_PROTOCOL_VERSION, 3);
|
||||
ldap_set_option($this->_ch, LDAP_OPT_REFERRALS, 0);
|
||||
//if configured try to upgrade encryption to tls for ldap connections
|
||||
if ($this->_starttls) {
|
||||
ldap_start_tls($this->_ch);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect from a resource if one is available
|
||||
*
|
||||
* @return LDAP
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
if (is_resource($this->_ch)) {
|
||||
@ldap_unbind($this->_ch);
|
||||
}
|
||||
$this->_ch = null;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind to an LDAP-Server with the given credentials
|
||||
*
|
||||
* @return LDAP
|
||||
* @throw AuthLdap_Exception
|
||||
*/
|
||||
public function bind()
|
||||
{
|
||||
if (! $this->_ch) {
|
||||
$this->connect();
|
||||
}
|
||||
if (! is_resource($this->_ch)) {
|
||||
throw new AuthLDAP_Exception('No Resource-handle given');
|
||||
}
|
||||
$bind = false;
|
||||
if (( ( $this->_username )
|
||||
&& ( $this->_username != 'anonymous') )
|
||||
&& ( $this->_password != '' ) ) {
|
||||
$bind = @ldap_bind($this->_ch, $this->_username, $this->_password);
|
||||
} else {
|
||||
$bind = @ldap_bind($this->_ch);
|
||||
}
|
||||
if (! $bind) {
|
||||
throw new AuthLDAP_Exception('bind was not successfull: ' . ldap_error($this->_ch));
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getErrorNumber()
|
||||
{
|
||||
return @ldap_errno($this->_ch);
|
||||
}
|
||||
|
||||
public function getErrorText()
|
||||
{
|
||||
return @ldap_error($this->_ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method does the actual ldap-serch.
|
||||
*
|
||||
* This is using the filter <var>$filter</var> for retrieving the attributes
|
||||
* <var>$attributes</var>
|
||||
*
|
||||
*
|
||||
* @param string $filter
|
||||
* @param array $attributes
|
||||
* @param string $base
|
||||
* @return array
|
||||
*/
|
||||
public function search($filter, $attributes = array('uid'), $base = '' )
|
||||
{
|
||||
if (! is_Resource($this->_ch)) {
|
||||
throw new AuthLDAP_Exception('No resource handle avbailable');
|
||||
}
|
||||
if (! $base) {
|
||||
$base = $this->_baseDn;
|
||||
}
|
||||
$result = ldap_search($this->_ch, $base, $filter, $attributes);
|
||||
if ($result === false) {
|
||||
throw new AuthLDAP_Exception('no result found');
|
||||
}
|
||||
$this->_info = @ldap_get_entries($this->_ch, $result);
|
||||
if ($this->_info === false) {
|
||||
throw new AuthLDAP_Exception('invalid results found');
|
||||
}
|
||||
return $this -> _info;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method sets debugging to ON
|
||||
*/
|
||||
public function debugOn()
|
||||
{
|
||||
$this->_debug = true;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method sets debugging to OFF
|
||||
*/
|
||||
public function debugOff()
|
||||
{
|
||||
$this->_debug = false;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method authenticates the user <var>$username</var> using the
|
||||
* password <var>$password</var>
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param string $filter OPTIONAL This parameter defines the Filter to be used
|
||||
* when searchin for the username. This MUST contain the string '%s' which
|
||||
* will be replaced by the vaue given in <var>$username</var>
|
||||
* @return boolean true or false depending on successfull authentication or not
|
||||
*/
|
||||
public function authenticate($username, $password, $filter = '(uid=%s)')
|
||||
{
|
||||
//return true;
|
||||
$this->connect();
|
||||
$this->bind();
|
||||
$res = $this->search(sprintf($filter, $username));
|
||||
if (! $res || ! is_array($res) || ( $res ['count'] != 1 )) {
|
||||
return false;
|
||||
}
|
||||
$dn = $res[0]['dn'];
|
||||
if ($username && $password) {
|
||||
if (@ldap_bind($this->_ch, $dn, $password)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* $this method loggs errors if debugging is set to ON
|
||||
*/
|
||||
public function logError()
|
||||
{
|
||||
if ($this->_debug) {
|
||||
$_v = debug_backtrace();
|
||||
throw new AuthLDAP_Exception('[LDAP_ERROR]' . ldap_errno($this->_ch) . ':' . ldap_error($this->_ch), $_v[0]['line']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AuthLDAP_Exception extends Exception
|
||||
{
|
||||
public function __construct($message, $line = null)
|
||||
{
|
||||
parent :: __construct($message);
|
||||
if ($line) {
|
||||
$this -> line = $line;
|
||||
}
|
||||
}
|
||||
}
|
28
wp-content/plugins/authLdap-2.3.1/phpunit.travis.xml
Normal file
28
wp-content/plugins/authLdap-2.3.1/phpunit.travis.xml
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit bootstrap="vendor/autoload.php">
|
||||
<testsuite name="authLdap Test-Suite">
|
||||
<directory>tests</directory>
|
||||
</testsuite>
|
||||
|
||||
<groups>
|
||||
<exclude>
|
||||
<group>disable</group>
|
||||
</exclude>
|
||||
</groups>
|
||||
<listeners>
|
||||
<listener class="\Mockery\Adapter\Phpunit\TestListener"></listener>
|
||||
</listeners>
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory suffix=".php">src</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
|
||||
<logging>
|
||||
<!--
|
||||
Adapt these paths to your special needs
|
||||
-->
|
||||
<log type="coverage-text" target="php://stdout" showUncoveredFiles="false"/>
|
||||
<log type="coverage-clover" target="build/logs/clover.xml" />
|
||||
</logging>
|
||||
</phpunit>
|
42
wp-content/plugins/authLdap-2.3.1/phpunit.xml.dist
Normal file
42
wp-content/plugins/authLdap-2.3.1/phpunit.xml.dist
Normal file
@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!--
|
||||
Document : phpunit.xml
|
||||
Created on : 21.09.2010
|
||||
Author : heiglandreas
|
||||
-->
|
||||
|
||||
<phpunit bootstrap="vendor/autoload.php">
|
||||
<testsuite name="authLdap Test-Suite">
|
||||
<directory>tests</directory>
|
||||
</testsuite>
|
||||
|
||||
<groups>
|
||||
<exclude>
|
||||
<group>disable</group>
|
||||
</exclude>
|
||||
</groups>
|
||||
<listeners>
|
||||
<!--listener class="\Mockery\Adapter\Phpunit\TestListener"></listener-->
|
||||
</listeners>
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory suffix=".php">src</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
<logging>
|
||||
<log type="coverage-html" target="build/coverage" charset="UTF-8"
|
||||
yui="true" highlight="false"
|
||||
lowUpperBound="35" highLowerBound="70" />
|
||||
<!--log type="coverage-xml" target="../report/coverage.xml"/-->
|
||||
<!--log type="graphviz" target="../report/logfile.dot"/-->
|
||||
<!--log type="json" target="../report/logfile.json"/-->
|
||||
<!--log type="metrics-xml" target="../report/metrics.xml"/-->
|
||||
<!--log type="plain" target="../report/logfile.txt"/-->
|
||||
<!--log type="pmd-xml" target="../report/pmd.xml" cpdMinLines="5" cpdMinMatches="70"/-->
|
||||
<!--log type="tap" target="../report/logfile.tap"/-->
|
||||
<!--log type="test-xml" target="../report/logfile.xml" logIncompleteSkipped="false"/-->
|
||||
<!--log type="testdox-html" target="../report/testdox.html"/-->
|
||||
<!--log type="testdox-text" target="../report/testdox.txt"/-->
|
||||
</logging>
|
||||
</phpunit>
|
111
wp-content/plugins/authLdap-2.3.1/readme.txt
Normal file
111
wp-content/plugins/authLdap-2.3.1/readme.txt
Normal file
@ -0,0 +1,111 @@
|
||||
=== authLdap ===
|
||||
Contributors: heiglandreas
|
||||
Tags: ldap, auth, authentication, active directory, AD, openLDAP, Open Directory
|
||||
Requires at least: 2.5.0
|
||||
Tested up to: 5.2.0
|
||||
Requires PHP: 5.6
|
||||
Stable tag: trunk
|
||||
License: MIT
|
||||
License URI: https://opensource.org/licenses/MIT
|
||||
|
||||
Use your existing LDAP flexible as authentication backend for WordPress
|
||||
|
||||
== Description ==
|
||||
|
||||
Use your existing LDAP as authentication-backend for your wordpress!
|
||||
|
||||
So what are the differences to other Wordpress-LDAP-Authentication-Plugins?
|
||||
|
||||
* Flexible: You are totaly free in which LDAP-backend to use. Due to the extensive configuration you can freely decide how to do the authentication of your users. It simply depends on your filters
|
||||
* Independent: As soon as a user logs in, it is added/updated to the Wordpress' user-database to allow wordpress to always use the correct data. You only have to administer your users once.
|
||||
* Failsafe: Due to the users being created in Wordpress' User-database they can also log in when the LDAP-backend currently is gone.
|
||||
* Role-Aware: You can map Wordpress' roles to values of an existing LDAP-attribute.
|
||||
|
||||
For more Information on the configuration have a look at https://github.com/heiglandreas/authLdap
|
||||
|
||||
== Installation ==
|
||||
|
||||
1. Upload the extracted folder `authLdap` to the `/wp-content/plugins/` directory
|
||||
2. Activate the plugin through the 'Plugins' menu in WordPress
|
||||
3. Configure the Plugin via the 'authLdap'-Configuration-Page.
|
||||
|
||||
== Frequently Asked Questions ==
|
||||
|
||||
= Where can I find more Informations about the plugin? =
|
||||
|
||||
Go to https://github.com/heiglandreas/authLdap
|
||||
|
||||
= Where can I report issues with the plugin? =
|
||||
|
||||
Please use the issuetracker at https://github.com/heiglandreas/authLdap/issues
|
||||
|
||||
== Changelog ==
|
||||
= 2.3.0 =
|
||||
* Allow to not overwrite existing WordPress-Users with LDAP-Users as that can be a security issue.
|
||||
|
||||
= 2.1.0 =
|
||||
* Add search-base for groups. This might come in handy for multisite-instances
|
||||
|
||||
= 2.0.0 =
|
||||
* This new release adds Multi-Site support. It will no longer be possible to use this plugin just in one subsite of a multisite installation!
|
||||
* Adds a warning screen to the config-section when no LDAPextension could be found
|
||||
* Fixes an issue with the max-length of the username
|
||||
|
||||
= 1.5.1 =
|
||||
* Fixes an issue with escaped backslashes and quotes
|
||||
|
||||
= 1.5.0 =
|
||||
* Allows parts of the LDAP-URI to be URLEncoded
|
||||
* Drops support for PHP 5.4
|
||||
|
||||
= 1.4.20 =
|
||||
* Allows multiple LDAP-servers to be queried (given that they use the same attributes)
|
||||
* Fixes issue with URL-Encoded informations (see https://github.com/heiglandreas/authLdap/issues/108)
|
||||
|
||||
= 1.4.19 =
|
||||
* Adds support for TLS
|
||||
|
||||
= 1.4.14 =
|
||||
* Update to showing password-fields check (thanks to @chaplina)
|
||||
|
||||
= 1.4.13 =
|
||||
* Removed generation of default email-address (thanks to @henryk)
|
||||
* Fixes password-hashing when caching passwords (thanks to @litinoveweedle)
|
||||
* Removes the possibility to reset a password for LDAP-based users (thanks to @chaplina)
|
||||
* Removes the password-change-Email from 4.3 on (thanks to @litinoveweedle)
|
||||
* Fixes double authentication-attempt (that resulted in failed authentication) (thanks to @litinoveweedle)
|
||||
|
||||
= 1.4.10 =
|
||||
* Cleanup by removing deprecated code
|
||||
* Fixes issues with undefined variables
|
||||
* Enables internal option-versioning
|
||||
* Setting users nickname initially to the realname instead of the uid
|
||||
* Fixes display of password-change possibility in users profile-page
|
||||
= 1.4.9 =
|
||||
* Fixed an issue with changing display name on every login
|
||||
* Use proper way of looking up user-roles in setups w/o DB-prefix
|
||||
= 1.4.8 =
|
||||
* Updated version string
|
||||
= 1.4.7 =
|
||||
* Use default user to retrieve group menberships and not logging in user.
|
||||
* return the UID from the LDAP instead of the value given by the user
|
||||
* remove unnecessary checkbox
|
||||
* Adds a testsuite
|
||||
* Fixes PSR2 violations
|
||||
|
||||
[…]
|
||||
|
||||
= 1.2.1 =
|
||||
* Fixed an issue with group-ids
|
||||
* Moved the code to GitHub (https://github.com/heiglandreas/authLdap)
|
||||
= 1.1.0 =
|
||||
* Changed the login-process. Now users that are not allowed to login due to
|
||||
missing group-memberships are not created within your blog as was the standard
|
||||
until Version 1.0.3 - Thanks to alex@tayts.com
|
||||
* Changed the default mail-address that is created when no mail-address can be
|
||||
retrieved from the LDAP from me@example.com to $username@example.com so that
|
||||
a new user can be created even though the mail address already exists in your
|
||||
blog - Also thanks to alex@tayts.com
|
||||
* Added support for WordPress-Table-prefixes as the capabilities of a user
|
||||
are interlany stored in a field that is named "$tablePrefix_capabilities" -
|
||||
again thanks to alex@tayts.com and also to sim0n of silicium.mine.nu
|
87
wp-content/plugins/authLdap-2.3.1/src/LdapList.php
Normal file
87
wp-content/plugins/authLdap-2.3.1/src/LdapList.php
Normal file
@ -0,0 +1,87 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Andreas Heigl<andreas@heigl.org>
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author Andreas Heigl<andreas@heigl.org>
|
||||
* @copyright Andreas Heigl
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT-License
|
||||
* @since 07.07.2016
|
||||
* @link http://github.com/heiglandreas/authLDAP
|
||||
*/
|
||||
|
||||
namespace Org_Heigl\AuthLdap;
|
||||
|
||||
class LdapList
|
||||
{
|
||||
/**
|
||||
* @var \LDAP[]
|
||||
*/
|
||||
protected $items = [];
|
||||
|
||||
public function addLdap(LDAP $ldap)
|
||||
{
|
||||
$this->items[] = $ldap;
|
||||
}
|
||||
|
||||
public function authenticate($username, $password, $filter = '(uid=%s)')
|
||||
{
|
||||
foreach ($this->items as $key => $item) {
|
||||
if (! $item->authenticate($username, $password, $filter)) {
|
||||
unset ($this->items[$key]);
|
||||
continue;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function bind()
|
||||
{
|
||||
$allFailed = true;
|
||||
foreach ($this->items as $key => $item) {
|
||||
try {
|
||||
$item->bind();
|
||||
} catch (\Exception $e) {
|
||||
unset($this->items[$key]);
|
||||
continue;
|
||||
}
|
||||
$allFailed = false;
|
||||
}
|
||||
|
||||
if ($allFailed) {
|
||||
throw new AuthLDAP_Exception('No bind successfull');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function search($filter, $attributes = array('uid'), $base = '')
|
||||
{
|
||||
foreach ($this->items as $item) {
|
||||
try {
|
||||
$result = $item->search($filter, $attributes, $base);
|
||||
return $result;
|
||||
} catch (Exception $e) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
throw new \AuthLDAP_Exception('No Results found');
|
||||
}
|
||||
}
|
134
wp-content/plugins/authLdap-2.3.1/tests/LDAPBaseTest.php
Normal file
134
wp-content/plugins/authLdap-2.3.1/tests/LDAPBaseTest.php
Normal file
@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (c) 2016-2016} Andreas Heigl<andreas@heigl.org>
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author Andreas Heigl<andreas@heigl.org>
|
||||
* @copyright 2016-2016 Andreas Heigl
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT-License
|
||||
* @version 0.0
|
||||
* @since 07.06.2016
|
||||
* @link http://github.com/heiglandreas/authLDAP
|
||||
*/
|
||||
namespace Org_Heigl\AuthLdapTest;
|
||||
|
||||
use Org_Heigl\AuthLdap\LDAP;
|
||||
use Org_Heigl\AuthLdap\LdapList;
|
||||
use phpmock\spy\Spy;
|
||||
use PHPUnit_Framework_TestCase;
|
||||
|
||||
class LDAPBaseTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
$this->ldap_connect_spy = new Spy('Org_Heigl\AuthLdap', 'ldap_connect');
|
||||
$this->ldap_connect_spy->enable();
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
$this->ldap_connect_spy->disable();
|
||||
}
|
||||
/** @dataProvider bindingWithPasswordProvider */
|
||||
public function testThatBindingWithPasswordWorks($user, $password, $filter, $uri)
|
||||
{
|
||||
$ldap = new LDAP($uri);
|
||||
$this->assertTrue($ldap->authenticate($user, $password, $filter));
|
||||
}
|
||||
|
||||
public function bindingWithPasswordProvider()
|
||||
{
|
||||
return [
|
||||
['user3', 'user!"', 'uid=%s', 'ldap://cn=Manager,dc=example,dc=com:insecure@127.0.0.1:3890/dc=example,dc=com'],
|
||||
['Manager', 'insecure', 'cn=%s', 'ldap://cn=Manager,dc=example,dc=com:insecure@127.0.0.1:3890/dc=example,dc=com'],
|
||||
['user1', 'user1', 'uid=%s', 'ldap://cn=Manager,dc=example,dc=com:insecure@127.0.0.1:3890/dc=example,dc=com'],
|
||||
['user 4', 'user!"', 'uid=%s', 'ldap://cn=Manager,dc=example,dc=com:insecure@127.0.0.1:3890/dc=example,dc=com'],
|
||||
['user 5', 'user!"', 'uid=%s', 'ldap://cn=Manager,dc=example,dc=com:insecure@127.0.0.1:3890/dc=test%20space,dc=example,dc=com'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $uri
|
||||
* @dataProvider initialBindingToLdapServerWorksProvider
|
||||
*/
|
||||
public function testThatInitialBindingWorks($uri)
|
||||
{
|
||||
$ldap = new LDAP($uri);
|
||||
$this->assertInstanceof(LDAP::class, $ldap->bind());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $uri
|
||||
* @dataProvider initialBindingToLdapServerWorksProvider
|
||||
*/
|
||||
public function testThatInitialBindingToMultipleLdapsWorks($uri)
|
||||
{
|
||||
$list = new LdapList();
|
||||
$list->addLDAP(new LDAP($uri));
|
||||
$this->assertTrue($list->bind());
|
||||
}
|
||||
|
||||
public function initialBindingToLdapServerWorksProvider()
|
||||
{
|
||||
return [
|
||||
['ldap://uid=user%205,dc=test%20space,dc=example,dc=com:user!"@localhost:3890/dc=test%20space,dc=example,dc=com'],
|
||||
];
|
||||
}
|
||||
|
||||
/** @dataProvider bindingWithPasswordProvider */
|
||||
public function testThatBindingWithAddedSlashesFailsWorks($user, $password, $filter)
|
||||
{
|
||||
$newpassword = addslashes($password);
|
||||
$ldap = new LDAP('ldap://cn=Manager,dc=example,dc=com:insecure@127.0.0.1:3890/dc=example,dc=com');
|
||||
if ($newpassword === $password) {
|
||||
$this->assertTrue($ldap->authenticate($user, $password, $filter));
|
||||
} else {
|
||||
$this->assertFalse($ldap->authenticate($user, $newpassword, $filter));
|
||||
}
|
||||
}
|
||||
|
||||
/** @dataProvider serchingForGroupsProvider */
|
||||
public function testThatSearchingForGoupsWorks($filter, $user, $groups)
|
||||
{
|
||||
// (&(objectCategory=group)(member=<USER_DN>))
|
||||
$ldap = new LDAP('ldap://cn=Manager,dc=example,dc=com:insecure@127.0.0.1:3890/dc=example,dc=com');
|
||||
$ldap->bind();
|
||||
$this->assertContains($groups, $ldap->search(sprintf($filter, $user), ['cn'])[0]);
|
||||
|
||||
}
|
||||
|
||||
public function serchingForGroupsProvider()
|
||||
{
|
||||
return [
|
||||
[
|
||||
'(&(objectclass=groupOfUniqueNames)(uniqueMember=%s))',
|
||||
'uid=user 4,dc=example,dc=com',
|
||||
['count' => 1, 0 => 'group4'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function testThatSettingLDAPSActuallyGivesTheCorrectPort()
|
||||
{
|
||||
|
||||
$ldap = new LDAP('ldaps://cn=Manager,dc=example,dc=com:insecure@127.0.0.1/dc=example,dc=com');
|
||||
$ldap->connect();
|
||||
|
||||
$this->assertEquals('ldaps://127.0.0.1:636', $this->ldap_connect_spy->getInvocations()[0]->getArguments()[0]);
|
||||
}
|
||||
}
|
66
wp-content/plugins/authLdap-2.3.1/tests/LDAPListBaseTest.php
Normal file
66
wp-content/plugins/authLdap-2.3.1/tests/LDAPListBaseTest.php
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (c) 2016-2016} Andreas Heigl<andreas@heigl.org>
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author Andreas Heigl<andreas@heigl.org>
|
||||
* @copyright 2016-2016 Andreas Heigl
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT-License
|
||||
* @version 0.0
|
||||
* @since 07.06.2016
|
||||
* @link http://github.com/heiglandreas/authLDAP
|
||||
*/
|
||||
namespace Org_Heigl\AuthLdapTest;
|
||||
|
||||
use Org_Heigl\AuthLdap\LDAP;
|
||||
use PHPUnit_Framework_TestCase;
|
||||
|
||||
class LDAPListBaseTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
/** @dataProvider bindingWithPasswordProvider */
|
||||
public function testThatBindingWithPasswordWorks($user, $password, $filter)
|
||||
{
|
||||
require_once __DIR__ . '/../src/LdapList.php';
|
||||
$ldaplist = new \Org_Heigl\AuthLdap\LdapList();
|
||||
$ldaplist->addLdap(new LDAP('ldap://cn=Manager,dc=example,dc=com:insecure@127.0.0.1:3890/dc=example,dc=com'));
|
||||
$this->assertTrue($ldaplist->authenticate($user, $password, $filter));
|
||||
}
|
||||
|
||||
public function bindingWithPasswordProvider()
|
||||
{
|
||||
return [
|
||||
['user3', 'user!"', 'uid=%s'],
|
||||
['Manager', 'insecure', 'cn=%s'],
|
||||
['user1', 'user1', 'uid=%s'],
|
||||
];
|
||||
}
|
||||
|
||||
/** @dataProvider bindingWithPasswordProvider */
|
||||
public function testThatBindingWithAddedSlashesFailsWorks($user, $password, $filter)
|
||||
{
|
||||
$newpassword = addslashes($password);
|
||||
require_once __DIR__ . '/../src/LdapList.php';
|
||||
$ldaplist = new \Org_Heigl\AuthLdap\LdapList();
|
||||
$ldaplist->addLdap(new LDAP('ldap://cn=Manager,dc=example,dc=com:insecure@127.0.0.1:3890/dc=example,dc=com'));
|
||||
if ($newpassword === $password) {
|
||||
$this->assertTrue($ldaplist->authenticate($user, $password, $filter));
|
||||
} else {
|
||||
$this->assertFalse($ldaplist->authenticate($user, $newpassword, $filter));
|
||||
}
|
||||
}
|
||||
}
|
183
wp-content/plugins/authLdap-2.3.1/tests/LdapTest.php
Normal file
183
wp-content/plugins/authLdap-2.3.1/tests/LdapTest.php
Normal file
@ -0,0 +1,183 @@
|
||||
<?php
|
||||
/**
|
||||
* $Id: LdapTest.php 292156 2010-09-21 19:32:01Z heiglandreas $
|
||||
*
|
||||
* authLdap - Authenticate Wordpress against an LDAP-Backend.
|
||||
* Copyright (c) 2008 Andreas Heigl<andreas@heigl.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* This file tests the basic LDAP-Tasks
|
||||
*
|
||||
* @category authLdap
|
||||
* @package authLdap
|
||||
* @subpackage UnitTests
|
||||
* @author Andreas Heigl<andreas@heigl.org>
|
||||
* @copyright 2010 Andreas Heigl<andreas@heigl.org>
|
||||
* @license GPL
|
||||
* @since 21.09.2010
|
||||
*/
|
||||
|
||||
namespace Org_Heigl\AuthLdapTest;
|
||||
|
||||
use PHPUnit_Framework_TestCase;
|
||||
use Org_Heigl\AuthLdap\LDAP;
|
||||
|
||||
class LdapTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @dataProvider dpInstantiateLdapClass
|
||||
* @param array $expected
|
||||
* @param array $given
|
||||
*/
|
||||
public function testInstantiateLdapClass($expected, $given)
|
||||
{
|
||||
$ldap = new LDAP($expected[0], $expected[1]);
|
||||
foreach ($given as $key => $value) {
|
||||
$this -> assertAttributeEquals($value, '_' . $key, $ldap);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dpExceptionsWhenInstantiatingLdapClass
|
||||
* @expectedException Exception
|
||||
* @param array $expected
|
||||
*/
|
||||
public function testExceptionsWhenInstantiatingLdapClass($expected)
|
||||
{
|
||||
new LDAP($expected);
|
||||
}
|
||||
|
||||
public function dpInstantiateLdapClass()
|
||||
{
|
||||
return array (
|
||||
array (
|
||||
array ('ldap://uid=jondoe,cn=users,cn=example,c=org:secret@ldap.example.org/cn=example,c=org', true),
|
||||
array (
|
||||
'username' => 'uid=jondoe,cn=users,cn=example,c=org',
|
||||
'password' => 'secret',
|
||||
'server' => 'ldap.example.org',
|
||||
'baseDn' => 'cn=example,c=org',
|
||||
'debug' => true
|
||||
)
|
||||
),
|
||||
array (
|
||||
array ('ldap://uid=jondoe,cn=users,cn=example,c=org@ldap.example.org/cn=example,c=org', true),
|
||||
array (
|
||||
'username' => 'uid=jondoe,cn=users,cn=example,c=org',
|
||||
'password' => '',
|
||||
'server' => 'ldap.example.org',
|
||||
'baseDn' => 'cn=example,c=org',
|
||||
'debug' => true
|
||||
)
|
||||
),
|
||||
array(
|
||||
array ('ldap://ldap.example.org/cn=example,c=org', true),
|
||||
array (
|
||||
'username' => 'anonymous',
|
||||
'password' => '',
|
||||
'server' => 'ldap.example.org',
|
||||
'baseDn' => 'cn=example,c=org',
|
||||
'debug' => true
|
||||
)
|
||||
),
|
||||
// array(
|
||||
// array ('ldap://ldap.example.org', true),
|
||||
// array (
|
||||
// 'username' => 'anonymous',
|
||||
// 'password' => '',
|
||||
// 'server' => 'ldap.example.org',
|
||||
// 'baseDn' => '',
|
||||
// 'debug' => true
|
||||
// )
|
||||
// ),
|
||||
array(
|
||||
array ('ldap://uid=jondoe,cn=users,cn=example,c=org:secret@ldap.example.org/cn=example,c=org', false),
|
||||
array (
|
||||
'username' => 'uid=jondoe,cn=users,cn=example,c=org',
|
||||
'password' => 'secret',
|
||||
'server' => 'ldap.example.org',
|
||||
'baseDn' => 'cn=example,c=org',
|
||||
'debug' => false
|
||||
)
|
||||
),
|
||||
array(
|
||||
array ('ldap://ldap.example.org/cn=test%20example,c=org', false),
|
||||
array (
|
||||
'username' => 'anonymous',
|
||||
'password' => '',
|
||||
'server' => 'ldap.example.org',
|
||||
'baseDn' => 'cn=test example,c=org',
|
||||
'debug' => false
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public function dpExceptionsWhenInstantiatingLdapClass()
|
||||
{
|
||||
return array (
|
||||
array('ldap://ldap.example.org'),
|
||||
array('ldap://foo:bar@/cn=example,c=org'),
|
||||
array('http://ldap.example.org'),
|
||||
array('fooBar'),
|
||||
array('ldap://ldap.example.org/'),
|
||||
array('()123üäö'),
|
||||
);
|
||||
}
|
||||
|
||||
public function testThatGroupMappingWorks()
|
||||
{
|
||||
$groups = [
|
||||
'count' => 1,
|
||||
0 => [
|
||||
'dn' => 'dn-1',
|
||||
'count' => 1,
|
||||
0 => 'group',
|
||||
'group' => [
|
||||
'count' => 2,
|
||||
0 => '7310T270:Překladatelství:čeština - angličtina@ff.cuni.cz',
|
||||
1 => '7310T033:Český jazyk a literatura@ff.cuni.cz',
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
$grp = array();
|
||||
for ($i = 0; $i < $groups ['count']; $i++) {
|
||||
for ($k = 0; $k < $groups[$i][strtolower('group')]['count']; $k++) {
|
||||
$grp[] = $groups[$i][strtolower('group')][$k];
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertEquals([
|
||||
'7310T270:Překladatelství:čeština - angličtina@ff.cuni.cz',
|
||||
'7310T033:Český jazyk a literatura@ff.cuni.cz',
|
||||
], $grp);
|
||||
|
||||
$role = '';
|
||||
foreach (['testrole' => '7310T031:Český jazyk a literatura@ff.cuni.cz,7310T033:Český jazyk a literatura@ff.cuni.cz'] as $key => $val) {
|
||||
$currentGroup = explode(',', $val);
|
||||
// Remove whitespaces around the group-ID
|
||||
$currentGroup = array_map('trim', $currentGroup);
|
||||
if (0 < count(array_intersect($currentGroup, $grp))) {
|
||||
$role = $key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertEquals('testrole', $role);
|
||||
}
|
||||
}
|
420
wp-content/plugins/authLdap-2.3.1/view/admin.phtml
Normal file
420
wp-content/plugins/authLdap-2.3.1/view/admin.phtml
Normal file
@ -0,0 +1,420 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c)2014-2014 heiglandreas
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIBILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @category
|
||||
* @author Andreas Heigl<andreas@heigl.org>
|
||||
* @copyright ©2014-2014 Andreas Heigl
|
||||
* @license http://www.opesource.org/licenses/mit-license.php MIT-License
|
||||
* @version 0.0
|
||||
* @since 19.12.14
|
||||
* @link https://github.com/heiglandreas/authLdap
|
||||
*/
|
||||
?><div class="wrap">
|
||||
<?php if (! extension_loaded('ldap')) : ?>
|
||||
<div class="error"><strong>Caveat:</strong> The LDAP-extension is not loaded!
|
||||
Without that extension it is not possible to query an LDAP-Server! Please have a look
|
||||
at <a href="http://php.net/manual/install.php">the PHP-Installation page</a>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
<h2>AuthLDAP Options</h2>
|
||||
<form method="post" id="authLDAP_options" action="<?php echo $action;?>">
|
||||
<h3 class="title">General Usage of authLDAP</h3>
|
||||
<fieldset class="options">
|
||||
<table class="form-table">
|
||||
<tr>
|
||||
<th>
|
||||
<label for="authLDAPAuth">Enable Authentication via LDAP?</label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="checkbox" name="authLDAPAuth" id="authLDAPAuth" value="1"<?php echo $tChecked; ?>/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<label for="authLDAPDebug">Debug AuthLDAP?</label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="checkbox" name="authLDAPDebug" id="authLDAPDebug" value="1"<?php echo $tDebugChecked; ?>/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<label for="authLDAPDoNotOverwriteNonLdapUsers">Do not authenticate existing WordPress-Users</label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="checkbox" name="authLDAPDoNotOverwriteNonLdapUsers" id="authLDAPDoNotOverwriteNonLdapUsers" value="1"<?php echo $tDoNotOverwriteNonLdapUsers; ?>/>
|
||||
<p class="description">
|
||||
Shall we prohibit authenticating already in WordPress created users using LDAP? If you enable this, LDAP-Users with the same user-ID
|
||||
as existing WordPress-Users can no longer take over the WordPress-Users account. This also means that LDAP-Users with the same User-ID as existing
|
||||
WordPress-Users will <strong>not</strong> be able to authenticate anymore! Accounts that have been taken over already will not be affected by this setting.
|
||||
</p>
|
||||
<p class="description">This should only be checked if you know what you are doing!</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<label for="authLDAPCachePW">Save entered passwords in the wordpress user table?</label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="checkbox" name="authLDAPCachePW" id="authLDAPCachePW" value="1"<?php echo $tPWChecked; ?>/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<label for="authLDAPGroupEnable">Map LDAP Groups to wordpress Roles?</label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="checkbox" name="authLDAPGroupEnable" id="authLDAPGroupEnable" value="1"<?php echo $tGroupChecked; ?>/>
|
||||
<p class="description">
|
||||
Search LDAP for user's groups and map to Wordpress Roles.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
<h3 class="title">General Server Settings</h3>
|
||||
<fieldset class="options">
|
||||
<table class="form-table">
|
||||
<tr>
|
||||
<th>
|
||||
<label for="authLDAPURI">LDAP URI</label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="authLDAPURI" id="authLDAPURI" placeholder="LDAP-URI"
|
||||
class="regular-text" value="<?php echo $authLDAPURI; ?>"/>
|
||||
<p class="description">
|
||||
The <abbr title="Uniform Ressource Identifier">URI</abbr>
|
||||
for connecting to the LDAP-Server. This usualy takes the form
|
||||
<var><scheme>://<user>:<password>@<server>/<path></var>
|
||||
according to RFC 1738.</p>
|
||||
<p class="description">
|
||||
In this case it schould be something like
|
||||
<var>ldap://uid=adminuser,dc=example,c=com:secret@ldap.example.com/dc=basePath,dc=example,c=com</var>.
|
||||
</p>
|
||||
<p class="description">
|
||||
If your LDAP accepts anonymous login, you can ommit the user and
|
||||
password-Part of the URI
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<label for="authLDAPURISeparator">LDAP URI-Separator</label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="authLDAPURISeparator" id="authLDAPURISeparator" placeholder="LDAP-URI Separator"
|
||||
class="regular-text" value="<?php echo $authLDAPURISeparator; ?>"/>
|
||||
<p class="description">
|
||||
A separator that separates multiple LDAP-URIs from one another.
|
||||
You can use that feature to try to authenticate against multiple LDAP-Servers
|
||||
as long as they all have the same attribute-settings. The first LDAP-Server the user can
|
||||
authenticate against will be used to handle the user.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<label for="authLDAPStartTLS" class="description">StartTLS</label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="checkbox" name="authLDAPStartTLS" id="authLDAPStartTLS" value="1"<?php echo $tStartTLSChecked; ?>/>
|
||||
<p class="description">
|
||||
Use StartTLS for encryption of ldap connections. This setting is not to be used in combination with ldaps connections (ldap:// only).
|
||||
</p>
|
||||
</td>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="authLDAPFilter" class="description">Filter</label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="authLDAPFilter" id="authLDAPFilter" placeholder="(uid=%s)"
|
||||
class="regular-text" value="<?php echo $authLDAPFilter; ?>"/>
|
||||
<p class="description">
|
||||
Please provide a valid filter that can be used for querying the
|
||||
<abbr title="Lightweight Directory Access Protocol">LDAP</abbr>
|
||||
for the correct user. For more information on this
|
||||
feature have a look at <a href="http://andreas.heigl.org/cat/dev/wp/authldap">http://andreas.heigl.org/cat/dev/wp/authldap</a>
|
||||
</p>
|
||||
<p class="description">
|
||||
This field <strong>should</strong> include the string <code>%s</code>
|
||||
that will be replaced with the username provided during log-in
|
||||
</p>
|
||||
<p class="description">
|
||||
If you leave this field empty it defaults to <strong>(uid=%s)</strong>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<h3 class="title">Settings for creating new Users</h3>
|
||||
<fieldset class="options">
|
||||
<table class="form-table">
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="authLDAPNameAttr">Name-Attribute</label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="authLDAPNameAttr" id="authLDAPNameAttr" placeholder="name"
|
||||
class="regular-text" value="<?php echo $authLDAPNameAttr; ?>"/><br />
|
||||
<p class="description">
|
||||
Which Attribute from the LDAP contains the Full or the First name
|
||||
of the user trying to log in.
|
||||
</p>
|
||||
<p class="description">
|
||||
This defaults to <strong>name</strong>
|
||||
</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="authLDAPSecName">Second Name Attribute</label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="authLDAPSecName" id="authLDAPSecName" placeholder=""
|
||||
class="regular-text" value="<?php echo $authLDAPSecName; ?>" />
|
||||
<p class="description">
|
||||
If the above Name-Attribute only contains the First Name of the
|
||||
user you can here specify an Attribute that contains the second name.
|
||||
</p>
|
||||
<p class="description">
|
||||
This field is empty by default
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="authLDAPUidAttr">User-ID Attribute</label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="authLDAPUidAttr" id="authLDAPUidAttr" placeholder="uid"
|
||||
class="regular-text" value="<?php echo $authLDAPUidAttr; ?>" />
|
||||
<p class="description">
|
||||
Please give the Attribute, that is used to identify the user. This
|
||||
should be the same as you used in the above <em>Filter</em>-Option
|
||||
</p>
|
||||
<p class="description">
|
||||
This field defaults to <strong>uid</strong>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="authLDAPMailAttr">Mail Attribute</label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="authLDAPMailAttr" id="authLDAPMailAttr" placeholder="mail"
|
||||
class="regular-text" value="<?php echo $authLDAPMailAttr; ?>" />
|
||||
<p class="description">
|
||||
Which Attribute holds the eMail-Address of the user?
|
||||
</p>
|
||||
<p class="description">
|
||||
If more than one eMail-Address are stored in the LDAP, only the first given is used
|
||||
</p>
|
||||
<p class="description">
|
||||
This field defaults to <strong>mail</strong>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="authLDAPWebAttr">Web-Attribute</label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="authLDAPWebAttr" id="authLDAPWebAttr" placeholder=""
|
||||
class="regular-text" value="<?php echo $authLDAPWebAttr; ?>" />
|
||||
<p class="description">
|
||||
If your users have a personal page (URI) stored in the LDAP, it can
|
||||
be provided here.
|
||||
</p>
|
||||
<p class="description">
|
||||
This field is empty by default
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="authLDAPDefaultRole">Default Role</label>
|
||||
</th>
|
||||
<td>
|
||||
<select name="authLDAPDefaultRole" id="authLDAPDefaultRole">
|
||||
<option value="" <?php echo ( $authLDAPDefaultRole == '' ? 'selected="selected"' : '' ); ?>>
|
||||
None (deny access)
|
||||
</option>
|
||||
<?php foreach ($roles->get_names() as $group => $vals) : ?>
|
||||
<option value="<?php echo $group; ?>" <?php echo ( $authLDAPDefaultRole == $group ? 'selected="selected"' : '' ); ?>>
|
||||
<?php echo $vals; ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<p class="description">
|
||||
Here you can select the default role for users.
|
||||
If you enable LDAP Groups below, they will take precedence over the Default Role.
|
||||
</p>
|
||||
<p class="description">
|
||||
Existing users will retain their roles unless overriden by LDAP Groups below.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
|
||||
<div id="authldaprolemapping">
|
||||
<h3 class="title">Groups for Roles</h3>
|
||||
<fieldset class="options">
|
||||
<table class="form-table">
|
||||
<tr>
|
||||
<th>
|
||||
<label for="authLDAPGroupOverUser">LDAP Groups override role of existing users?</label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="checkbox" name="authLDAPGroupOverUser" id="authLDAPGroupOverUser" value="1"<?php echo $tGroupOverUserChecked; ?>/>
|
||||
<p class="description">
|
||||
If role determined by LDAP Group differs from existing Wordpress User's role, use LDAP Group.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="authLDAPGroupBase">Group-Base</label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="authLDAPGroupBase" id="authLDAPGroupBase" placeholder=""
|
||||
class="regular-text" value="<?php echo $authLDAPGroupBase; ?>" />
|
||||
<p class="description">
|
||||
This is the base dn to lookup groups.
|
||||
</p>
|
||||
<p class="description">
|
||||
If empty the base dn of the LDAP URI will be used
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="authLDAPGroupAttr">Group-Attribute</label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="authLDAPGroupAttr" id="authLDAPGroupAttr" placeholder="gidNumber"
|
||||
class="regular-text" value="<?php echo $authLDAPGroupAttr; ?>" />
|
||||
<p class="description">
|
||||
This is the attribute that defines the Group-ID that can be matched
|
||||
against the Groups defined further down
|
||||
</p>
|
||||
<p class="description">
|
||||
This field defaults to <strong>gidNumber</strong>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="authLDAPGroupSeparator">Group-Separator</label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="authLDAPGroupSeparator" id="authLDAPGroupSeparator" placeholder=","
|
||||
class="regular-text" value="<?php echo $authLDAPGroupSeparator; ?>" />
|
||||
<p class="description">
|
||||
This attribute defines the separator used for the Group-IDs listed in the
|
||||
Groups defined further down. This is useful if the value of Group-Attribute
|
||||
listed above can contain a comma (for example, when using the memberof attribute)
|
||||
</p>
|
||||
<p class="description">
|
||||
This field defaults to <strong>, (comma)</strong>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="authLDAPGroupFilter">Group-Filter</label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="authLDAPGroupFilter" id="authLDAPGroupFilter"
|
||||
placeholder="(&(objectClass=posixGroup)(memberUid=%s))"
|
||||
class="regular-text" value="<?php echo $authLDAPGroupFilter; ?>" />
|
||||
<p class="description">
|
||||
Here you can add the filter for selecting groups for ther
|
||||
currentlly logged in user
|
||||
</p>
|
||||
<p class="description">
|
||||
The Filter should contain the string <code>%s</code> which will be replaced by
|
||||
the login-name of the currently logged in user
|
||||
</p>
|
||||
<p class="description">
|
||||
Alternatively the string <code>%dn%</code> will be replaced by the
|
||||
DN of the currently logged in user. This can be helpfull if
|
||||
group-memberships are defined with DNs rather than UIDs
|
||||
</p>
|
||||
<p class="description">This field defaults to
|
||||
<strong>(&(objectClass=posixGroup)(memberUid=%s))</strong>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<h3 class="title">Role - group mapping</h3>
|
||||
<fieldset class="options">
|
||||
<table class="form-table">
|
||||
<?php
|
||||
foreach ($roles->get_names() as $group => $vals) :
|
||||
$aGroup=$authLDAPGroups[$group]; ?>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="authLDAPGroups[<?php echo $group; ?>]">
|
||||
<?php echo $vals; ?>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="authLDAPGroups[<?php echo $group; ?>]" id="authLDAPGroups[<?php echo $group; ?>]"
|
||||
value="<?php echo $aGroup; ?>" />
|
||||
<p class="description">What LDAP-Groups shall be matched to the <?php echo $vals; ?>-Role?</p>
|
||||
<p class="description">Please provide a coma-separated list of values</p>
|
||||
<p class="description">This field is empty by default</p>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
</fieldset>
|
||||
</div>
|
||||
<fieldset class="buttons">
|
||||
<p class="submit">
|
||||
<input type="submit" name="ldapOptionsSave" class="button button-primary" value="Save Changes" />
|
||||
</p>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
elem = document.getElementById('authLDAPGroupEnable');
|
||||
if(! elem.checked) {
|
||||
document.getElementById('authldaprolemapping').setAttribute('style', 'display:none;');
|
||||
}
|
||||
|
||||
elem.addEventListener('change', function(e){
|
||||
if(! e.target.checked) {
|
||||
document.getElementById('authldaprolemapping').setAttribute('style', 'display:none;');
|
||||
} else {
|
||||
document.getElementById('authldaprolemapping').removeAttribute('style');
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/*
|
||||
Plugin Name: Disable WordPress Core Updates
|
||||
Description: Disables WordPress core update checks and notifications.
|
||||
Plugin URI: https://lud.icro.us/disable-wordpress-core-update/
|
||||
Version: 1.5
|
||||
Author: John Blackbourn
|
||||
Author URI: https://johnblackbourn.com/
|
||||
License: GPL v2 or later
|
||||
Network: true
|
||||
|
||||
Props: Matt Mullenweg, _ck_, miqrogroove
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
*/
|
||||
|
||||
# 2.3 to 2.7:
|
||||
add_action( 'init', create_function( '$a', "remove_action( 'init', 'wp_version_check' );" ), 2 );
|
||||
add_filter( 'pre_option_update_core', create_function( '$a', "return null;" ) );
|
||||
|
||||
# 2.8+:
|
||||
remove_action( 'wp_version_check', 'wp_version_check' );
|
||||
remove_action( 'admin_init', '_maybe_update_core' );
|
||||
add_filter( 'pre_transient_update_core', create_function( '$a', "return null;" ) );
|
||||
|
||||
# 3.0+:
|
||||
add_filter( 'pre_site_transient_update_core', create_function( '$a', "return null;" ) );
|
58
wp-content/plugins/disable-wordpress-core-update/readme.txt
Normal file
58
wp-content/plugins/disable-wordpress-core-update/readme.txt
Normal file
@ -0,0 +1,58 @@
|
||||
=== Disable WordPress Core Updates ===
|
||||
Contributors: johnbillion
|
||||
Tags: disable, core update
|
||||
Requires at least: 2.3
|
||||
Tested up to: 3.7
|
||||
Stable tag: trunk
|
||||
|
||||
Disables WordPress core update checks and notifications.
|
||||
|
||||
== Description ==
|
||||
|
||||
Completely disables the core update checking system in WordPress. This prevents WordPress from checking for core updates, and prevents any notifications from being displayed in the admin area. Ideal for administrators of multiple WordPress installations.
|
||||
|
||||
= Please note! =
|
||||
|
||||
It's *very* important that you keep your WordPress installation(s) up to date. If you don't, your blog or website could be susceptible to security vulnerabilities or performance issues. If you use this plugin, you must make sure you keep yourself informed of new WordPress releases and update your WordPress installation(s) as new versions are released.
|
||||
|
||||
See also: [Disable WordPress plugin updates](http://wordpress.org/plugins/disable-wordpress-plugin-updates/) and [Disable WordPress theme updates](http://wordpress.org/plugins/disable-wordpress-theme-updates/).
|
||||
|
||||
== Installation ==
|
||||
|
||||
1. Unzip the ZIP file and drop the folder straight into your `wp-content/plugins/` directory.
|
||||
2. Activate the plugin through the 'Plugins' menu in WordPress.
|
||||
|
||||
== Frequently Asked Questions ==
|
||||
|
||||
= Why would I want to disable the core update system? =
|
||||
|
||||
Most people will not want to (and should not) disable this feature. It's a fantastic feature of WordPress and I'm fully in support of it. However, administrators who maintain multiple installations of WordPress on behalf of other people (eg. clients) may not want update notifications to be shown to the users of these installations. This plugin is for them.
|
||||
|
||||
= Does this plugin disable the automatic updates in WordPress 3.7 and higher? =
|
||||
|
||||
Yes, this plugin completely disables all core update checks, so the automatic update system will be disabled too.
|
||||
|
||||
= Can I disable the plugin update notifications too? =
|
||||
|
||||
Yes. See the [Disable WordPress Plugin Updates](http://wordpress.org/extend/plugins/disable-wordpress-plugin-updates/) plugin.
|
||||
|
||||
= Can I disable the theme update notifications too? =
|
||||
|
||||
Yes. See the [Disable WordPress Theme Updates](http://wordpress.org/extend/plugins/disable-wordpress-theme-updates/) plugin.
|
||||
|
||||
== Changelog ==
|
||||
|
||||
= 1.5 =
|
||||
* Force the plugin to be network enabled.
|
||||
|
||||
= 1.4 =
|
||||
* Support for WordPress 3.0.
|
||||
|
||||
= 1.3 =
|
||||
* Support for WordPress 2.8.
|
||||
|
||||
= 1.2 =
|
||||
* Bugfix to completely prevent any communication with api.wordpress.org.
|
||||
|
||||
= 1.1 =
|
||||
* Initial release.
|
420
wp-content/plugins/gitium/functions.php
Normal file
420
wp-content/plugins/gitium/functions.php
Normal file
@ -0,0 +1,420 @@
|
||||
<?php
|
||||
/* Copyright 2014-2016 Presslabs SRL <ping@presslabs.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2, as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
function gitium_error_log( $message ) {
|
||||
if ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) { return; }
|
||||
error_log( "gitium_error_log: $message" );
|
||||
}
|
||||
|
||||
function wp_content_is_versioned() {
|
||||
return file_exists( WP_CONTENT_DIR . '/.git' );
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'gitium_enable_maintenance_mode' ) ) :
|
||||
function gitium_enable_maintenance_mode() {
|
||||
$file = ABSPATH . '/.maintenance';
|
||||
|
||||
if ( false === file_put_contents( $file, '<?php $upgrading = ' . time() .';' ) ) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
endif;
|
||||
|
||||
if ( ! function_exists( 'gitium_disable_maintenance_mode' ) ) :
|
||||
function gitium_disable_maintenance_mode() {
|
||||
return unlink( ABSPATH . '/.maintenance' );
|
||||
}
|
||||
endif;
|
||||
|
||||
function gitium_get_versions() {
|
||||
$versions = get_transient( 'gitium_versions' );
|
||||
if ( empty( $versions ) ) {
|
||||
$versions = gitium_update_versions();
|
||||
}
|
||||
return $versions;
|
||||
}
|
||||
|
||||
function _gitium_commit_changes( $message, $dir = '.' ) {
|
||||
global $git;
|
||||
|
||||
list( , $git_private_key ) = gitium_get_keypair();
|
||||
if (!$git_private_key)
|
||||
return false;
|
||||
$git->set_key( $git_private_key );
|
||||
|
||||
$git->add( $dir );
|
||||
gitium_update_versions();
|
||||
$current_user = wp_get_current_user();
|
||||
return $git->commit( $message, $current_user->display_name, $current_user->user_email );
|
||||
}
|
||||
|
||||
function _gitium_format_message( $name, $version = false, $prefix = '' ) {
|
||||
$commit_message = "`$name`";
|
||||
if ( $version ) {
|
||||
$commit_message .= " version $version";
|
||||
}
|
||||
if ( $prefix ) {
|
||||
$commit_message = "$prefix $commit_message";
|
||||
}
|
||||
return $commit_message;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function return the basic info about a path.
|
||||
*
|
||||
* base_path - means the path after wp-content dir (themes/plugins)
|
||||
* type - can be file/theme/plugin
|
||||
* name - the file name of the path, if it is a file, or the theme/plugin name
|
||||
* version - the theme/plugin version, othewise null
|
||||
*/
|
||||
/* Some examples:
|
||||
|
||||
with 'wp-content/themes/twentyten/style.css' will return:
|
||||
array(
|
||||
'base_path' => 'wp-content/themes/twentyten'
|
||||
'type' => 'theme'
|
||||
'name' => 'TwentyTen'
|
||||
'version' => '1.12'
|
||||
)
|
||||
|
||||
with 'wp-content/themes/twentyten/img/foo.png' will return:
|
||||
array(
|
||||
'base_path' => 'wp-content/themes/twentyten'
|
||||
'type' => 'theme'
|
||||
'name' => 'TwentyTen'
|
||||
'version' => '1.12'
|
||||
)
|
||||
|
||||
with 'wp-content/plugins/foo.php' will return:
|
||||
array(
|
||||
'base_path' => 'wp-content/plugins/foo.php'
|
||||
'type' => 'plugin'
|
||||
'name' => 'Foo'
|
||||
'varsion' => '2.0'
|
||||
)
|
||||
|
||||
with 'wp-content/plugins/autover/autover.php' will return:
|
||||
array(
|
||||
'base_path' => 'wp-content/plugins/autover'
|
||||
'type' => 'plugin'
|
||||
'name' => 'autover'
|
||||
'version' => '3.12'
|
||||
)
|
||||
|
||||
with 'wp-content/plugins/autover/' will return:
|
||||
array(
|
||||
'base_path' => 'wp-content/plugins/autover'
|
||||
'type' => 'plugin'
|
||||
'name' => 'autover'
|
||||
'version' => '3.12'
|
||||
)
|
||||
*/
|
||||
function _gitium_module_by_path( $path ) {
|
||||
$versions = gitium_get_versions();
|
||||
|
||||
// default values
|
||||
$module = array(
|
||||
'base_path' => $path,
|
||||
'type' => 'file',
|
||||
'name' => basename( $path ),
|
||||
'version' => null,
|
||||
);
|
||||
|
||||
// find the base_path
|
||||
$split_path = explode( '/', $path );
|
||||
if ( 2 < count( $split_path ) ) {
|
||||
$module['base_path'] = "{$split_path[0]}/{$split_path[1]}/{$split_path[2]}";
|
||||
}
|
||||
|
||||
// find other data for theme
|
||||
if ( array_key_exists( 'themes', $versions ) && 0 === strpos( $path, 'wp-content/themes/' ) ) {
|
||||
$module['type'] = 'theme';
|
||||
foreach ( $versions['themes'] as $theme => $data ) {
|
||||
if ( 0 === strpos( $path, "wp-content/themes/$theme" ) ) {
|
||||
$module['name'] = $data['name'];
|
||||
$module['version'] = $data['version'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// find other data for plugin
|
||||
if ( array_key_exists( 'plugins', $versions ) && 0 === strpos( $path, 'wp-content/plugins/' ) ) {
|
||||
$module['type'] = 'plugin';
|
||||
foreach ( $versions['plugins'] as $plugin => $data ) {
|
||||
if ( '.' === dirname( $plugin ) ) { // single file plugin
|
||||
if ( "wp-content/plugins/$plugin" === $path ) {
|
||||
$module['base_path'] = $path;
|
||||
$module['name'] = $data['name'];
|
||||
$module['version'] = $data['version'];
|
||||
break;
|
||||
}
|
||||
} else if ( 'wp-content/plugins/' . dirname( $plugin ) === $module['base_path'] ) {
|
||||
$module['name'] = $data['name'];
|
||||
$module['version'] = $data['version'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $module;
|
||||
}
|
||||
|
||||
function gitium_group_commit_modified_plugins_and_themes( $msg_append = '' ) {
|
||||
global $git;
|
||||
|
||||
$uncommited_changes = $git->get_local_changes();
|
||||
$commit_groups = array();
|
||||
$commits = array();
|
||||
|
||||
if ( ! empty( $msg_append ) ) {
|
||||
$msg_append = "($msg_append)";
|
||||
}
|
||||
foreach ( $uncommited_changes as $path => $action ) {
|
||||
$change = _gitium_module_by_path( $path );
|
||||
$change['action'] = $action;
|
||||
$commit_groups[ $change['base_path'] ] = $change;
|
||||
}
|
||||
|
||||
foreach ( $commit_groups as $base_path => $change ) {
|
||||
$commit_message = _gitium_format_message( $change['name'], $change['version'], "${change['action']} ${change['type']}" );
|
||||
$commit = _gitium_commit_changes( "$commit_message $msg_append", $base_path, false );
|
||||
if ( $commit ) {
|
||||
$commits[] = $commit;
|
||||
}
|
||||
}
|
||||
|
||||
return $commits;
|
||||
}
|
||||
|
||||
function gitium_commit_and_push_gitignore_file( $path = '' ) {
|
||||
global $git;
|
||||
|
||||
$current_user = wp_get_current_user();
|
||||
if ( ! empty( $path ) ) { $git->rm_cached( $path ); }
|
||||
$git->add( '.gitignore' );
|
||||
$commit = $git->commit( 'Update the `.gitignore` file', $current_user->display_name, $current_user->user_email );
|
||||
gitium_merge_and_push( $commit );
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'gitium_acquire_merge_lock' ) ) :
|
||||
function gitium_acquire_merge_lock() {
|
||||
$gitium_lock_path = apply_filters( 'gitium_lock_path', '/tmp/.gitium-lock' );
|
||||
$gitium_lock_handle = fopen( $gitium_lock_path, 'w+' );
|
||||
|
||||
$lock_timeout = intval( ini_get( 'max_execution_time' ) ) > 10 ? intval( ini_get( 'max_execution_time' ) ) - 5 : 10;
|
||||
$lock_timeout_ms = 10;
|
||||
$lock_retries = 0;
|
||||
while ( ! flock( $gitium_lock_handle, LOCK_EX | LOCK_NB ) ) {
|
||||
usleep( $lock_timeout_ms * 1000 );
|
||||
$lock_retries++;
|
||||
if ( $lock_retries * $lock_timeout_ms > $lock_timeout * 1000 ) {
|
||||
return false; // timeout
|
||||
}
|
||||
}
|
||||
gitium_error_log( __FUNCTION__ );
|
||||
return array( $gitium_lock_path, $gitium_lock_handle );
|
||||
}
|
||||
endif;
|
||||
|
||||
if ( ! function_exists( 'gitium_release_merge_lock' ) ) :
|
||||
function gitium_release_merge_lock( $lock ) {
|
||||
list( $gitium_lock_path, $gitium_lock_handle ) = $lock;
|
||||
gitium_error_log( __FUNCTION__ );
|
||||
flock( $gitium_lock_handle, LOCK_UN );
|
||||
fclose( $gitium_lock_handle );
|
||||
}
|
||||
endif;
|
||||
|
||||
// Merges the commits with remote and pushes them back
|
||||
function gitium_merge_and_push( $commits ) {
|
||||
global $git;
|
||||
|
||||
$lock = gitium_acquire_merge_lock()
|
||||
or trigger_error( 'Timeout when gitium lock was acquired', E_USER_WARNING );
|
||||
|
||||
if ( ! $git->fetch_ref() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$merge_status = $git->merge_with_accept_mine( $commits );
|
||||
|
||||
gitium_release_merge_lock( $lock );
|
||||
|
||||
return $git->push() && $merge_status;
|
||||
}
|
||||
|
||||
function gitium_check_after_event( $plugin, $event = 'activation' ) {
|
||||
global $git;
|
||||
|
||||
if ( 'gitium/gitium.php' == $plugin ) { return; } // do not hook on activation of this plugin
|
||||
|
||||
if ( $git->is_dirty() ) {
|
||||
$versions = gitium_update_versions();
|
||||
if ( isset( $versions['plugins'][ $plugin ] ) ) {
|
||||
$name = $versions['plugins'][ $plugin ]['name'];
|
||||
$version = $versions['plugins'][ $plugin ]['version'];
|
||||
} else {
|
||||
$name = $plugin;
|
||||
}
|
||||
gitium_auto_push( _gitium_format_message( $name, $version, "after $event of" ) );
|
||||
}
|
||||
}
|
||||
|
||||
function gitium_update_remote_tracking_branch() {
|
||||
global $git;
|
||||
$remote_branch = $git->get_remote_tracking_branch();
|
||||
set_transient( 'gitium_remote_tracking_branch', $remote_branch );
|
||||
|
||||
return $remote_branch;
|
||||
}
|
||||
|
||||
function _gitium_get_remote_tracking_branch( $update_transient = false ) {
|
||||
if ( ! $update_transient && ( false !== ( $remote_branch = get_transient( 'gitium_remote_tracking_branch' ) ) ) ) {
|
||||
return $remote_branch;
|
||||
} else {
|
||||
return gitium_update_remote_tracking_branch();
|
||||
}
|
||||
}
|
||||
|
||||
function gitium_update_is_status_working() {
|
||||
global $git;
|
||||
$is_status_working = $git->is_status_working();
|
||||
set_transient( 'gitium_is_status_working', $is_status_working );
|
||||
return $is_status_working;
|
||||
}
|
||||
|
||||
function _gitium_is_status_working( $update_transient = false ) {
|
||||
if ( ! $update_transient && ( false !== ( $is_status_working = get_transient( 'gitium_is_status_working' ) ) ) ) {
|
||||
return $is_status_working;
|
||||
} else {
|
||||
return gitium_update_is_status_working();
|
||||
}
|
||||
}
|
||||
|
||||
function _gitium_status( $update_transient = false ) {
|
||||
global $git;
|
||||
|
||||
if ( ! $update_transient && ( false !== ( $changes = get_transient( 'gitium_uncommited_changes' ) ) ) ) {
|
||||
return $changes;
|
||||
}
|
||||
|
||||
$git_version = get_transient( 'gitium_git_version' );
|
||||
if ( false === $git_version ) {
|
||||
set_transient( 'gitium_git_version', $git->get_version() );
|
||||
}
|
||||
|
||||
if ( $git->is_status_working() && $git->get_remote_tracking_branch() ) {
|
||||
if ( ! $git->fetch_ref() ) {
|
||||
set_transient( 'gitium_remote_disconnected', $git->get_last_error() );
|
||||
} else {
|
||||
delete_transient( 'gitium_remote_disconnected' );
|
||||
}
|
||||
$changes = $git->status();
|
||||
} else {
|
||||
delete_transient( 'gitium_remote_disconnected' );
|
||||
$changes = array();
|
||||
}
|
||||
|
||||
set_transient( 'gitium_uncommited_changes', $changes, 12 * 60 * 60 ); // cache changes for half-a-day
|
||||
return $changes;
|
||||
}
|
||||
|
||||
function _gitium_ssh_encode_buffer( $buffer ) {
|
||||
$len = strlen( $buffer );
|
||||
if ( ord( $buffer[0] ) & 0x80 ) {
|
||||
$len++;
|
||||
$buffer = "\x00" . $buffer;
|
||||
}
|
||||
return pack( 'Na*', $len, $buffer );
|
||||
}
|
||||
|
||||
function _gitium_generate_keypair() {
|
||||
$rsa_key = openssl_pkey_new(
|
||||
array(
|
||||
'private_key_bits' => 2048,
|
||||
'private_key_type' => OPENSSL_KEYTYPE_RSA,
|
||||
)
|
||||
);
|
||||
|
||||
try {
|
||||
$private_key = openssl_pkey_get_private( $rsa_key );
|
||||
$try = openssl_pkey_export( $private_key, $pem ); //Private Key
|
||||
if (!$try)
|
||||
return false;
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$key_info = openssl_pkey_get_details( $rsa_key );
|
||||
$buffer = pack( 'N', 7 ) . 'ssh-rsa' .
|
||||
_gitium_ssh_encode_buffer( $key_info['rsa']['e'] ) .
|
||||
_gitium_ssh_encode_buffer( $key_info['rsa']['n'] );
|
||||
$public_key = 'ssh-rsa ' . base64_encode( $buffer ) . ' gitium@' . parse_url( get_home_url(), PHP_URL_HOST );
|
||||
|
||||
return array( $public_key, $pem );
|
||||
}
|
||||
|
||||
function gitium_get_keypair( $generate_new_keypair = false ) {
|
||||
if ( $generate_new_keypair ) {
|
||||
$keypair = _gitium_generate_keypair();
|
||||
delete_option( 'gitium_keypair' );
|
||||
add_option( 'gitium_keypair', $keypair, '', false );
|
||||
}
|
||||
if ( false === ( $keypair = get_option( 'gitium_keypair', false ) ) ) {
|
||||
$keypair = _gitium_generate_keypair();
|
||||
add_option( 'gitium_keypair', $keypair, '', false );
|
||||
}
|
||||
return $keypair;
|
||||
}
|
||||
|
||||
function _gitium_generate_webhook_key() {
|
||||
return md5( str_shuffle( 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.()[]{}-_=+!@#%^&*~<>:;' ) );
|
||||
}
|
||||
|
||||
function gitium_get_webhook_key( $generate_new_webhook_key = false ) {
|
||||
if ( $generate_new_webhook_key ) {
|
||||
$key = _gitium_generate_webhook_key();
|
||||
delete_option( 'gitium_webhook_key' );
|
||||
add_option( 'gitium_webhook_key', $key, '', false );
|
||||
return $key;
|
||||
}
|
||||
if ( false === ( $key = get_option( 'gitium_webhook_key', false ) ) ) {
|
||||
$key = _gitium_generate_webhook_key();
|
||||
add_option( 'gitium_webhook_key', $key, '', false );
|
||||
}
|
||||
return $key;
|
||||
}
|
||||
|
||||
function gitium_get_webhook() {
|
||||
if ( defined( 'GIT_WEBHOOK_URL' ) && GIT_WEBHOOK_URL ) { return GIT_WEBHOOK_URL; }
|
||||
$key = gitium_get_webhook_key();
|
||||
$url = add_query_arg( 'key', $key, plugins_url( 'gitium-webhook.php', __FILE__ ) );
|
||||
return apply_filters( 'gitium_webhook_url', $url, $key );
|
||||
}
|
||||
|
||||
function gitium_admin_init() {
|
||||
global $git;
|
||||
|
||||
$git_version = get_transient( 'gitium_git_version' );
|
||||
if ( false === $git_version ) {
|
||||
set_transient( 'gitium_git_version', $git->get_version() );
|
||||
}
|
||||
}
|
||||
add_action( 'admin_init', 'gitium_admin_init' );
|
49
wp-content/plugins/gitium/gitium-webhook.php
Normal file
49
wp-content/plugins/gitium/gitium-webhook.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/* Copyright 2014-2016 Presslabs SRL <ping@presslabs.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2, as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
header( 'Content-Type: text/html' );
|
||||
define( 'SHORTINIT', true );
|
||||
//$wordpress_loader = $_SERVER['DOCUMENT_ROOT'] . '/wp-load.php';
|
||||
$wordpress_loader = filter_input(INPUT_SERVER, 'DOCUMENT_ROOT', FILTER_SANITIZE_STRING) . '/wp-load.php';
|
||||
|
||||
require_once $wordpress_loader;
|
||||
require_once __DIR__ . '/functions.php';
|
||||
require_once __DIR__ . '/inc/class-git-wrapper.php';
|
||||
|
||||
$webhook_key = get_option( 'gitium_webhook_key', '' );
|
||||
$get_key = filter_input(INPUT_GET, 'key', FILTER_SANITIZE_STRING);
|
||||
if ( ! empty ( $webhook_key ) && isset( $get_key ) && $webhook_key == $get_key ) :
|
||||
( '1.7' <= substr( $git->get_version(), 0, 3 ) ) or wp_die( 'Gitium plugin require minimum `git version 1.7`!' );
|
||||
|
||||
list( $git_public_key, $git_private_key ) = gitium_get_keypair();
|
||||
if ( ! $git_public_key || ! $git_private_key )
|
||||
wp_die('Not ready.', 'Not ready.', array( 'response' => 403 ));
|
||||
else
|
||||
$git->set_key( $git_private_key );
|
||||
|
||||
$commits = array();
|
||||
$commitmsg = sprintf( 'Merged changes from %s on %s', $_SERVER['SERVER_NAME'], date( 'm.d.Y' ) );
|
||||
|
||||
if ( $git->is_dirty() && $git->add() > 0 ) {
|
||||
$commits[] = $git->commit( $commitmsg ) or trigger_error( 'Could not commit local changes!', E_USER_ERROR );
|
||||
}
|
||||
gitium_merge_and_push( $commits ) or trigger_error( 'Failed merge & push: ' . serialize( $git->get_last_error() ), E_USER_ERROR );
|
||||
|
||||
wp_die( $commitmsg , 'Pull done!', array( 'response' => 200 ) );
|
||||
else :
|
||||
wp_die( 'Cheating uh?', 'Cheating uh?', array( 'response' => 403 ) );
|
||||
endif;
|
374
wp-content/plugins/gitium/gitium.php
Normal file
374
wp-content/plugins/gitium/gitium.php
Normal file
@ -0,0 +1,374 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin Name: Gitium
|
||||
* Version: 1.0.3
|
||||
* Author: Presslabs
|
||||
* Author URI: https://www.presslabs.com
|
||||
* License: GPL2
|
||||
* Description: Keep all your code on git version control system.
|
||||
* Text Domain: gitium
|
||||
* Domain Path: /languages/
|
||||
*/
|
||||
/* Copyright 2014-2016 Presslabs SRL <ping@presslabs.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2, as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
define( 'GITIUM_LAST_COMMITS', 20 );
|
||||
define( 'GITIUM_MIN_GIT_VER', '1.7' );
|
||||
define( 'GITIUM_MIN_PHP_VER', '5.6' );
|
||||
|
||||
if ( is_multisite() ) {
|
||||
define( 'GITIUM_ADMIN_MENU_ACTION', 'network_admin_menu' );
|
||||
define( 'GITIUM_ADMIN_NOTICES_ACTION', 'network_admin_notices' );
|
||||
define( 'GITIUM_MANAGE_OPTIONS_CAPABILITY', 'manage_network_options' );
|
||||
} else {
|
||||
define( 'GITIUM_ADMIN_MENU_ACTION', 'admin_menu' );
|
||||
define( 'GITIUM_ADMIN_NOTICES_ACTION', 'admin_notices' );
|
||||
define( 'GITIUM_MANAGE_OPTIONS_CAPABILITY', 'manage_options' );
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/functions.php';
|
||||
require_once __DIR__ . '/inc/class-git-wrapper.php';
|
||||
require_once __DIR__ . '/inc/class-gitium-requirements.php';
|
||||
require_once __DIR__ . '/inc/class-gitium-admin.php';
|
||||
require_once __DIR__ . '/inc/class-gitium-help.php';
|
||||
require_once __DIR__ . '/inc/class-gitium-menu.php';
|
||||
require_once __DIR__ . '/inc/class-gitium-menu-bubble.php';
|
||||
require_once __DIR__ . '/inc/class-gitium-submenu-configure.php';
|
||||
require_once __DIR__ . '/inc/class-gitium-submenu-status.php';
|
||||
require_once __DIR__ . '/inc/class-gitium-submenu-commits.php';
|
||||
require_once __DIR__ . '/inc/class-gitium-submenu-settings.php';
|
||||
|
||||
function gitium_load_textdomain() {
|
||||
load_plugin_textdomain( 'gitium', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
|
||||
}
|
||||
add_action( 'plugins_loaded', 'gitium_load_textdomain' );
|
||||
|
||||
function _gitium_make_ssh_git_file_exe() {
|
||||
$ssh_wrapper = dirname( __FILE__ ) . '/inc/ssh-git';
|
||||
$process = proc_open(
|
||||
"chmod -f +x $ssh_wrapper",
|
||||
array(
|
||||
0 => array( 'pipe', 'r' ), // stdin
|
||||
1 => array( 'pipe', 'w' ), // stdout
|
||||
),
|
||||
$pipes
|
||||
);
|
||||
if ( is_resource( $process ) ) {
|
||||
fclose( $pipes[0] );
|
||||
proc_close( $process );
|
||||
}
|
||||
}
|
||||
register_activation_hook( __FILE__, '_gitium_make_ssh_git_file_exe' );
|
||||
|
||||
function gitium_deactivation() {
|
||||
delete_transient( 'gitium_git_version' );
|
||||
}
|
||||
register_deactivation_hook( __FILE__, 'gitium_deactivation' );
|
||||
|
||||
function gitium_uninstall_hook() {
|
||||
delete_transient( 'gitium_remote_tracking_branch' );
|
||||
delete_transient( 'gitium_remote_disconnected' );
|
||||
delete_transient( 'gitium_uncommited_changes' );
|
||||
delete_transient( 'gitium_git_version' );
|
||||
delete_transient( 'gitium_versions' );
|
||||
delete_transient( 'gitium_menu_bubble' );
|
||||
delete_transient( 'gitium_is_status_working' );
|
||||
|
||||
delete_option( 'gitium_keypair' );
|
||||
delete_option( 'gitium_webhook_key' );
|
||||
}
|
||||
register_uninstall_hook( __FILE__, 'gitium_uninstall_hook' );
|
||||
|
||||
/* Array
|
||||
(
|
||||
[themes] => Array
|
||||
(
|
||||
[twentytwelve] => `Twenty Twelve` version 1.3
|
||||
)
|
||||
[plugins] => Array
|
||||
(
|
||||
[cron-view/cron-gui.php] => `Cron GUI` version 1.03
|
||||
[hello-dolly/hello.php] => `Hello Dolly` version 1.6
|
||||
)
|
||||
|
||||
) */
|
||||
function gitium_update_versions() {
|
||||
$new_versions = [];
|
||||
|
||||
// get all themes from WP
|
||||
$all_themes = wp_get_themes( array( 'allowed' => true ) );
|
||||
foreach ( $all_themes as $theme_name => $theme ) :
|
||||
$theme_versions[ $theme_name ] = array(
|
||||
'name' => $theme->Name,
|
||||
'version' => null,
|
||||
'msg' => '',
|
||||
);
|
||||
$theme_versions[ $theme_name ]['msg'] = '`' . $theme->Name . '`';
|
||||
$version = $theme->Version;
|
||||
if ( ! empty( $version ) ) {
|
||||
$theme_versions[ $theme_name ]['msg'] .= " version $version";
|
||||
$theme_versions[ $theme_name ]['version'] .= $version;
|
||||
}
|
||||
endforeach;
|
||||
|
||||
if ( ! empty( $theme_versions ) ) {
|
||||
$new_versions['themes'] = $theme_versions;
|
||||
}
|
||||
// get all plugins from WP
|
||||
if ( ! function_exists( 'get_plugins' ) ) {
|
||||
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
||||
}
|
||||
$all_plugins = get_plugins();
|
||||
foreach ( $all_plugins as $name => $data ) :
|
||||
$plugin_versions[ $name ] = array(
|
||||
'name' => $data['Name'],
|
||||
'version' => null,
|
||||
'msg' => '',
|
||||
);
|
||||
$plugin_versions[ $name ]['msg'] = "`{$data['Name']}`";
|
||||
if ( ! empty( $data['Version'] ) ) {
|
||||
$plugin_versions[ $name ]['msg'] .= ' version ' . $data['Version'];
|
||||
$plugin_versions[ $name ]['version'] .= $data['Version'];
|
||||
}
|
||||
endforeach;
|
||||
|
||||
if ( ! empty( $plugin_versions ) ) {
|
||||
$new_versions['plugins'] = $plugin_versions;
|
||||
}
|
||||
|
||||
set_transient( 'gitium_versions', $new_versions );
|
||||
|
||||
return $new_versions;
|
||||
}
|
||||
add_action( 'load-plugins.php', 'gitium_update_versions', 999 );
|
||||
|
||||
function gitium_upgrader_post_install( $res, $hook_extra, $result ) {
|
||||
_gitium_make_ssh_git_file_exe();
|
||||
|
||||
$action = null;
|
||||
$type = null;
|
||||
|
||||
// install logic
|
||||
if ( isset( $hook_extra['type'] ) && ( 'plugin' === $hook_extra['type'] ) ) {
|
||||
$action = 'installed';
|
||||
$type = 'plugin';
|
||||
} else if ( isset( $hook_extra['type'] ) && ( 'theme' === $hook_extra['type'] ) ) {
|
||||
$action = 'installed';
|
||||
$type = 'theme';
|
||||
}
|
||||
|
||||
// update/upgrade logic
|
||||
if ( isset( $hook_extra['plugin'] ) ) {
|
||||
$action = 'updated';
|
||||
$type = 'plugin';
|
||||
} else if ( isset( $hook_extra['theme'] ) ) {
|
||||
$action = 'updated';
|
||||
$type = 'theme';
|
||||
}
|
||||
|
||||
// get action if missed above
|
||||
if ( isset( $hook_extra['action'] ) ) {
|
||||
$action = $hook_extra['action'];
|
||||
if ( 'install' === $action ) {
|
||||
$action = 'installed';
|
||||
}
|
||||
if ( 'update' === $action ) {
|
||||
$action = 'updated';
|
||||
}
|
||||
}
|
||||
|
||||
if ( WP_DEBUG ) {
|
||||
error_log( __FUNCTION__ . ':hook_extra:' . serialize( $hook_extra ) );
|
||||
error_log( __FUNCTION__ . ':action:type:' . $action . ':' . $type );
|
||||
}
|
||||
|
||||
$git_dir = $result['destination'];
|
||||
$version = '';
|
||||
|
||||
if ( ABSPATH == substr( $git_dir, 0, strlen( ABSPATH ) ) ) {
|
||||
$git_dir = substr( $git_dir, strlen( ABSPATH ) );
|
||||
}
|
||||
switch ( $type ) {
|
||||
case 'theme':
|
||||
wp_clean_themes_cache();
|
||||
$theme_data = wp_get_theme( $result['destination_name'] );
|
||||
$name = $theme_data->get( 'Name' );
|
||||
$version = $theme_data->get( 'Version' );
|
||||
break;
|
||||
case 'plugin':
|
||||
foreach ( $result['source_files'] as $file ) :
|
||||
if ( '.php' != substr( $file, -4 ) ) { continue; }
|
||||
// every .php file is a possible plugin so we check if it's a plugin
|
||||
$filepath = trailingslashit( $result['destination'] ) . $file;
|
||||
$plugin_data = get_plugin_data( $filepath );
|
||||
if ( $plugin_data['Name'] ) :
|
||||
$name = $plugin_data['Name'];
|
||||
$version = $plugin_data['Version'];
|
||||
// We get info from the first plugin in the package
|
||||
break;
|
||||
endif;
|
||||
endforeach;
|
||||
break;
|
||||
}
|
||||
if ( empty( $name ) ) {
|
||||
$name = $result['destination_name'];
|
||||
}
|
||||
$commit_message = _gitium_format_message( $name,$version,"$action $type" );
|
||||
$commit = _gitium_commit_changes( $commit_message, $git_dir, false );
|
||||
gitium_merge_and_push( $commit );
|
||||
|
||||
return $res;
|
||||
}
|
||||
add_filter( 'upgrader_post_install', 'gitium_upgrader_post_install', 10, 3 );
|
||||
|
||||
// Checks for local changes, tries to group them by plugin/theme and pushes the changes
|
||||
function gitium_auto_push( $msg_prepend = '' ) {
|
||||
global $git;
|
||||
list( , $git_private_key ) = gitium_get_keypair();
|
||||
if ( ! $git_private_key )
|
||||
return;
|
||||
$git->set_key( $git_private_key );
|
||||
|
||||
$commits = gitium_group_commit_modified_plugins_and_themes( $msg_prepend );
|
||||
gitium_merge_and_push( $commits );
|
||||
gitium_update_versions();
|
||||
}
|
||||
add_action( 'upgrader_process_complete', 'gitium_auto_push', 11, 0 );
|
||||
|
||||
function gitium_check_after_activate_modifications( $plugin ) {
|
||||
gitium_check_after_event( $plugin );
|
||||
}
|
||||
add_action( 'activated_plugin', 'gitium_check_after_activate_modifications', 999 );
|
||||
|
||||
function gitium_check_after_deactivate_modifications( $plugin ) {
|
||||
gitium_check_after_event( $plugin, 'deactivation' );
|
||||
}
|
||||
add_action( 'deactivated_plugin', 'gitium_check_after_deactivate_modifications', 999 );
|
||||
|
||||
function gitium_check_for_plugin_deletions() { // Handle plugin deletion
|
||||
// $_GET['deleted'] used to resemble if a plugin has been deleted (true)
|
||||
// ...meanwhile commit b28dd45f3dad19f0e06c546fdc89ed5b24bacd72 in github.com/WordPress/WordPress...
|
||||
// Now it resembles the number of deleted plugins (a number). Thanks WP
|
||||
if ( isset( $_GET['deleted'] ) && ( 1 <= (int) $_GET['deleted'] || 'true' == $_GET['deleted'] ) ) {
|
||||
gitium_auto_push();
|
||||
}
|
||||
}
|
||||
add_action( 'load-plugins.php', 'gitium_check_for_plugin_deletions' );
|
||||
|
||||
add_action( 'wp_ajax_wp-plugin-delete-success', 'gitium_auto_push' );
|
||||
add_action( 'wp_ajax_wp-theme-delete-success', 'gitium_auto_push' );
|
||||
|
||||
function gitium_wp_plugin_delete_success() {
|
||||
?>
|
||||
<script type='text/javascript'>
|
||||
jQuery(document).ready(function() {
|
||||
jQuery(document).on( 'wp-plugin-delete-success', function() {
|
||||
jQuery.post(ajaxurl, data={'action': 'wp-plugin-delete-success'});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
add_action( 'admin_head', 'gitium_wp_plugin_delete_success' );
|
||||
|
||||
function gitium_wp_theme_delete_success() {
|
||||
?>
|
||||
<script type='text/javascript'>
|
||||
jQuery(document).ready(function() {
|
||||
jQuery(document).on( 'wp-theme-delete-success', function() {
|
||||
jQuery.post(ajaxurl, data={'action': 'wp-theme-delete-success'});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
add_action( 'admin_head', 'gitium_wp_theme_delete_success' );
|
||||
|
||||
function gitium_check_for_themes_deletions() { // Handle theme deletion
|
||||
if ( isset( $_GET['deleted'] ) && 'true' == $_GET['deleted'] ) {
|
||||
gitium_auto_push();
|
||||
}
|
||||
}
|
||||
add_action( 'load-themes.php', 'gitium_check_for_themes_deletions' );
|
||||
|
||||
// Deprecated function - backward compatibility
|
||||
function gitium_hook_plugin_and_theme_editor_page( $hook )
|
||||
{
|
||||
switch ($hook) {
|
||||
case 'plugin-editor.php':
|
||||
if (isset($_GET['a']) && 'te' == $_GET['a']) {
|
||||
gitium_auto_push();
|
||||
}
|
||||
break;
|
||||
|
||||
case 'theme-editor.php':
|
||||
if (isset($_GET['updated']) && 'true' == $_GET['updated']) {
|
||||
gitium_auto_push();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* We execute the "gitium_auto_push" on "wp_die_ajax_handler" filter to make sure we are
|
||||
* at the end of our request and the latest file is saved on disk.
|
||||
*/
|
||||
function gitium_check_ajax_success_call($callback)
|
||||
{
|
||||
gitium_auto_push();
|
||||
|
||||
return $callback;
|
||||
}
|
||||
|
||||
/*
|
||||
* We add this filer on "wp_die_ajax_handler" since our action executes before the actual file is saved on disk
|
||||
* which results in a race condition that would commit only the previously saved data not the
|
||||
* currently saved one.
|
||||
*/
|
||||
function add_filter_for_ajax_save()
|
||||
{
|
||||
add_filter('wp_die_ajax_handler', 'gitium_check_ajax_success_call', 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to apply different filters while checking for WP version to maintain
|
||||
* backworks compatibility since the Code Editor has changed drastically
|
||||
* with the 4.9 WP update.
|
||||
*/
|
||||
if ( version_compare( $GLOBALS['wp_version'], '4.9', '>=' ) )
|
||||
add_action( 'wp_ajax_edit-theme-plugin-file', 'add_filter_for_ajax_save', 1, 0 );
|
||||
else
|
||||
add_action( 'admin_enqueue_scripts', 'gitium_hook_plugin_and_theme_editor_page' );
|
||||
|
||||
function gitium_options_page_check() {
|
||||
global $git;
|
||||
if ( ! $git->can_exec_git() ) { wp_die( 'Cannot exec git' ); }
|
||||
return true;
|
||||
}
|
||||
|
||||
function gitium_remote_disconnected_notice() {
|
||||
if ( current_user_can( GITIUM_MANAGE_OPTIONS_CAPABILITY ) && $message = get_transient( 'gitium_remote_disconnected' ) ) : ?>
|
||||
<div class="error-nag error">
|
||||
<p>
|
||||
Could not connect to remote repository.
|
||||
<pre><?php echo esc_html( $message ); ?></pre>
|
||||
</p>
|
||||
</div>
|
||||
<?php endif;
|
||||
}
|
||||
add_action( 'admin_notices', 'gitium_remote_disconnected_notice' );
|
BIN
wp-content/plugins/gitium/img/gitium.png
Normal file
BIN
wp-content/plugins/gitium/img/gitium.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 540 B |
26
wp-content/plugins/gitium/img/gitium.svg
Normal file
26
wp-content/plugins/gitium/img/gitium.svg
Normal file
@ -0,0 +1,26 @@
|
||||
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In -->
|
||||
<svg version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
|
||||
x="0px" y="0px" width="233.9px" height="204.1px" viewBox="0 0 233.9 204.1" enable-background="new 0 0 233.9 204.1"
|
||||
xml:space="preserve">
|
||||
<defs>
|
||||
</defs>
|
||||
<path fill="#496567" d="M233.9,0v172.3c0,16.8-14.7,31.8-30,31.8H39c-25.4,0-39-13.2-39-45.4V35.1h37.9V0H233.9L233.9,0z"/>
|
||||
<path fill="#FFFFFF" d="M37.9,46.8H12.4v113.8c0,17.5,6.5,25.8,12.6,25.8c7.4,0,12.8-8.2,12.8-25.8V46.8z M219.4,14H51.5v149.2
|
||||
c0,12.1-2.2,20.8-5.6,27.6h156.9c6.7,0,17.7-9,16.5-22.1V14z"/>
|
||||
<path fill="#496567" d="M192.4,46.4H79.5c-3.4,0-6.1-2.7-6.1-6.1c0-3.4,2.7-6.1,6.1-6.1h112.9c3.4,0,6.1,2.7,6.1,6.1
|
||||
C198.5,43.7,195.8,46.4,192.4,46.4z M149.7,118.3c-1-1.4-2.2-2.3-3.8-2.7s-3.5-0.6-5.8-0.6h-18.5c-2.2,0-4,0.6-5.3,1.8
|
||||
c-1.3,1.2-2,2.7-2,4.5c0,2.2,0.8,3.8,2.3,4.7s3.9,1.4,6.9,1.4h12.6v13.1c-3.4,1.8-6.8,3.2-10.1,4.2c-3.3,1-6.9,1.5-10.6,1.5
|
||||
c-7.8,0-13.8-2.5-18.2-7.6c-4.3-5.1-6.5-12.4-6.5-21.8c0-4.4,0.6-8.3,1.7-11.9s2.7-6.6,4.8-9.1c2.1-2.5,4.6-4.4,7.6-5.7
|
||||
c3-1.3,6.3-2,10.1-2c3.7,0,6.7,0.5,9,1.6s4.2,2.5,5.6,4.1s3.1,4,5.1,7.1c0.7,1,1.6,1.8,2.7,2.3s2.2,0.8,3.4,0.8
|
||||
c2.1,0,3.9-0.7,5.5-2.2c1.5-1.4,2.3-3.2,2.3-5.3c0-1.9-0.7-4.1-2-6.5c-1.3-2.5-3.3-4.8-5.9-7c-2.6-2.2-6-4-10.2-5.5
|
||||
c-4.2-1.4-9-2.2-14.4-2.2c-6.6,0-12.5,1-17.7,2.9c-5.2,1.9-9.6,4.7-13.3,8.3s-6.4,8-8.2,13.3s-2.8,10.9-2.8,17.2
|
||||
c0,6.4,1,12.2,2.9,17.3c1.9,5.2,4.7,9.6,8.3,13.2s7.9,6.4,13,8.3c5.1,1.9,10.7,2.9,16.9,2.9c5.3,0,10.2-0.6,14.7-1.8
|
||||
c4.5-1.2,9.2-3.1,14.1-5.8c1.7-0.9,3.1-1.9,4.2-2.9s1.8-2.1,2.2-3.3c0.4-1.2,0.6-2.9,0.6-4.9v-15.5
|
||||
C151.1,121.8,150.7,119.7,149.7,118.3z M161.3,100.5c-1.2,1-1.8,2.3-1.8,3.9c0,1.6,0.6,2.9,1.7,3.9s2.8,1.5,4.9,1.5h2v28.8
|
||||
c0,4.7,0.4,8.4,1.1,11.2s2.3,5,4.8,6.5c2.4,1.6,6,2.4,10.7,2.4c4.9,0,8.7-0.6,11.4-1.9c2.6-1.3,4-3.1,4-5.6c0-1.4-0.5-2.6-1.5-3.6
|
||||
c-1-1-2.1-1.5-3.3-1.5c-0.8,0-2,0.2-3.5,0.5c-1.5,0.3-2.7,0.5-3.6,0.5c-1.6,0-2.8-0.4-3.5-1.2c-0.7-0.8-1.2-1.8-1.3-3.1
|
||||
c-0.2-1.3-0.2-3.1-0.2-5.4v-27.6h2.8c3,0,5.3-0.4,6.8-1.2c1.6-0.8,2.4-2.2,2.4-4.2c0-1.6-0.6-2.9-1.7-3.9c-1.1-1-2.7-1.5-4.9-1.5
|
||||
h-5.5V88.8c0-2.5-0.1-4.5-0.4-5.9c-0.3-1.4-0.9-2.5-2-3.5c-1.5-1.4-3.3-2.1-5.2-2.1c-1.4,0-2.6,0.3-3.7,1c-1.1,0.6-1.9,1.5-2.5,2.5
|
||||
c-0.6,1-0.9,2.2-1.1,3.5c-0.1,1.4-0.2,3.3-0.2,5.7v9h-1.6C164.2,99,162.5,99.5,161.3,100.5z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 2.4 KiB |
667
wp-content/plugins/gitium/inc/class-git-wrapper.php
Normal file
667
wp-content/plugins/gitium/inc/class-git-wrapper.php
Normal file
@ -0,0 +1,667 @@
|
||||
<?php
|
||||
/* Copyright 2014-2016 Presslabs SRL <ping@presslabs.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2, as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
define('GITIGNORE', <<<EOF
|
||||
*.log
|
||||
*.swp
|
||||
*.back
|
||||
*.bak
|
||||
*.sql
|
||||
*.sql.gz
|
||||
~*
|
||||
|
||||
.htaccess
|
||||
.maintenance
|
||||
|
||||
wp-config.php
|
||||
sitemap.xml
|
||||
sitemap.xml.gz
|
||||
wp-content/uploads/
|
||||
wp-content/blogs.dir/
|
||||
wp-content/upgrade/
|
||||
wp-content/backup-db/
|
||||
wp-content/cache/
|
||||
wp-content/backups/
|
||||
|
||||
wp-content/advanced-cache.php
|
||||
wp-content/object-cache.php
|
||||
wp-content/wp-cache-config.php
|
||||
wp-content/db.php
|
||||
|
||||
wp-admin/
|
||||
wp-includes/
|
||||
/index.php
|
||||
/license.txt
|
||||
/readme.html
|
||||
|
||||
# de_DE
|
||||
/liesmich.html
|
||||
|
||||
# it_IT
|
||||
/LEGGIMI.txt
|
||||
/licenza.html
|
||||
|
||||
# da_DK
|
||||
/licens.html
|
||||
|
||||
# es_ES, es_PE
|
||||
/licencia.txt
|
||||
|
||||
# hu_HU
|
||||
/licenc.txt
|
||||
/olvasdel.html
|
||||
|
||||
# sk_SK
|
||||
/licencia-sk_SK.txt
|
||||
|
||||
# sv_SE
|
||||
/licens-sv_SE.txt
|
||||
|
||||
/wp-activate.php
|
||||
/wp-blog-header.php
|
||||
/wp-comments-post.php
|
||||
/wp-config-sample.php
|
||||
/wp-cron.php
|
||||
/wp-links-opml.php
|
||||
/wp-load.php
|
||||
/wp-login.php
|
||||
/wp-mail.php
|
||||
/wp-settings.php
|
||||
/wp-signup.php
|
||||
/wp-trackback.php
|
||||
/xmlrpc.php
|
||||
EOF
|
||||
);
|
||||
|
||||
|
||||
class Git_Wrapper {
|
||||
|
||||
private $last_error = '';
|
||||
private $gitignore = GITIGNORE;
|
||||
|
||||
function __construct( $repo_dir ) {
|
||||
$this->repo_dir = $repo_dir;
|
||||
$this->private_key = '';
|
||||
}
|
||||
|
||||
function _rrmdir( $dir ) {
|
||||
if ( empty( $dir ) || ! is_dir( $dir ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$files = array_diff( scandir( $dir ), array( '.', '..' ) );
|
||||
foreach ( $files as $file ) {
|
||||
$filepath = realpath("$dir/$file");
|
||||
( is_dir( $filepath ) ) ? $this->_rrmdir( $filepath ) : unlink( $filepath );
|
||||
}
|
||||
return rmdir( $dir );
|
||||
}
|
||||
|
||||
function _log(...$args) {
|
||||
if ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) { return; }
|
||||
|
||||
$output = '';
|
||||
if (isset($args) && $args) foreach ( $args as $arg ) {
|
||||
$output .= var_export($arg, true).'/n/n';
|
||||
}
|
||||
|
||||
if ($output) error_log($output);
|
||||
}
|
||||
|
||||
function _git_temp_key_file() {
|
||||
$key_file = tempnam( sys_get_temp_dir(), 'ssh-git' );
|
||||
return $key_file;
|
||||
}
|
||||
|
||||
function set_key( $private_key ) {
|
||||
$this->private_key = $private_key;
|
||||
}
|
||||
|
||||
private function get_env() {
|
||||
$env = array();
|
||||
$key_file = null;
|
||||
|
||||
if ( defined( 'GIT_SSH' ) && GIT_SSH ) {
|
||||
$env['GIT_SSH'] = GIT_SSH;
|
||||
} else {
|
||||
$env['GIT_SSH'] = dirname( __FILE__ ) . '/ssh-git';
|
||||
}
|
||||
|
||||
if ( defined( 'GIT_KEY_FILE' ) && GIT_KEY_FILE ) {
|
||||
$env['GIT_KEY_FILE'] = GIT_KEY_FILE;
|
||||
} elseif ( $this->private_key ) {
|
||||
$key_file = $this->_git_temp_key_file();
|
||||
chmod( $key_file, 0600 );
|
||||
file_put_contents( $key_file, $this->private_key );
|
||||
$env['GIT_KEY_FILE'] = $key_file;
|
||||
}
|
||||
|
||||
return $env;
|
||||
}
|
||||
|
||||
protected function _call(...$args) {
|
||||
$args = join( ' ', array_map( 'escapeshellarg', $args ) );
|
||||
$cmd = "git $args 2>&1";
|
||||
$return = -1;
|
||||
$response = array();
|
||||
$env = $this->get_env();
|
||||
|
||||
$proc = proc_open(
|
||||
$cmd,
|
||||
array(
|
||||
0 => array( 'pipe', 'r' ), // stdin
|
||||
1 => array( 'pipe', 'w' ), // stdout
|
||||
),
|
||||
$pipes,
|
||||
$this->repo_dir,
|
||||
$env
|
||||
);
|
||||
if ( is_resource( $proc ) ) {
|
||||
fclose( $pipes[0] );
|
||||
while ( $line = fgets( $pipes[1] ) ) {
|
||||
$response[] = rtrim( $line, "\n\r" );
|
||||
}
|
||||
$return = (int)proc_close( $proc );
|
||||
}
|
||||
$this->_log( "$return $cmd", join( "\n", $response ) );
|
||||
if ( ! defined( 'GIT_KEY_FILE' ) && isset( $env['GIT_KEY_FILE'] ) ) {
|
||||
unlink( $env['GIT_KEY_FILE'] );
|
||||
}
|
||||
if ( 0 != $return ) {
|
||||
$this->last_error = join( "\n", $response );
|
||||
} else {
|
||||
$this->last_error = null;
|
||||
}
|
||||
return array( $return, $response );
|
||||
}
|
||||
|
||||
function get_last_error() {
|
||||
return $this->last_error;
|
||||
}
|
||||
|
||||
function can_exec_git() {
|
||||
list( $return, ) = $this->_call( 'version' );
|
||||
return ( 0 == $return );
|
||||
}
|
||||
|
||||
function is_status_working() {
|
||||
list( $return, ) = $this->_call( 'status', '-s' );
|
||||
return ( 0 == $return );
|
||||
}
|
||||
|
||||
function get_version() {
|
||||
list( $return, $version ) = $this->_call( 'version' );
|
||||
if ( 0 != $return ) { return ''; }
|
||||
if ( ! empty( $version[0] ) ) {
|
||||
return substr( $version[0], 12 );
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
// git rev-list @{u}..
|
||||
function get_ahead_commits() {
|
||||
list( , $commits ) = $this->_call( 'rev-list', '@{u}..' );
|
||||
return $commits;
|
||||
}
|
||||
|
||||
// git rev-list ..@{u}
|
||||
function get_behind_commits() {
|
||||
list( , $commits ) = $this->_call( 'rev-list', '..@{u}' );
|
||||
return $commits;
|
||||
}
|
||||
|
||||
function init() {
|
||||
file_put_contents( "$this->repo_dir/.gitignore", $this->gitignore );
|
||||
list( $return, ) = $this->_call( 'init' );
|
||||
$this->_call( 'config', 'user.email', 'gitium@presslabs.com' );
|
||||
$this->_call( 'config', 'user.name', 'Gitium' );
|
||||
$this->_call( 'config', 'push.default', 'matching' );
|
||||
return ( 0 == $return );
|
||||
}
|
||||
|
||||
function is_dot_git_dir( $dir ) {
|
||||
$realpath = realpath( $dir );
|
||||
$git_config = realpath( $realpath . '/config' );
|
||||
$git_index = realpath( $realpath . '/index' );
|
||||
if ( ! empty( $realpath ) && is_dir( $realpath ) && file_exists( $git_config ) && file_exists( $git_index ) ) {
|
||||
return True;
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
$dot_git_dir = realpath( $this->repo_dir . '/.git' );
|
||||
if ( $this->is_dot_git_dir( $dot_git_dir ) && $this->_rrmdir( $dot_git_dir ) ) {
|
||||
if ( WP_DEBUG ) {
|
||||
error_log( "Gitium cleanup successfull. Removed '$dot_git_dir'." );
|
||||
}
|
||||
return True;
|
||||
}
|
||||
if ( WP_DEBUG ) {
|
||||
error_log( "Gitium cleanup failed. '$dot_git_dir' is not a .git dir." );
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
function add_remote_url( $url ) {
|
||||
list( $return, ) = $this->_call( 'remote', 'add', 'origin', $url );
|
||||
return ( 0 == $return );
|
||||
}
|
||||
|
||||
function get_remote_url() {
|
||||
list( , $response ) = $this->_call( 'config', '--get', 'remote.origin.url' );
|
||||
if ( isset( $response[0] ) ) {
|
||||
return $response[0];
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function remove_remote() {
|
||||
list( $return, ) = $this->_call( 'remote', 'rm', 'origin');
|
||||
return ( 0 == $return );
|
||||
}
|
||||
|
||||
function get_remote_tracking_branch() {
|
||||
list( $return, $response ) = $this->_call( 'rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{u}' );
|
||||
if ( 0 == $return ) {
|
||||
return $response[0];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function get_local_branch() {
|
||||
list( $return, $response ) = $this->_call( 'rev-parse', '--abbrev-ref', 'HEAD' );
|
||||
if ( 0 == $return ) {
|
||||
return $response[0];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function fetch_ref() {
|
||||
list( $return, ) = $this->_call( 'fetch', 'origin' );
|
||||
return ( 0 == $return );
|
||||
}
|
||||
|
||||
protected function _resolve_merge_conflicts( $message ) {
|
||||
list( , $changes ) = $this->status( true );
|
||||
$this->_log( $changes );
|
||||
foreach ( $changes as $path => $change ) {
|
||||
if ( in_array( $change, array( 'UD', 'DD' ) ) ) {
|
||||
$this->_call( 'rm', $path );
|
||||
$message .= "\n\tConflict: $path [removed]";
|
||||
} elseif ( 'DU' == $change ) {
|
||||
$this->_call( 'add', $path );
|
||||
$message .= "\n\tConflict: $path [added]";
|
||||
} elseif ( in_array( $change, array( 'AA', 'UU', 'AU', 'UA' ) ) ) {
|
||||
$this->_call( 'checkout', '--theirs', $path );
|
||||
$this->_call( 'add', '--all', $path );
|
||||
$message .= "\n\tConflict: $path [local version]";
|
||||
}
|
||||
}
|
||||
$this->commit( $message );
|
||||
}
|
||||
|
||||
function get_commit_message( $commit ) {
|
||||
list( $return, $response ) = $this->_call( 'log', '--format=%B', '-n', '1', $commit );
|
||||
return ( $return !== 0 ? false : join( "\n", $response ) );
|
||||
}
|
||||
|
||||
private function strpos_haystack_array( $haystack, $needle, $offset=0 ) {
|
||||
if ( ! is_array( $haystack ) ) { $haystack = array( $haystack ); }
|
||||
|
||||
foreach ( $haystack as $query ) {
|
||||
if ( strpos( $query, $needle, $offset) !== false ) { return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private function cherry_pick( $commits ) {
|
||||
foreach ( $commits as $commit ) {
|
||||
if ( empty( $commit ) ) { return false; }
|
||||
|
||||
list( $return, $response ) = $this->_call( 'cherry-pick', $commit );
|
||||
|
||||
// abort the cherry-pick if the changes are already pushed
|
||||
if ( false !== $this->strpos_haystack_array( $response, 'previous cherry-pick is now empty' ) ) {
|
||||
$this->_call( 'cherry-pick', '--abort' );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $return != 0 ) {
|
||||
$this->_resolve_merge_conflicts( $this->get_commit_message( $commit ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function merge_with_accept_mine(...$commits) {
|
||||
do_action( 'gitium_before_merge_with_accept_mine' );
|
||||
|
||||
if ( 1 == count($commits) && is_array( $commits[0] ) ) {
|
||||
$commits = $commits[0];
|
||||
}
|
||||
|
||||
// get ahead commits
|
||||
$ahead_commits = $this->get_ahead_commits();
|
||||
|
||||
// combine all commits with the ahead commits
|
||||
$commits = array_unique( array_merge( array_reverse( $commits ), $ahead_commits ) );
|
||||
$commits = array_reverse( $commits );
|
||||
|
||||
// get the remote branch
|
||||
$remote_branch = $this->get_remote_tracking_branch();
|
||||
|
||||
// get the local branch
|
||||
$local_branch = $this->get_local_branch();
|
||||
|
||||
// rename the local branch to 'merge_local'
|
||||
$this->_call( 'branch', '-m', 'merge_local' );
|
||||
|
||||
// local branch set up to track remote branch
|
||||
$this->_call( 'branch', $local_branch, $remote_branch );
|
||||
|
||||
// checkout to the $local_branch
|
||||
list( $return, ) = $this->_call( 'checkout', $local_branch );
|
||||
if ( $return != 0 ) {
|
||||
$this->_call( 'branch', '-M', $local_branch );
|
||||
return false;
|
||||
}
|
||||
|
||||
// don't cherry pick if there are no commits
|
||||
if ( count( $commits ) > 0 ) {
|
||||
$this->cherry_pick( $commits );
|
||||
}
|
||||
|
||||
if ( $this->successfully_merged() ) { // git status without states: AA, DD, UA, AU ...
|
||||
// delete the 'merge_local' branch
|
||||
$this->_call( 'branch', '-D', 'merge_local' );
|
||||
return true;
|
||||
} else {
|
||||
$this->_call( 'cherry-pick', '--abort' );
|
||||
$this->_call( 'checkout', '-b', 'merge_local' );
|
||||
$this->_call( 'branch', '-M', $local_branch );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function successfully_merged() {
|
||||
list( , $response ) = $this->status( true );
|
||||
$changes = array_values( $response );
|
||||
return ( 0 == count( array_intersect( $changes, array( 'DD', 'AU', 'UD', 'UA', 'DU', 'AA', 'UU' ) ) ) );
|
||||
}
|
||||
|
||||
function merge_initial_commit( $commit, $branch ) {
|
||||
list( $return, ) = $this->_call( 'branch', '-m', 'initial' );
|
||||
if ( 0 != $return ) {
|
||||
return false;
|
||||
}
|
||||
list( $return, ) = $this->_call( 'checkout', $branch );
|
||||
if ( 0 != $return ) {
|
||||
return false;
|
||||
}
|
||||
list( $return, ) = $this->_call(
|
||||
'cherry-pick', '--strategy', 'recursive', '--strategy-option', 'theirs', $commit
|
||||
);
|
||||
if ( $return != 0 ) {
|
||||
$this->_resolve_merge_conflicts( $this->get_commit_message( $commit ) );
|
||||
if ( ! $this->successfully_merged() ) {
|
||||
$this->_call( 'cherry-pick', '--abort' );
|
||||
$this->_call( 'checkout', 'initial' );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$this->_call( 'branch', '-D', 'initial' );
|
||||
return true;
|
||||
}
|
||||
|
||||
function get_remote_branches() {
|
||||
list( , $response ) = $this->_call( 'branch', '-r' );
|
||||
$response = array_map( 'trim', $response );
|
||||
$response = array_map( create_function( '$b', 'return str_replace("origin/","",$b);' ), $response );
|
||||
return $response;
|
||||
}
|
||||
|
||||
function add(...$args) {
|
||||
if ( 1 == count($args) && is_array( $args[0] ) ) {
|
||||
$args = $args[0];
|
||||
}
|
||||
$params = array_merge( array( 'add', '-n', '--all' ), $args );
|
||||
list ( , $response ) = call_user_func_array( array( $this, '_call' ), $params );
|
||||
$count = count( $response );
|
||||
|
||||
$params = array_merge( array( 'add', '--all' ), $args );
|
||||
list ( , $response ) = call_user_func_array( array( $this, '_call' ), $params );
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
function commit( $message, $author_name = '', $author_email = '' ) {
|
||||
$author = '';
|
||||
if ( $author_email ) {
|
||||
if ( empty( $author_name ) ) {
|
||||
$author_name = $author_email;
|
||||
}
|
||||
$author = "$author_name <$author_email>";
|
||||
}
|
||||
|
||||
if ( ! empty( $author ) ) {
|
||||
list( $return, $response ) = $this->_call( 'commit', '-m', $message, '--author', $author );
|
||||
} else {
|
||||
list( $return, $response ) = $this->_call( 'commit', '-m', $message );
|
||||
}
|
||||
if ( $return !== 0 ) { return false; }
|
||||
|
||||
list( $return, $response ) = $this->_call( 'rev-parse', 'HEAD' );
|
||||
|
||||
return ( $return === 0 ) ? $response[0] : false;
|
||||
}
|
||||
|
||||
function push( $branch = '' ) {
|
||||
if ( ! empty( $branch ) ) {
|
||||
list( $return, ) = $this->_call( 'push', '--porcelain', '-u', 'origin', $branch );
|
||||
} else {
|
||||
list( $return, ) = $this->_call( 'push', '--porcelain', '-u', 'origin', 'HEAD' );
|
||||
}
|
||||
return ( $return == 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Get uncommited changes with status porcelain
|
||||
* git status --porcelain
|
||||
* It returns an array like this:
|
||||
array(
|
||||
file => deleted|modified
|
||||
...
|
||||
)
|
||||
*/
|
||||
function get_local_changes() {
|
||||
list( $return, $response ) = $this->_call( 'status', '--porcelain' );
|
||||
|
||||
if ( 0 !== $return ) {
|
||||
return array();
|
||||
}
|
||||
$new_response = array();
|
||||
if ( ! empty( $response ) ) {
|
||||
foreach ( $response as $line ) :
|
||||
$work_tree_status = substr( $line, 1, 1 );
|
||||
$path = substr( $line, 3 );
|
||||
|
||||
if ( ( '"' == $path[0] ) && ('"' == $path[strlen( $path ) - 1] ) ) {
|
||||
// git status --porcelain will put quotes around paths with whitespaces
|
||||
// we don't want the quotes, let's get rid of them
|
||||
$path = substr( $path, 1, strlen( $path ) - 2 );
|
||||
}
|
||||
|
||||
if ( 'D' == $work_tree_status ) {
|
||||
$action = 'deleted';
|
||||
} else {
|
||||
$action = 'modified';
|
||||
}
|
||||
$new_response[ $path ] = $action;
|
||||
endforeach;
|
||||
}
|
||||
return $new_response;
|
||||
}
|
||||
|
||||
function get_uncommited_changes() {
|
||||
list( , $changes ) = $this->status();
|
||||
return $changes;
|
||||
}
|
||||
|
||||
function local_status() {
|
||||
list( $return, $response ) = $this->_call( 'status', '-s', '-b', '-u' );
|
||||
if ( 0 !== $return ) {
|
||||
return array( '', array() );
|
||||
}
|
||||
|
||||
$new_response = array();
|
||||
if ( ! empty( $response ) ) {
|
||||
$branch_status = array_shift( $response );
|
||||
foreach ( $response as $idx => $line ) :
|
||||
unset( $index_status, $work_tree_status, $path, $new_path, $old_path );
|
||||
|
||||
if ( empty( $line ) ) { continue; } // ignore empty lines like the last item
|
||||
if ( '#' == $line[0] ) { continue; } // ignore branch status
|
||||
|
||||
$index_status = substr( $line, 0, 1 );
|
||||
$work_tree_status = substr( $line, 1, 1 );
|
||||
$path = substr( $line, 3 );
|
||||
|
||||
$old_path = '';
|
||||
$new_path = explode( '->', $path );
|
||||
if ( ( 'R' === $index_status ) && ( ! empty( $new_path[1] ) ) ) {
|
||||
$old_path = trim( $new_path[0] );
|
||||
$path = trim( $new_path[1] );
|
||||
}
|
||||
$new_response[ $path ] = trim( $index_status . $work_tree_status . ' ' . $old_path );
|
||||
endforeach;
|
||||
}
|
||||
|
||||
return array( $branch_status, $new_response );
|
||||
}
|
||||
|
||||
function status( $local_only = false ) {
|
||||
list( $branch_status, $new_response ) = $this->local_status();
|
||||
|
||||
if ( $local_only ) { return array( $branch_status, $new_response ); }
|
||||
|
||||
$behind_count = 0;
|
||||
$ahead_count = 0;
|
||||
if ( preg_match( '/## ([^.]+)\.+([^ ]+)/', $branch_status, $matches ) ) {
|
||||
$local_branch = $matches[1];
|
||||
$remote_branch = $matches[2];
|
||||
|
||||
list( , $response ) = $this->_call( 'rev-list', "$local_branch..$remote_branch", '--count' );
|
||||
$behind_count = (int)$response[0];
|
||||
|
||||
list( , $response ) = $this->_call( 'rev-list', "$remote_branch..$local_branch", '--count' );
|
||||
$ahead_count = (int)$response[0];
|
||||
}
|
||||
|
||||
if ( $behind_count ) {
|
||||
list( , $response ) = $this->_call( 'diff', '-z', '--name-status', "$local_branch~$ahead_count", $remote_branch );
|
||||
$response = explode( chr( 0 ), $response[0] );
|
||||
array_pop( $response );
|
||||
for ( $idx = 0 ; $idx < count( $response ) / 2 ; $idx++ ) {
|
||||
$file = $response[ $idx * 2 + 1 ];
|
||||
$change = $response[ $idx * 2 ];
|
||||
if ( ! isset( $new_response[ $file ] ) ) {
|
||||
$new_response[ $file ] = "r$change";
|
||||
}
|
||||
}
|
||||
}
|
||||
return array( $branch_status, $new_response );
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if repo has uncommited changes
|
||||
* git status --porcelain
|
||||
*/
|
||||
function is_dirty() {
|
||||
$changes = $this->get_uncommited_changes();
|
||||
return ! empty( $changes );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the last n commits
|
||||
*/
|
||||
function get_last_commits( $n = 20 ) {
|
||||
list( $return, $message ) = $this->_call( 'log', '-n', $n, '--pretty=format:%s' );
|
||||
if ( 0 !== $return ) { return false; }
|
||||
|
||||
list( $return, $response ) = $this->_call( 'log', '-n', $n, '--pretty=format:%h|%an|%ae|%ad|%cn|%ce|%cd' );
|
||||
if ( 0 !== $return ) { return false; }
|
||||
|
||||
foreach ( $response as $index => $value ) {
|
||||
$commit_info = explode( '|', $value );
|
||||
$commits[ $commit_info[0] ] = array(
|
||||
'subject' => $message[ $index ],
|
||||
'author_name' => $commit_info[1],
|
||||
'author_email' => $commit_info[2],
|
||||
'author_date' => $commit_info[3],
|
||||
);
|
||||
if ( $commit_info[1] != $commit_info[4] && $commit_info[2] != $commit_info[5] ) {
|
||||
$commits[ $commit_info[0] ]['committer_name'] = $commit_info[4];
|
||||
$commits[ $commit_info[0] ]['committer_email'] = $commit_info[5];
|
||||
$commits[ $commit_info[0] ]['committer_date'] = $commit_info[6];
|
||||
}
|
||||
}
|
||||
return $commits;
|
||||
}
|
||||
|
||||
public function set_gitignore( $content ) {
|
||||
file_put_contents( $this->repo_dir . '/.gitignore', $content );
|
||||
return true;
|
||||
}
|
||||
|
||||
public function get_gitignore() {
|
||||
return file_get_contents( $this->repo_dir . '/.gitignore' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove files in .gitignore from version control
|
||||
*/
|
||||
function rm_cached( $path ) {
|
||||
list( $return, ) = $this->_call( 'rm', '--cached', $path );
|
||||
return ( $return == 0 );
|
||||
}
|
||||
|
||||
function remove_wp_content_from_version_control() {
|
||||
$process = proc_open(
|
||||
'rm -rf ' . ABSPATH . '/wp-content/.git',
|
||||
array(
|
||||
0 => array( 'pipe', 'r' ), // stdin
|
||||
1 => array( 'pipe', 'w' ), // stdout
|
||||
),
|
||||
$pipes
|
||||
);
|
||||
if ( is_resource( $process ) ) {
|
||||
fclose( $pipes[0] );
|
||||
proc_close( $process );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! defined( 'GIT_DIR' ) ) {
|
||||
define( 'GIT_DIR', dirname( WP_CONTENT_DIR ) );
|
||||
}
|
||||
|
||||
# global is needed here for wp-cli as it includes/exec files inside a function scope
|
||||
# this forces the context to really be global :\.
|
||||
global $git;
|
||||
$git = new Git_Wrapper( GIT_DIR );
|
53
wp-content/plugins/gitium/inc/class-gitium-admin.php
Normal file
53
wp-content/plugins/gitium/inc/class-gitium-admin.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/* Copyright 2014-2016 Presslabs SRL <ping@presslabs.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2, as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
class Gitium_Admin {
|
||||
|
||||
public function __construct() {
|
||||
global $git;
|
||||
|
||||
list( , $git_private_key ) = gitium_get_keypair();
|
||||
$git->set_key( $git_private_key );
|
||||
|
||||
if ( current_user_can( GITIUM_MANAGE_OPTIONS_CAPABILITY ) ) {
|
||||
$req = new Gitium_Requirements();
|
||||
if ( ! $req->get_status() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $this->has_configuration() ) {
|
||||
new Gitium_Submenu_Status();
|
||||
new Gitium_Submenu_Commits();
|
||||
new Gitium_Submenu_Settings();
|
||||
new Gitium_Menu_Bubble();
|
||||
} else {
|
||||
new Gitium_Submenu_Configure();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function has_configuration() {
|
||||
return _gitium_is_status_working() && _gitium_get_remote_tracking_branch();
|
||||
}
|
||||
}
|
||||
|
||||
if ( ( is_admin() && ! is_multisite() ) || ( is_network_admin() && is_multisite() ) ) {
|
||||
add_action( 'init', 'gitium_admin_page' );
|
||||
function gitium_admin_page() {
|
||||
new Gitium_Admin();
|
||||
}
|
||||
}
|
107
wp-content/plugins/gitium/inc/class-gitium-help.php
Normal file
107
wp-content/plugins/gitium/inc/class-gitium-help.php
Normal file
@ -0,0 +1,107 @@
|
||||
<?php
|
||||
/* Copyright 2014-2016 Presslabs SRL <ping@presslabs.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2, as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
class Gitium_Help {
|
||||
|
||||
public function __construct( $hook, $help = 'gitium' ) {
|
||||
add_action( "load-{$hook}", array( $this, $help ), 20 );
|
||||
}
|
||||
|
||||
private function general() {
|
||||
$screen = get_current_screen();
|
||||
$screen->add_help_tab( array( 'id' => 'gitium', 'title' => __( 'Gitium', 'gitium' ), 'callback' => array( $this, 'gitium' ) ) );
|
||||
$screen->add_help_tab( array( 'id' => 'faq', 'title' => __( 'F.A.Q.', 'gitium' ), 'callback' => array( $this, 'faq' ) ) );
|
||||
$screen->add_help_tab( array( 'id' => 'requirements', 'title' => __( 'Requirements', 'gitium' ), 'callback' => array( $this, 'requirements_callback' ) ) );
|
||||
$screen->set_help_sidebar( '<div style="width:auto; height:auto; float:right; padding-right:28px; padding-top:15px"><img src="' . plugins_url( 'img/gitium.svg', dirname( __FILE__ ) ) . '" width="96"></div>' );
|
||||
}
|
||||
|
||||
public function gitium() {
|
||||
echo '<p>' . __( 'Gitium enables continuous deployment for WordPress integrating with tools such as Github, Bitbucket or Travis-CI. Plugin and theme updates, installs and removals are automatically versioned.', 'gitium' ) . '</p>';
|
||||
echo '<p>' . __( 'Ninja code edits from the WordPress editor are also tracked into version control. Gitium is designed for sane development environments.', 'gitium' ) . '</p>';
|
||||
echo '<p>' . __( 'Staging and production can follow different branches of the same repository. You can deploy code simply trough git push.', 'gitium' ) . '</p>';
|
||||
echo '<p>' . __( 'Gitium requires <code>git</code> command line tool minimum version 1.7 installed on the server and <code>proc_open</code> PHP function enabled.', 'gitium' ) . '</p>';
|
||||
}
|
||||
|
||||
public function faq() {
|
||||
echo '<p><strong>' . __( 'Could not connect to remote repository?', 'gitium' ) . '</strong><br />'. __( 'If you encounter this kind of error you can try to fix it by setting the proper username of the .git directory.', 'gitium' ) . '<br />' . __( 'Example', 'gitium' ) .': <code>chown -R www-data:www-data .git</code></p>';
|
||||
echo '<p><strong>' . __( 'Is this plugin considered stable?', 'gitium' ) . '</strong><br />'. __( 'Right now this plugin is considered alpha quality and should be used in production environments only by adventurous kinds.', 'gitium' ) . '</p>';
|
||||
echo '<p><strong>' . __( 'What happens in case of conflicts?', 'gitium' ) . '</strong><br />'. __( 'The behavior in case of conflicts is to overwrite the changes on the origin repository with the local changes (ie. local modifications take precedence over remote ones).', 'gitium' ) . '</p>';
|
||||
echo '<p><strong>' . __( 'How to deploy automatically after a push?', 'gitium' ) . '</strong><br />'. __( 'You can ping the webhook url after a push to automatically deploy the new code. The webhook url can be found under Code menu. This url plays well with Github or Bitbucket webhooks.', 'gitium' ) . '</p>';
|
||||
echo '<p><strong>' . __( 'Does it works on multi site setups?', 'gitium' ) . '</strong><br />'. __( 'Gitium is not supporting multisite setups at the moment.', 'gitium' ) . '</p>';
|
||||
echo '<p><strong>' . __( 'How does gitium handle submodules?', 'gitium' ) . '</strong><br />'. __( 'Currently submodules are not supported.', 'gitium' ) . '</p>';
|
||||
}
|
||||
|
||||
public function requirements_callback() {
|
||||
echo '<p>' . __( 'Gitium requires:', 'gitium' ) . '</p>';
|
||||
echo '<p>' . __( 'the function proc_open available', 'gitium' ) . '</p>';
|
||||
echo '<p>' . __( 'can exec the file inc/ssh-git', 'gitium' ) . '</p>';
|
||||
|
||||
printf( '<p>' . __( 'git version >= %s', 'gitium' ) . '</p>', GITIUM_MIN_GIT_VER );
|
||||
printf( '<p>' . __( 'PHP version >= %s', 'gitium' ) . '</p>', GITIUM_MIN_PHP_VER );
|
||||
}
|
||||
|
||||
public function configuration() {
|
||||
$screen = get_current_screen();
|
||||
$screen->add_help_tab( array( 'id' => 'configuration', 'title' => __( 'Configuration', 'gitium' ), 'callback' => array( $this, 'configuration_callback' ) ) );
|
||||
$this->general();
|
||||
}
|
||||
|
||||
public function configuration_callback() {
|
||||
echo '<p><strong>' . __( 'Configuration step 1', 'gitium' ) . '</strong><br />' . __( 'In this step you must specify the <code>Remote URL</code>. This URL represents the link between the git sistem and your site.', 'gitium' ) . '</p>';
|
||||
echo '<p>' . __( 'You can get this URL from your Git repository and it looks like this:', 'gitium' ) . '</p>';
|
||||
echo '<p>' . __( 'github.com -> git@github.com:user/example.git', 'gitium' ) . '</p>';
|
||||
echo '<p>' . __( 'bitbucket.org -> git@bitbucket.org:user/glowing-happiness.git', 'gitium' ) . '</p>';
|
||||
echo '<p>' . __( 'To go to the next step, fill the <code>Remote URL</code> and then press the <code>Fetch</code> button.', 'gitium' ) . '</p>';
|
||||
echo '<p><strong>' . __( 'Configuration step 2', 'gitium' ) . '</strong><br />' . __( 'In this step you must select the <code>branch</code> you want to follow.', 'gitium' ) . '</p>';
|
||||
echo '<p>' . __( 'Only this branch will have all of your code modifications.', 'gitium' ) . '</p>';
|
||||
echo '<p>' . __( 'When you push the button <code>Merge & Push</code>, all code(plugins & themes) will be pushed on the git repository.', 'gitium' ) . '</p>';
|
||||
}
|
||||
|
||||
public function status() {
|
||||
$screen = get_current_screen();
|
||||
$screen->add_help_tab( array( 'id' => 'status', 'title' => __( 'Status', 'gitium' ), 'callback' => array( $this, 'status_callback' ) ) );
|
||||
$this->general();
|
||||
}
|
||||
|
||||
public function status_callback() {
|
||||
echo '<p>' . __( 'On status page you can see what files are modified, and you can commit the changes to git.', 'gitium' ) . '</p>';
|
||||
}
|
||||
|
||||
public function commits() {
|
||||
$screen = get_current_screen();
|
||||
$screen->add_help_tab( array( 'id' => 'commits', 'title' => __( 'Commits', 'gitium' ), 'callback' => array( $this, 'commits_callback' ) ) );
|
||||
$this->general();
|
||||
}
|
||||
|
||||
public function commits_callback() {
|
||||
echo '<p>' . __( 'You may be wondering what is the difference between author and committer.', 'gitium' ) . '</p>';
|
||||
echo '<p>' . __( 'The <code>author</code> is the person who originally wrote the patch, whereas the <code>committer</code> is the person who last applied the patch.', 'gitium' ) . '</p>';
|
||||
echo '<p>' . __( 'So, if you send in a patch to a project and one of the core members applies the patch, both of you get credit — you as the author and the core member as the committer.', 'gitium' ) . '</p>';
|
||||
}
|
||||
|
||||
public function settings() {
|
||||
$screen = get_current_screen();
|
||||
$screen->add_help_tab( array( 'id' => 'settings', 'title' => __( 'Settings', 'gitium' ), 'callback' => array( $this, 'settings_callback' ) ) );
|
||||
$this->general();
|
||||
}
|
||||
|
||||
public function settings_callback() {
|
||||
echo '<p>' . __( 'Each line from the gitignore file specifies a pattern.', 'gitium' ) . '</p>';
|
||||
echo '<p>' . __( 'When deciding whether to ignore a path, Git normally checks gitignore patterns from multiple sources, with the following order of precedence, from highest to lowest (within one level of precedence, the last matching pattern decides the outcome)', 'gitium' ) . '</p>';
|
||||
echo '<p>' . sprintf( __( 'Read more on %s', 'gitium' ), '<a href="http://git-scm.com/docs/gitignore" target="_blank">git documentation</a>' ) . '</p>';
|
||||
}
|
||||
}
|
55
wp-content/plugins/gitium/inc/class-gitium-menu-bubble.php
Normal file
55
wp-content/plugins/gitium/inc/class-gitium-menu-bubble.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/* Copyright 2014-2016 Presslabs SRL <ping@presslabs.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2, as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
class Gitium_Menu_Bubble extends Gitium_Menu {
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct( $this->gitium_menu_slug, $this->gitium_menu_slug );
|
||||
add_action( GITIUM_ADMIN_MENU_ACTION, array( $this, 'add_menu_bubble' ) );
|
||||
}
|
||||
|
||||
public function add_menu_bubble() {
|
||||
global $menu;
|
||||
|
||||
if ( ! _gitium_is_status_working() ) {
|
||||
foreach ( $menu as $key => $value ) {
|
||||
if ( $this->menu_slug == $menu[ $key ][2] ) {
|
||||
$menu_bubble = get_transient( 'gitium_menu_bubble' );
|
||||
if ( false === $menu_bubble ) { $menu_bubble = ''; }
|
||||
$menu[ $key ][0] = str_replace( $menu_bubble, '', $menu[ $key ][0] );
|
||||
delete_transient( 'gitium_menu_bubble' );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list( , $changes ) = _gitium_status();
|
||||
|
||||
if ( ! empty( $changes ) ) :
|
||||
$bubble_count = count( $changes );
|
||||
foreach ( $menu as $key => $value ) {
|
||||
if ( $this->menu_slug == $menu[ $key ][2] ) {
|
||||
$menu_bubble = " <span class='update-plugins count-$bubble_count'><span class='plugin-count'>"
|
||||
. $bubble_count . '</span></span>';
|
||||
$menu[ $key ][0] .= $menu_bubble;
|
||||
set_transient( 'gitium_menu_bubble', $menu_bubble );
|
||||
return;
|
||||
}
|
||||
}
|
||||
endif;
|
||||
}
|
||||
}
|
97
wp-content/plugins/gitium/inc/class-gitium-menu.php
Normal file
97
wp-content/plugins/gitium/inc/class-gitium-menu.php
Normal file
@ -0,0 +1,97 @@
|
||||
<?php
|
||||
/* Copyright 2014-2016 Presslabs SRL <ping@presslabs.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2, as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
class Gitium_Menu {
|
||||
|
||||
public $gitium_menu_slug = 'gitium/gitium.php';
|
||||
public $commits_menu_slug = 'gitium/gitium-commits.php';
|
||||
public $settings_menu_slug = 'gitium/gitium-settings.php';
|
||||
|
||||
public $git = null;
|
||||
|
||||
public $menu_slug;
|
||||
public $submenu_slug;
|
||||
|
||||
public function __construct( $menu_slug, $submenu_slug ) {
|
||||
global $git;
|
||||
$this->git = $git;
|
||||
|
||||
$this->menu_slug = $menu_slug;
|
||||
$this->submenu_slug = $submenu_slug;
|
||||
}
|
||||
|
||||
public function redirect( $message = '', $success = false, $menu_slug = '' ) {
|
||||
$message_id = substr(
|
||||
md5( str_shuffle( 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' ) . time() ), 0, 8
|
||||
);
|
||||
if ( $message ) {
|
||||
set_transient( 'message_' . $message_id, $message, 900 );
|
||||
}
|
||||
if ( '' === $menu_slug ) { $menu_slug = $this->menu_slug; }
|
||||
$url = network_admin_url( 'admin.php?page=' . $menu_slug );
|
||||
$url = esc_url_raw( add_query_arg(
|
||||
array(
|
||||
'message' => $message_id,
|
||||
'success' => $success,
|
||||
),
|
||||
$url
|
||||
) );
|
||||
wp_safe_redirect( $url );
|
||||
exit;
|
||||
}
|
||||
|
||||
public function success_redirect( $message = '', $menu_slug = '' ) {
|
||||
$this->redirect( $message, true, $menu_slug );
|
||||
}
|
||||
|
||||
public function disconnect_repository() {
|
||||
$gitium_disconnect_repo = filter_input(INPUT_POST, 'GitiumSubmitDisconnectRepository', FILTER_SANITIZE_STRING);
|
||||
|
||||
if ( ! isset( $gitium_disconnect_repo ) ) {
|
||||
return;
|
||||
}
|
||||
check_admin_referer( 'gitium-admin' );
|
||||
gitium_uninstall_hook();
|
||||
if ( ! $this->git->remove_remote() ) {
|
||||
$this->redirect( __('Could not remove remote.', 'gitium') );
|
||||
}
|
||||
$this->success_redirect( __('You are now disconnected from the repository. New key pair generated.', 'gitium') );
|
||||
}
|
||||
|
||||
public function show_message() {
|
||||
$get_message = filter_input(INPUT_GET, 'message', FILTER_SANITIZE_STRING);
|
||||
$get_success = filter_input(INPUT_GET, 'success', FILTER_SANITIZE_STRING);
|
||||
if ( isset( $get_message ) && $get_message ) {
|
||||
$type = ( isset( $get_success ) && $get_success == 1 ) ? 'updated' : 'error';
|
||||
$message = get_transient( 'message_'. $get_message );
|
||||
if ( $message ) : ?>
|
||||
<div class="<?php echo esc_attr( $type ); ?>"><p><?php echo esc_html( $message ); ?></p></div>
|
||||
<?php endif;
|
||||
}
|
||||
}
|
||||
|
||||
protected function show_disconnect_repository_button() {
|
||||
?>
|
||||
<form name="gitium_form_disconnect" id="gitium_form_disconnect" action="" method="POST">
|
||||
<?php
|
||||
wp_nonce_field( 'gitium-admin' );
|
||||
?>
|
||||
<input type="submit" name="GitiumSubmitDisconnectRepository" value='<?php _e( 'Disconnect from repo', 'gitium' ); ?>' class="button secondary" onclick="return confirm('<?php _e( 'Are you sure you want to disconnect from the remote repository?', 'gitium' ); ?>')"/>
|
||||
</form>
|
||||
<?php
|
||||
}
|
||||
}
|
117
wp-content/plugins/gitium/inc/class-gitium-requirements.php
Normal file
117
wp-content/plugins/gitium/inc/class-gitium-requirements.php
Normal file
@ -0,0 +1,117 @@
|
||||
<?php
|
||||
/* Copyright 2014-2016 Presslabs SRL <ping@presslabs.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2, as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
class Gitium_Requirements {
|
||||
|
||||
private $req = array();
|
||||
private $msg = array();
|
||||
|
||||
/**
|
||||
* Gitium requires:
|
||||
* git min version
|
||||
* the function proc_open available
|
||||
* PHP min version
|
||||
* can exec the file inc/ssh-git
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->_check_req();
|
||||
add_action( GITIUM_ADMIN_NOTICES_ACTION, array( $this, 'admin_notices' ) );
|
||||
}
|
||||
|
||||
private function _check_req() {
|
||||
list($this->req['is_git_version'], $this->msg['is_git_version'] ) = $this->is_git_version();
|
||||
list($this->req['is_proc_open'], $this->msg['is_proc_open'] ) = $this->is_proc_open();
|
||||
list($this->req['is_php_verion'], $this->msg['is_php_verion'] ) = $this->is_php_version();
|
||||
list($this->req['can_exec_ssh_git_file'],$this->msg['can_exec_ssh_git_file']) = $this->can_exec_ssh_git_file();
|
||||
|
||||
return $this->req;
|
||||
}
|
||||
|
||||
public function admin_notices() {
|
||||
if ( ! current_user_can( GITIUM_MANAGE_OPTIONS_CAPABILITY ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( $this->req as $key => $value ) {
|
||||
if ( false === $value ) {
|
||||
echo "<div class='error-nag error'><p>Gitium Requirement: {$this->msg[$key]}</p></div>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function get_status() {
|
||||
$requirements = $this->req;
|
||||
|
||||
foreach ( $requirements as $req ) :
|
||||
if ( false === $req ) :
|
||||
return false;
|
||||
endif;
|
||||
endforeach;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function is_git_version() {
|
||||
$git_version = get_transient( 'gitium_git_version' );
|
||||
|
||||
if ( GITIUM_MIN_GIT_VER > substr( $git_version, 0, 3 ) ) {
|
||||
global $git;
|
||||
$git_version = $git->get_version();
|
||||
set_transient( 'gitium_git_version', $git_version );
|
||||
if ( empty( $git_version ) ) {
|
||||
return array( false, 'There is no git installed on this server.' );
|
||||
} else if ( GITIUM_MIN_GIT_VER > substr( $git_version, 0, 3 ) ) {
|
||||
return array( false, "The git version is `$git_version` and must be greater than `" . GITIUM_MIN_GIT_VER . "`!" );
|
||||
}
|
||||
}
|
||||
|
||||
return array( true, "The git version is `$git_version`." );
|
||||
}
|
||||
|
||||
private function is_proc_open() {
|
||||
if ( ! function_exists( 'proc_open' ) ) {
|
||||
return array( false, 'The function `proc_open` is disabled!' );
|
||||
} else {
|
||||
return array( true, 'The function `proc_open` is enabled!' );
|
||||
}
|
||||
}
|
||||
|
||||
private function is_php_version() {
|
||||
if ( ! function_exists( 'phpversion' ) ) {
|
||||
return array( false, 'The function `phpversion` is disabled!' );
|
||||
} else {
|
||||
$php_version = phpversion();
|
||||
if ( GITIUM_MIN_PHP_VER <= substr( $php_version, 0, 3 ) ) {
|
||||
return array( true, "The PHP version is `$php_version`." );
|
||||
} else {
|
||||
return array( false, "The PHP version is `$php_version` and is not greater or equal to " . GITIUM_MIN_PHP_VER );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function can_exec_ssh_git_file() {
|
||||
$filepath = dirname( __FILE__ ) . '/ssh-git';
|
||||
|
||||
if ( ! function_exists( 'is_executable' ) ) {
|
||||
return array( false, 'The function `is_executable` is disabled!' );
|
||||
} else if ( is_executable( $filepath ) ) {
|
||||
return array( true, "The `$filepath` file can be executed!" );
|
||||
} else {
|
||||
return array( false, "The `$filepath` file is not executable" );
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
<?php
|
||||
/* Copyright 2014-2016 Presslabs SRL <ping@presslabs.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2, as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
class Gitium_Submenu_Commits extends Gitium_Menu {
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct( $this->gitium_menu_slug, $this->commits_menu_slug );
|
||||
add_action( GITIUM_ADMIN_MENU_ACTION, array( $this, 'admin_menu' ) );
|
||||
}
|
||||
|
||||
public function admin_menu() {
|
||||
$submenu_hook = add_submenu_page(
|
||||
$this->menu_slug,
|
||||
__( 'Git Commits', 'gitium' ),
|
||||
__( 'Commits', 'gitium' ),
|
||||
GITIUM_MANAGE_OPTIONS_CAPABILITY,
|
||||
$this->submenu_slug,
|
||||
array( $this, 'page' )
|
||||
);
|
||||
new Gitium_Help( $submenu_hook, 'commits' );
|
||||
}
|
||||
|
||||
public function table_head() {
|
||||
?>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col"><?php _e( 'Commits', 'gitium' ); ?></th>
|
||||
<th scope="col"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<?php
|
||||
}
|
||||
|
||||
public function table_end_row() {
|
||||
echo '</tr>';
|
||||
}
|
||||
|
||||
public function table_start_row() {
|
||||
static $counter = 0;
|
||||
$counter++;
|
||||
echo ( 0 != $counter % 2 ) ? '<tr class="active">' : '<tr class="inactive">';
|
||||
}
|
||||
|
||||
public function page() {
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h2><?php printf( __( 'Last %s commits', 'gitium' ), GITIUM_LAST_COMMITS ); ?></h2>
|
||||
<table class="wp-list-table widefat plugins">
|
||||
<?php $this->table_head(); ?>
|
||||
<tbody>
|
||||
<?php
|
||||
foreach ( $this->git->get_last_commits( GITIUM_LAST_COMMITS ) as $commit_id => $data ) {
|
||||
unset( $committer_name );
|
||||
extract( $data );
|
||||
if ( isset( $committer_name ) ) {
|
||||
$committer = "<span title='$committer_email'> -> $committer_name " . sprintf( __( 'committed %s ago', 'gitium' ), human_time_diff( strtotime( $committer_date ) ) ) . '</span>';
|
||||
$committers_avatar = '<div style="position:absolute; left:30px; border: 1px solid white; background:white; height:17px; top:30px; border-radius:2px">' . get_avatar( $committer_email, 16 ) . '</div>';
|
||||
} else {
|
||||
$committer = '';
|
||||
$committers_avatar = '';
|
||||
}
|
||||
$this->table_start_row();
|
||||
?>
|
||||
<td style="position:relative">
|
||||
<div style="float:left; width:auto; height:auto; padding-left:2px; padding-right:5px; padding-top:2px; margin-right:5px; border-radius:2px"><?php echo get_avatar( $author_email, 32 ); ?></div>
|
||||
<?php echo $committers_avatar; ?>
|
||||
<div style="float:left; width:auto; height:auto;"><strong><?php echo esc_html( $subject ); ?></strong><br />
|
||||
<span title="<?php echo esc_attr( $author_email ); ?>"><?php echo esc_html( $author_name ) . ' ' . sprintf( __( 'authored %s ago', 'gitium' ), human_time_diff( strtotime( $author_date ) ) ); ?></span><?php echo $committer; ?></div>
|
||||
</td>
|
||||
<td><p style="padding-top:8px"><?php echo $commit_id; ?></p></td>
|
||||
<?php
|
||||
$this->table_end_row();
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
253
wp-content/plugins/gitium/inc/class-gitium-submenu-configure.php
Normal file
253
wp-content/plugins/gitium/inc/class-gitium-submenu-configure.php
Normal file
@ -0,0 +1,253 @@
|
||||
<?php
|
||||
/* Copyright 2014-2016 Presslabs SRL <ping@presslabs.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2, as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
class Gitium_Submenu_Configure extends Gitium_Menu {
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct( $this->gitium_menu_slug, $this->gitium_menu_slug );
|
||||
|
||||
if ( current_user_can( GITIUM_MANAGE_OPTIONS_CAPABILITY ) ) {
|
||||
add_action( GITIUM_ADMIN_MENU_ACTION, array( $this, 'admin_menu' ) );
|
||||
add_action( 'admin_init', array( $this, 'regenerate_keypair' ) );
|
||||
add_action( 'admin_init', array( $this, 'gitium_warning' ) );
|
||||
add_action( 'admin_init', array( $this, 'init_repo' ) );
|
||||
add_action( 'admin_init', array( $this, 'choose_branch' ) );
|
||||
add_action( 'admin_init', array( $this, 'disconnect_repository' ) );
|
||||
}
|
||||
}
|
||||
|
||||
public function admin_menu() {
|
||||
add_menu_page(
|
||||
__( 'Git Configuration', 'gitium' ),
|
||||
'Gitium',
|
||||
GITIUM_MANAGE_OPTIONS_CAPABILITY,
|
||||
$this->menu_slug,
|
||||
array( $this, 'page' ),
|
||||
plugins_url( 'img/gitium.png', dirname( __FILE__ ) )
|
||||
);
|
||||
|
||||
$submenu_hook = add_submenu_page(
|
||||
$this->menu_slug,
|
||||
__( 'Git Configuration', 'gitium' ),
|
||||
__( 'Configuration', 'gitium' ),
|
||||
GITIUM_MANAGE_OPTIONS_CAPABILITY,
|
||||
$this->menu_slug,
|
||||
array( $this, 'page' )
|
||||
);
|
||||
new Gitium_Help( $submenu_hook, 'configuration' );
|
||||
}
|
||||
|
||||
public function regenerate_keypair() {
|
||||
$submit_keypair = filter_input(INPUT_POST, 'GitiumSubmitRegenerateKeypair', FILTER_SANITIZE_STRING);
|
||||
if ( ! isset( $submit_keypair ) ) {
|
||||
return;
|
||||
}
|
||||
check_admin_referer( 'gitium-admin' );
|
||||
gitium_get_keypair( true );
|
||||
$this->success_redirect( __( 'Keypair successfully regenerated.', 'gitium' ) );
|
||||
}
|
||||
|
||||
public function gitium_warning() {
|
||||
$submit_warning = filter_input(INPUT_POST, 'GitiumSubmitWarning', FILTER_SANITIZE_STRING);
|
||||
if ( ! isset( $submit_warning ) ) {
|
||||
return;
|
||||
}
|
||||
check_admin_referer( 'gitium-admin' );
|
||||
$this->git->remove_wp_content_from_version_control();
|
||||
}
|
||||
|
||||
public function init_process( $remote_url ) {
|
||||
$git = $this->git;
|
||||
$git->init();
|
||||
$git->add_remote_url( $remote_url );
|
||||
$git->fetch_ref();
|
||||
if ( count( $git->get_remote_branches() ) == 0 ) {
|
||||
$git->add( 'wp-content', '.gitignore' );
|
||||
$current_user = wp_get_current_user();
|
||||
$git->commit( __( 'Initial commit', 'gitium' ), $current_user->display_name, $current_user->user_email );
|
||||
if ( ! $git->push( 'master' ) ) {
|
||||
$git->cleanup();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function init_repo() {
|
||||
$remote_url = filter_input(INPUT_POST, 'remote_url', FILTER_SANITIZE_STRING);
|
||||
$gitium_submit_fetch = filter_input(INPUT_POST, 'GitiumSubmitFetch', FILTER_SANITIZE_STRING);
|
||||
if ( ! isset( $gitium_submit_fetch ) || ! isset( $remote_url ) ) {
|
||||
return;
|
||||
}
|
||||
check_admin_referer( 'gitium-admin' );
|
||||
|
||||
if ( empty( $remote_url ) ) {
|
||||
$this->redirect( __( 'Please specify a valid repo.', 'gitium' ) );
|
||||
}
|
||||
if ( $this->init_process( $remote_url ) ) {
|
||||
$this->success_redirect( __( 'Repository initialized successfully.', 'gitium' ) );
|
||||
} else {
|
||||
global $git;
|
||||
$this->redirect( __( 'Could not push to remote: ', 'gitium' ) . $remote_url . ' ERROR: ' . serialize( $git->get_last_error() ) );
|
||||
}
|
||||
}
|
||||
|
||||
public function choose_branch() {
|
||||
$gitium_submit_merge_push = filter_input(INPUT_POST, 'GitiumSubmitMergeAndPush', FILTER_SANITIZE_STRING);
|
||||
$tracking_branch = filter_input(INPUT_POST, 'tracking_branch', FILTER_SANITIZE_STRING);
|
||||
if ( ! isset( $gitium_submit_merge_push ) || ! isset( $tracking_branch ) ) {
|
||||
return;
|
||||
}
|
||||
check_admin_referer( 'gitium-admin' );
|
||||
$this->git->add();
|
||||
|
||||
$branch = $tracking_branch;
|
||||
set_transient( 'gitium_remote_tracking_branch', $branch );
|
||||
$current_user = wp_get_current_user();
|
||||
|
||||
$commit = $this->git->commit( __( 'Merged existing code from ', 'gitium' ) . get_home_url(), $current_user->display_name, $current_user->user_email );
|
||||
if ( ! $commit ) {
|
||||
$this->git->cleanup();
|
||||
$this->redirect( __( 'Could not create initial commit -> ', 'gitium' ) . $this->git->get_last_error() );
|
||||
}
|
||||
if ( ! $this->git->merge_initial_commit( $commit, $branch ) ) {
|
||||
$this->git->cleanup();
|
||||
$this->redirect( __( 'Could not merge the initial commit -> ', 'gitium' ) . $this->git->get_last_error() );
|
||||
}
|
||||
$this->git->push( $branch );
|
||||
$this->success_redirect( __( 'Branch selected successfully.', 'gitium' ) );
|
||||
}
|
||||
|
||||
private function setup_step_1_remote_url() {
|
||||
?>
|
||||
<tr>
|
||||
<th scope="row"><label for="remote_url"><?php _e( 'Remote URL', 'gitium' ); ?></label></th>
|
||||
<td>
|
||||
<input type="text" class="regular-text" name="remote_url" id="remote_url" placeholder="git@github.com:user/example.git" value="">
|
||||
<p class="description"><?php _e( 'This URL provide access to a Git repository via SSH, HTTPS, or Subversion.', 'gitium' ); ?><br />
|
||||
<?php _e( 'If you need to authenticate over "https://" instead of SSH use: <code>https://user:pass@github.com/user/example.git</code>', 'gitium' ); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
|
||||
private function setup_step_1_key_pair() {
|
||||
if ( ! defined( 'GIT_KEY_FILE' ) || GIT_KEY_FILE == '' ) :
|
||||
list( $git_public_key, ) = gitium_get_keypair(); ?>
|
||||
<tr>
|
||||
<th scope="row"><label for="key_pair"><?php _e( 'Key pair', 'gitium' ); ?></label></th>
|
||||
<td>
|
||||
<p>
|
||||
<input type="text" class="regular-text" name="key_pair" id="key_pair" value="<?php echo esc_attr( $git_public_key ); ?>" readonly="readonly">
|
||||
<input type="submit" name="GitiumSubmitRegenerateKeypair" class="button" value="<?php _e( 'Regenerate Key', 'gitium' ); ?>" />
|
||||
</p>
|
||||
<p class="description"><?php _e( 'If your code use ssh keybased authentication for git you need to allow write access to your repository using this key.', 'gitium' ); ?><br />
|
||||
<?php _e( 'Checkout instructions for <a href="https://help.github.com/articles/generating-ssh-keys#step-3-add-your-ssh-key-to-github" target="_blank">github</a> or <a href="https://confluence.atlassian.com/display/BITBUCKET/Add+an+SSH+key+to+an+account#AddanSSHkeytoanaccount-HowtoaddakeyusingSSHforOSXorLinux" target="_blank">bitbucket</a>.', 'gitium' ); ?>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endif;
|
||||
}
|
||||
|
||||
private function setup_warning() {
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h2><?php _e( 'Warning!', 'gitium' ); ?></h2>
|
||||
<form name="gitium_form_warning" id="gitium_form_warning" action="" method="POST">
|
||||
<?php wp_nonce_field( 'gitium-admin' ); ?>
|
||||
<p><code>wp-content</code> is already under version control. You <a onclick="document.getElementById('gitium_form_warning').submit();" style="color:red;" href="#">must remove it from version control</a> in order to continue.</p>
|
||||
<p><strong>NOTE</strong> by doing this you WILL LOSE commit history, but NOT the actual files.</p>
|
||||
<input type="hidden" name="GitiumSubmitWarning" class="button-primary" value="1" />
|
||||
</form>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
private function setup_step_1() {
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h2><?php _e( 'Configuration step 1', 'gitium' ); ?></h2>
|
||||
<p><?php _e( 'If you need help to set this up, please click on the "Help" button from the top right corner of this screen.' ); ?></p>
|
||||
<form action="" method="POST">
|
||||
<?php wp_nonce_field( 'gitium-admin' ); ?>
|
||||
<table class="form-table">
|
||||
<?php $this->setup_step_1_remote_url(); ?>
|
||||
<?php $this->setup_step_1_key_pair(); ?>
|
||||
</table>
|
||||
<p class="submit">
|
||||
<input type="submit" name="GitiumSubmitFetch" class="button-primary" value="<?php _e( 'Fetch', 'gitium' ); ?>" />
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
private function setup_step_2() {
|
||||
$git = $this->git; ?>
|
||||
<div class="wrap">
|
||||
<h2><?php _e( 'Configuration step 2', 'gitium' ); ?></h2>
|
||||
<p><?php _e( 'If you need help to set this up, please click on the "Help" button from the top right corner of this screen.' ); ?></p>
|
||||
|
||||
|
||||
<form action="" method="POST">
|
||||
<?php wp_nonce_field( 'gitium-admin' ); ?>
|
||||
|
||||
<table class="form-table">
|
||||
<tr>
|
||||
<th scope="row"><label for="tracking_branch"><?php _e( 'Choose tracking branch', 'gitium' ); ?></label></th>
|
||||
<td>
|
||||
<select name="tracking_branch" id="tracking_branch">
|
||||
<?php foreach ( $git->get_remote_branches() as $branch ) : ?>
|
||||
<option value="<?php echo esc_attr( $branch ); ?>"><?php echo esc_html( $branch ); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<p class="description"><?php _e( 'Your code origin is set to', 'gitium' ); ?> <code><?php echo esc_html( $git->get_remote_url() ); ?></code></p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p class="submit">
|
||||
<input type="submit" name="GitiumSubmitMergeAndPush" class="button-primary" value="<?php _e( 'Merge & Push', 'gitium' ); ?>" />
|
||||
</p>
|
||||
</form>
|
||||
<?php
|
||||
$this->show_disconnect_repository_button();
|
||||
?>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
public function page() {
|
||||
$this->show_message();
|
||||
|
||||
if ( wp_content_is_versioned() ) {
|
||||
return $this->setup_warning();
|
||||
}
|
||||
|
||||
if ( ! $this->git->is_status_working() || ! $this->git->get_remote_url() ) {
|
||||
return $this->setup_step_1();
|
||||
}
|
||||
|
||||
if ( ! $this->git->get_remote_tracking_branch() ) {
|
||||
return $this->setup_step_2();
|
||||
}
|
||||
|
||||
_gitium_status( true );
|
||||
gitium_update_is_status_working();
|
||||
gitium_update_remote_tracking_branch();
|
||||
}
|
||||
}
|
139
wp-content/plugins/gitium/inc/class-gitium-submenu-settings.php
Normal file
139
wp-content/plugins/gitium/inc/class-gitium-submenu-settings.php
Normal file
@ -0,0 +1,139 @@
|
||||
<?php
|
||||
/* Copyright 2014-2016 Presslabs SRL <ping@presslabs.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2, as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
class Gitium_Submenu_Settings extends Gitium_Menu {
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct( $this->gitium_menu_slug, $this->settings_menu_slug );
|
||||
add_action( GITIUM_ADMIN_MENU_ACTION, array( $this, 'admin_menu' ) );
|
||||
add_action( 'admin_init', array( $this, 'save' ) );
|
||||
add_action( 'admin_init', array( $this, 'regenerate_webhook' ) );
|
||||
add_action( 'admin_init', array( $this, 'regenerate_public_key' ) );
|
||||
}
|
||||
|
||||
public function admin_menu() {
|
||||
$submenu_hook = add_submenu_page(
|
||||
$this->menu_slug,
|
||||
'Settings',
|
||||
__( 'Settings' ),
|
||||
GITIUM_MANAGE_OPTIONS_CAPABILITY,
|
||||
$this->submenu_slug,
|
||||
array( $this, 'page' )
|
||||
);
|
||||
new Gitium_Help( $submenu_hook, 'settings' );
|
||||
}
|
||||
|
||||
public function regenerate_webhook() {
|
||||
$gitium_regen_webhook = filter_input(INPUT_POST, 'GitiumSubmitRegenerateWebhook', FILTER_SANITIZE_STRING);
|
||||
if ( ! isset( $gitium_regen_webhook ) ) {
|
||||
return;
|
||||
}
|
||||
check_admin_referer( 'gitium-settings' );
|
||||
gitium_get_webhook_key( true );
|
||||
$this->success_redirect( __( 'Webhook URL regenerates. Please make sure you update any external references.', 'gitium' ), $this->settings_menu_slug );
|
||||
}
|
||||
|
||||
public function regenerate_public_key() {
|
||||
$submit_regenerate_pub_key = filter_input(INPUT_POST, 'GitiumSubmitRegeneratePublicKey', FILTER_SANITIZE_STRING);
|
||||
if ( ! isset( $submit_regenerate_pub_key ) ) {
|
||||
return;
|
||||
}
|
||||
check_admin_referer( 'gitium-settings' );
|
||||
gitium_get_keypair( true );
|
||||
$this->success_redirect( __( 'Public key successfully regenerated.', 'gitium' ), $this->settings_menu_slug );
|
||||
}
|
||||
|
||||
private function show_webhook_table_webhook_url() {
|
||||
?>
|
||||
<tr>
|
||||
<th><label for="webhook-url"><?php _e( 'Webhook URL', 'gitium' ); ?>:</label></th>
|
||||
<td>
|
||||
<p><code id="webhook-url"><?php echo esc_url( gitium_get_webhook() ); ?></code>
|
||||
<?php if ( ! defined( 'GIT_WEBHOOK_URL' ) || GIT_WEBHOOK_URL == '' ) : ?>
|
||||
<input type="submit" name="GitiumSubmitRegenerateWebhook" class="button" value="<?php _e( 'Regenerate Webhook', 'gitium' ); ?>" />
|
||||
<a class="button" href="<?php echo esc_url( gitium_get_webhook() ); ?>" target="_blank">Merge changes</a></p>
|
||||
<?php endif; ?>
|
||||
<p class="description"><?php _e( 'Pinging this URL triggers an update from remote repository.', 'gitium' ); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
|
||||
private function show_webhook_table_public_key() {
|
||||
list( $git_public_key, ) = gitium_get_keypair();
|
||||
if ( ! defined( 'GIT_KEY_FILE' ) || GIT_KEY_FILE == '' ) : ?>
|
||||
<tr>
|
||||
<th><label for="public-key"><?php _e( 'Public Key', 'gitium' ); ?>:</label></th>
|
||||
<td>
|
||||
<p><input type="text" class="regular-text" name="public_key" id="public-key" value="<?php echo esc_attr( $git_public_key ); ?>" readonly="readonly">
|
||||
<input type="submit" name="GitiumSubmitRegeneratePublicKey" class="button" value="<?php _e( 'Regenerate Key', 'gitium' ); ?>" /></p>
|
||||
<p class="description"><?php _e( 'If your code use ssh keybased authentication for git you need to allow write access to your repository using this key.', 'gitium' ); ?><br />
|
||||
<?php _e( 'Checkout instructions for <a href="https://help.github.com/articles/generating-ssh-keys#step-3-add-your-ssh-key-to-github" target="_blank">github</a> or <a href="https://confluence.atlassian.com/display/BITBUCKET/Add+an+SSH+key+to+an+account#AddanSSHkeytoanaccount-HowtoaddakeyusingSSHforOSXorLinux" target="_blank">bitbucket</a>.', 'gitium' ); ?>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endif;
|
||||
}
|
||||
|
||||
public function show_webhook_table() {
|
||||
?>
|
||||
<table class="form-table">
|
||||
<?php $this->show_webhook_table_webhook_url() ?>
|
||||
<?php $this->show_webhook_table_public_key(); ?>
|
||||
</table>
|
||||
<?php
|
||||
}
|
||||
|
||||
public function save() {
|
||||
$submit_save = filter_input(INPUT_POST, 'GitiumSubmitSave', FILTER_SANITIZE_STRING);
|
||||
$gitignore_content = filter_input(INPUT_POST, 'gitignore_content', FILTER_SANITIZE_STRING);
|
||||
if ( ! isset( $submit_save ) || ! isset( $gitignore_content ) ) {
|
||||
return;
|
||||
}
|
||||
check_admin_referer( 'gitium-settings' );
|
||||
|
||||
if ( $this->git->set_gitignore( $gitignore_content ) ) {
|
||||
gitium_commit_and_push_gitignore_file();
|
||||
$this->success_redirect( __( 'The file `.gitignore` is saved!', 'gitium' ), $this->settings_menu_slug );
|
||||
} else {
|
||||
$this->redirect( __( 'The file `.gitignore` could not be saved!', 'gitium' ), false, $this->settings_menu_slug );
|
||||
}
|
||||
}
|
||||
|
||||
public function page() {
|
||||
$this->show_message();
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h2><?php _e( 'Gitium Settings', 'gitium' ); ?></h2>
|
||||
|
||||
<form action="" method="POST">
|
||||
<?php wp_nonce_field( 'gitium-settings' ) ?>
|
||||
|
||||
<p><span style="color:red;"><?php _e( 'Be careful when you modify this list!', 'gitium' ); ?></span></p>
|
||||
<textarea name="gitignore_content" rows="20" cols="140"><?php echo esc_html( $this->git->get_gitignore() ); ?></textarea>
|
||||
|
||||
<?php $this->show_webhook_table(); ?>
|
||||
<p class="submit">
|
||||
<input type="submit" name="GitiumSubmitSave" class="button-primary" value="<?php _e( 'Save', 'gitium' ); ?>" />
|
||||
</p>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
}
|
236
wp-content/plugins/gitium/inc/class-gitium-submenu-status.php
Normal file
236
wp-content/plugins/gitium/inc/class-gitium-submenu-status.php
Normal file
@ -0,0 +1,236 @@
|
||||
<?php
|
||||
/* Copyright 2014-2016 Presslabs SRL <ping@presslabs.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2, as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
class Gitium_Submenu_Status extends Gitium_Menu {
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct( $this->gitium_menu_slug, $this->gitium_menu_slug );
|
||||
|
||||
if ( current_user_can( GITIUM_MANAGE_OPTIONS_CAPABILITY ) ) {
|
||||
add_action( GITIUM_ADMIN_MENU_ACTION, array( $this, 'admin_menu' ) );
|
||||
add_action( 'admin_init', array( $this, 'save_changes' ) );
|
||||
add_action( 'admin_init', array( $this, 'save_ignorelist' ) );
|
||||
add_action( 'admin_init', array( $this, 'disconnect_repository' ) );
|
||||
}
|
||||
}
|
||||
|
||||
public function admin_menu() {
|
||||
add_menu_page(
|
||||
__( 'Git Status', 'gitium' ),
|
||||
'Gitium',
|
||||
GITIUM_MANAGE_OPTIONS_CAPABILITY,
|
||||
$this->menu_slug,
|
||||
array( $this, 'page' ),
|
||||
plugins_url( 'img/gitium.png', dirname( __FILE__ ) )
|
||||
);
|
||||
|
||||
$submenu_hook = add_submenu_page(
|
||||
$this->menu_slug,
|
||||
__( 'Git Status', 'gitium' ),
|
||||
__( 'Status', 'gitium' ),
|
||||
GITIUM_MANAGE_OPTIONS_CAPABILITY,
|
||||
$this->menu_slug,
|
||||
array( $this, 'page' )
|
||||
);
|
||||
new Gitium_Help( $submenu_hook, 'status' );
|
||||
}
|
||||
|
||||
private function get_change_meanings() {
|
||||
return array(
|
||||
'??' => __( 'untracked', 'gitium' ),
|
||||
'rM' => __( 'modified on remote', 'gitium' ),
|
||||
'rA' => __( 'added to remote', 'gitium' ),
|
||||
'rD' => __( 'deleted from remote', 'gitium' ),
|
||||
'D' => __( 'deleted from work tree', 'gitium' ),
|
||||
'M' => __( 'updated in work tree', 'gitium' ),
|
||||
'A' => __( 'added to work tree', 'gitium' ),
|
||||
'AM' => __( 'added to work tree', 'gitium' ),
|
||||
'R' => __( 'deleted from work tree', 'gitium' ),
|
||||
);
|
||||
}
|
||||
|
||||
public function humanized_change( $change ) {
|
||||
$meaning = $this->get_change_meanings();
|
||||
|
||||
if ( isset( $meaning[ $change ] ) ) {
|
||||
return $meaning[ $change ];
|
||||
}
|
||||
if ( 0 === strpos( $change, 'R ' ) ) {
|
||||
$old_filename = substr( $change, 2 );
|
||||
$change = sprintf( __( 'renamed from `%s`', 'gitium' ), $old_filename );
|
||||
}
|
||||
return $change;
|
||||
}
|
||||
|
||||
public function save_ignorelist() {
|
||||
$gitium_ignore_path = filter_input(INPUT_POST, 'GitiumIgnorePath', FILTER_SANITIZE_STRING);
|
||||
if ( ! isset( $gitium_ignore_path ) ) {
|
||||
return;
|
||||
} else {
|
||||
$path = $gitium_ignore_path;
|
||||
}
|
||||
check_admin_referer( 'gitium-admin' );
|
||||
|
||||
if ( $this->git->set_gitignore( join( "\n", array_unique( array_merge( explode( "\n", $this->git->get_gitignore() ), array( $path ) ) ) ) ) ) {
|
||||
gitium_commit_and_push_gitignore_file( $path );
|
||||
$this->success_redirect( __( 'The file `.gitignore` is saved!', 'gitium' ), $this->gitium_menu_slug );
|
||||
} else {
|
||||
$this->redirect( __( 'The file `.gitignore` could not be saved!', 'gitium' ), false, $this->gitium_menu_slug );
|
||||
}
|
||||
}
|
||||
|
||||
public function save_changes() {
|
||||
$gitium_save_changes = filter_input(INPUT_POST, 'GitiumSubmitSaveChanges', FILTER_SANITIZE_STRING);
|
||||
$gitium_commit_msg = filter_input(INPUT_POST, 'commitmsg', FILTER_SANITIZE_STRING);
|
||||
if ( ! isset( $gitium_save_changes ) ) {
|
||||
return;
|
||||
}
|
||||
check_admin_referer( 'gitium-admin' );
|
||||
|
||||
gitium_enable_maintenance_mode() or wp_die( __( 'Could not enable the maintenance mode!', 'gitium' ) );
|
||||
$this->git->add();
|
||||
$commitmsg = sprintf( __( 'Merged changes from %s on %s', 'gitium' ), get_site_url(), date( 'm.d.Y' ) );
|
||||
if ( isset( $gitium_commit_msg ) && ! empty( $gitium_commit_msg ) ) {
|
||||
$commitmsg = $gitium_commit_msg;
|
||||
}
|
||||
$current_user = wp_get_current_user();
|
||||
$commit = $this->git->commit( $commitmsg, $current_user->display_name, $current_user->user_email );
|
||||
if ( ! $commit ) {
|
||||
$this->redirect( __( 'Could not commit!', 'gitium' ) );
|
||||
}
|
||||
$merge_success = gitium_merge_and_push( $commit );
|
||||
gitium_disable_maintenance_mode();
|
||||
if ( ! $merge_success ) {
|
||||
$this->redirect( __( 'Merge failed: ', 'gitium' ) . $this->git->get_last_error() );
|
||||
}
|
||||
$this->success_redirect( sprintf( __( 'Pushed commit: `%s`', 'gitium' ), $commitmsg ) );
|
||||
}
|
||||
|
||||
private function show_ahead_and_behind_info( $changes = '' ) {
|
||||
$branch = $this->git->get_remote_tracking_branch();
|
||||
$ahead = count( $this->git->get_ahead_commits() );
|
||||
$behind = count( $this->git->get_behind_commits() );
|
||||
?>
|
||||
<p>
|
||||
<?php printf( __( 'Following remote branch <code>%s</code>.', 'gitium' ), $branch );
|
||||
?> <?php
|
||||
if ( ! $ahead && ! $behind && empty( $changes ) ) {
|
||||
_e( 'Everything is up to date', 'gitium' );
|
||||
}
|
||||
if ( $ahead && $behind ) {
|
||||
printf( __( 'You are %s commits ahead and %s behind remote.', 'gitium' ), $ahead, $behind );
|
||||
} elseif ( $ahead ) {
|
||||
printf( __( 'You are %s commits ahead remote.', 'gitium' ), $ahead );
|
||||
} elseif ( $behind ) {
|
||||
printf( __( 'You are %s commits behind remote.', 'gitium' ), $behind );
|
||||
}
|
||||
?>
|
||||
</p>
|
||||
<?php
|
||||
}
|
||||
|
||||
private function show_git_changes_table_rows( $changes = '' ) {
|
||||
?>
|
||||
<script type="application/javascript">
|
||||
function add_path_and_submit( elem ) {
|
||||
var container = document.getElementById( 'form_status' );
|
||||
var input = document.createElement( 'input' );
|
||||
input.type = 'hidden';
|
||||
input.name = 'GitiumIgnorePath';
|
||||
input.value = elem;
|
||||
container.appendChild( input );
|
||||
container.submit();
|
||||
}
|
||||
</script>
|
||||
<?php
|
||||
$counter = 0;
|
||||
foreach ( $changes as $path => $type ) :
|
||||
$counter++;
|
||||
echo ( 0 != $counter % 2 ) ? '<tr class="alternate">' : '<tr>';
|
||||
echo '<td><strong>' . esc_html( $path ) . '</strong>';
|
||||
echo '<div class="row-actions"><span class="edit"><a href="#" onclick="add_path_and_submit(\'' . $path . '\');">' . __( 'Add this file to the `.gitignore` list.', 'gitium' ) . '</a></span></div></td>';
|
||||
echo '<td>';
|
||||
if ( is_dir( ABSPATH . '/' . $path ) && is_dir( ABSPATH . '/' . trailingslashit( $path ) . '.git' ) ) { // test if is submodule
|
||||
_e( 'Submodules are not supported in this version.', 'gitium' );
|
||||
} else {
|
||||
echo '<span title="' . esc_html( $type ) .'">' . esc_html( $this->humanized_change( $type ) ) . '</span>';
|
||||
}
|
||||
echo '</td>';
|
||||
echo '</tr>';
|
||||
endforeach;
|
||||
}
|
||||
|
||||
private function show_git_changes_table( $changes = '' ) {
|
||||
?>
|
||||
<table class="widefat" id="git-changes-table">
|
||||
<thead><tr><th scope="col" class="manage-column"><?php _e( 'Path', 'gitium' ); ?></th><th scope="col" class="manage-column"><?php _e( 'Change', 'gitium' ); ?></th></tr></thead>
|
||||
<tfoot><tr><th scope="col" class="manage-column"><?php _e( 'Path', 'gitium' ); ?></th><th scope="col" class="manage-column"><?php _e( 'Change', 'gitium' ); ?></th></tr></tfoot>
|
||||
<tbody>
|
||||
<?php
|
||||
if ( empty( $changes ) ) :
|
||||
echo '<tr><td><p>';
|
||||
_e( 'Nothing to commit, working directory clean.', 'gitium' );
|
||||
echo '</p></td></tr>';
|
||||
else :
|
||||
$this->show_git_changes_table_rows( $changes );
|
||||
endif;
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php
|
||||
}
|
||||
|
||||
private function show_git_changes_table_submit_buttons( $changes ) {
|
||||
if ( ! empty( $changes ) ) : ?>
|
||||
<p>
|
||||
<label for="save-changes"><?php _e( 'Commit message', 'gitium' ); ?>:</label>
|
||||
<input type="text" name="commitmsg" id="save-changes" class="widefat" value="" placeholder="<?php printf( __( 'Merged changes from %s on %s', 'gitium' ), get_site_url(), date( 'm.d.Y' ) ); ?>" />
|
||||
</p>
|
||||
<p>
|
||||
<input type="submit" name="GitiumSubmitSaveChanges" class="button-primary button" value="<?php _e( 'Save changes', 'gitium' ); ?>" <?php if ( get_transient( 'gitium_remote_disconnected' ) ) { echo 'disabled="disabled" '; } ?>/>
|
||||
</p>
|
||||
<?php endif;
|
||||
}
|
||||
|
||||
private function changes_page() {
|
||||
list( , $changes ) = _gitium_status();
|
||||
?>
|
||||
<div class="wrap">
|
||||
<div id="icon-options-general" class="icon32"> </div>
|
||||
<h2><?php _e( 'Status', 'gitium' ); ?> <code class="small" style="background-color:forestgreen; color:whitesmoke;"><?php _e( 'connected to', 'gitium' ); ?> <strong><?php echo esc_html( $this->git->get_remote_url() ); ?></strong></code></h2>
|
||||
|
||||
<form name="form_status" id="form_status" action="" method="POST">
|
||||
<?php
|
||||
wp_nonce_field( 'gitium-admin' );
|
||||
$this->show_ahead_and_behind_info( $changes );
|
||||
$this->show_git_changes_table( $changes );
|
||||
$this->show_git_changes_table_submit_buttons( $changes );
|
||||
?>
|
||||
</form>
|
||||
<?php
|
||||
$this->show_disconnect_repository_button();
|
||||
?>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
public function page() {
|
||||
$this->show_message();
|
||||
_gitium_status( true );
|
||||
$this->changes_page();
|
||||
}
|
||||
}
|
8
wp-content/plugins/gitium/inc/ssh-git
Executable file
8
wp-content/plugins/gitium/inc/ssh-git
Executable file
@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
SSH_AUTH_SOCK=''
|
||||
SSH="ssh -q -F /dev/null -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
|
||||
if [ -z "$GIT_KEY_FILE" ] ; then
|
||||
exec $SSH "$@"
|
||||
else
|
||||
exec $SSH -i "$GIT_KEY_FILE" "$@"
|
||||
fi
|
BIN
wp-content/plugins/gitium/languages/gitium-es_ES.mo
Normal file
BIN
wp-content/plugins/gitium/languages/gitium-es_ES.mo
Normal file
Binary file not shown.
546
wp-content/plugins/gitium/languages/gitium-es_ES.po
Normal file
546
wp-content/plugins/gitium/languages/gitium-es_ES.po
Normal file
@ -0,0 +1,546 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Gitium\n"
|
||||
"POT-Creation-Date: 2014-10-20 19:06+0200\n"
|
||||
"PO-Revision-Date: 2014-11-13 11:20+0200\n"
|
||||
"Last-Translator: Presslabs <ping@presslabs.com>\n"
|
||||
"Language-Team: Presslabs <ping@presslabs.com>\n"
|
||||
"Language: English\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 1.5.4\n"
|
||||
"X-Poedit-KeywordsList: __;_e\n"
|
||||
"X-Poedit-Basepath: .\n"
|
||||
"X-Poedit-SourceCharset: UTF-8\n"
|
||||
"X-Poedit-SearchPath-0: ..\n"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:34
|
||||
#: ../inc/class-gitium-submenu-configure.php:44
|
||||
msgid "Git Configuration"
|
||||
msgstr "Configuración Git"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:45
|
||||
msgid "Configuration"
|
||||
msgstr "Configuración"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:59
|
||||
msgid "Keypair successfully regenerated."
|
||||
msgstr "Par de claves regenerado con éxito."
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:78
|
||||
msgid "Initial commit"
|
||||
msgstr "Commit Inicial"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:94
|
||||
msgid "Please specify a valid repo."
|
||||
msgstr "Por favor, especifique un repo válido"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:99
|
||||
msgid "Could not push to remote"
|
||||
msgstr "No se pudo empujar al remoto"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:113
|
||||
msgid "Merged existing code from "
|
||||
msgstr "Código existente fusionado de"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:116
|
||||
msgid "Could not create initial commit -> "
|
||||
msgstr "No se pudo crear Commit inicial ->"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:120
|
||||
msgid "Could not merge the initial commit -> "
|
||||
msgstr "No se pudo fusionar el Commit inicial ->"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:129
|
||||
msgid "Remote URL"
|
||||
msgstr "URL remoto"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:132
|
||||
msgid ""
|
||||
"This URL provide access to a Git repository via SSH, HTTPS, or Subversion."
|
||||
msgstr ""
|
||||
"Este URL proporciona acceso a un repositorio Git vía SSH, HTTPS o Subversión."
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:133
|
||||
msgid ""
|
||||
"If you need to authenticate over \"https://\" instead of SSH use: "
|
||||
"<code>https://user:pass@github.com/user/example.git</code>"
|
||||
msgstr ""
|
||||
"Si necesita autenticar sobre \"https:// en lugar del uso de SSH: <code> "
|
||||
"https://user:pass@github.com/user/example.git </code>"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:143
|
||||
msgid "Key pair"
|
||||
msgstr "Par de claves"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:147
|
||||
#: ../inc/class-gitium-submenu-settings.php:80
|
||||
msgid "Regenerate Key"
|
||||
msgstr "Regenerar clave"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:149
|
||||
#: ../inc/class-gitium-submenu-settings.php:81
|
||||
msgid ""
|
||||
"If your code use ssh keybased authentication for git you need to allow write "
|
||||
"access to your repository using this key."
|
||||
msgstr ""
|
||||
"Si su código usa autenticación ssh keybased para git, usted necesita "
|
||||
"permitir el acceso de escritura a su repositorio utilizando esta clave."
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:150
|
||||
#: ../inc/class-gitium-submenu-settings.php:82
|
||||
msgid ""
|
||||
"Checkout instructions for <a href=\"https://help.github.com/articles/"
|
||||
"generating-ssh-keys#step-3-add-your-ssh-key-to-github\" target=\"_blank"
|
||||
"\">github</a> or <a href=\"https://confluence.atlassian.com/display/"
|
||||
"BITBUCKET/Add+an+SSH+key+to+an+account#AddanSSHkeytoanaccount-"
|
||||
"HowtoaddakeyusingSSHforOSXorLinux\" target=\"_blank\">bitbucket</a>."
|
||||
msgstr ""
|
||||
"Instrucciones de Pedido para <a href=\"https://help.github.com/articles/"
|
||||
"generating-ssh-keys#step-3-add-your-ssh-key-to-github\" target=\"_blank"
|
||||
"\">github</a> or <a href=\"https://confluence.atlassian.com/display/"
|
||||
"BITBUCKET/Add+an+SSH+key+to+an+account#AddanSSHkeytoanaccount-"
|
||||
"HowtoaddakeyusingSSHforOSXorLinux\"."
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:160
|
||||
msgid "Warning!"
|
||||
msgstr "¡Advertencia!"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:174
|
||||
#: ../inc/class-gitium-help.php:47
|
||||
msgid "Configuration step 1"
|
||||
msgstr "Paso de configuración 1"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:175
|
||||
#: ../inc/class-gitium-submenu-configure.php:194
|
||||
msgid ""
|
||||
"If you need help to set this up, please click on the \"Help\" button from "
|
||||
"the top right corner of this screen."
|
||||
msgstr ""
|
||||
"Si necesita ayuda para configurar esto, por favor haga clic en el botón "
|
||||
"\"Ayuda\" de la esquina superior derecha de esta pantalla."
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:183
|
||||
msgid "Fetch"
|
||||
msgstr "Buscar"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:193
|
||||
#: ../inc/class-gitium-help.php:52
|
||||
msgid "Configuration step 2"
|
||||
msgstr "Paso de configuración 2"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:202
|
||||
msgid "Choose tracking branch"
|
||||
msgstr "Elija la rama de seguimiento"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:215
|
||||
msgid "Merge & Push"
|
||||
msgstr "Una & Empuje"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:32
|
||||
#: ../inc/class-gitium-submenu-status.php:42
|
||||
msgid "Git Status"
|
||||
msgstr "Estado Git"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:43
|
||||
#: ../inc/class-gitium-submenu-status.php:209 ../inc/class-gitium-help.php:59
|
||||
msgid "Status"
|
||||
msgstr "Estado"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:53
|
||||
msgid "untracked"
|
||||
msgstr "sin seguimiento"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:54
|
||||
msgid "modified on remote"
|
||||
msgstr "modificación en el remoto"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:55
|
||||
msgid "added to remote"
|
||||
msgstr "Agregado a remoto"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:56
|
||||
msgid "deleted from remote"
|
||||
msgstr "Borrado de remoto"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:57
|
||||
#: ../inc/class-gitium-submenu-status.php:61
|
||||
msgid "deleted from work tree"
|
||||
msgstr "Borrado del árbol de trabajo"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:58
|
||||
msgid "updated in work tree"
|
||||
msgstr "actualizado en el árbol de trabajo"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:59
|
||||
#: ../inc/class-gitium-submenu-status.php:60
|
||||
msgid "added to work tree"
|
||||
msgstr "añadido a árbol de trabajo"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:73
|
||||
#, php-format
|
||||
msgid "renamed from `%s`"
|
||||
msgstr "renombrado de `%s`"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:88
|
||||
#: ../inc/class-gitium-submenu-settings.php:106
|
||||
msgid "The file `.gitignore` is saved!"
|
||||
msgstr "¡El archivo` .gitignore` se guardó!"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:90
|
||||
#: ../inc/class-gitium-submenu-settings.php:108
|
||||
msgid "The file `.gitignore` could not be saved!"
|
||||
msgstr "¡El archivo ` .gitignore` no pudo guardarse!"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:100
|
||||
msgid "Could not enable the maintenance mode!"
|
||||
msgstr "No se pudo activar el modo de mantenimiento"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:102
|
||||
#: ../inc/class-gitium-submenu-status.php:196
|
||||
#, php-format
|
||||
msgid "Merged changes from %s on %s"
|
||||
msgstr "Cambios fusionados de %s en %s"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:109
|
||||
msgid "Could not commit!"
|
||||
msgstr "¡No pudo comprometerse!"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:114
|
||||
msgid "Merge failed: "
|
||||
msgstr "Combinar falló:"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:116
|
||||
#, php-format
|
||||
msgid "Pushed commit: `%s`"
|
||||
msgstr "Empujado comprometer: `%s`"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:125
|
||||
#, php-format
|
||||
msgid "Following remote branch <code>%s</code>."
|
||||
msgstr "Siguiendo sucursal remota <code>%s</code>."
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:127
|
||||
msgid "Everything is up to date"
|
||||
msgstr "Todo está actualizado"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:130
|
||||
#, php-format
|
||||
msgid "You are %s commits ahead and %s behind remote."
|
||||
msgstr "Usted está %s Commits por delante y %s por detrás del remoto."
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:132
|
||||
#, php-format
|
||||
msgid "You are %s commits ahead remote."
|
||||
msgstr "Usted está %s Commits delante del remoto."
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:134
|
||||
#, php-format
|
||||
msgid "You are %s commits behind remote."
|
||||
msgstr "Usted está %s Commits detrás del remoto."
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:160
|
||||
msgid "Add this file to the `.gitignore` list."
|
||||
msgstr "Añadir este archivo a la lista `.gitignore`."
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:163
|
||||
msgid "Submodules are not supported in this version."
|
||||
msgstr "Sub-módulos no son compatibles con esta versión."
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:175
|
||||
#: ../inc/class-gitium-submenu-status.php:176
|
||||
msgid "Path"
|
||||
msgstr "Ruta"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:175
|
||||
#: ../inc/class-gitium-submenu-status.php:176
|
||||
msgid "Change"
|
||||
msgstr "Cambiar"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:181
|
||||
msgid "Nothing to commit, working directory clean."
|
||||
msgstr "Nada que comprometer, directorio de trabajo limpio."
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:195
|
||||
msgid "Commit message"
|
||||
msgstr "Comprometer mensaje"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:199
|
||||
msgid "Save changes"
|
||||
msgstr "Guardar cambios"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:209
|
||||
msgid "connected to"
|
||||
msgstr "conectados a"
|
||||
|
||||
#: ../inc/class-gitium-submenu-settings.php:32 ../inc/class-gitium-help.php:81
|
||||
msgid "Settings"
|
||||
msgstr "Ajustes"
|
||||
|
||||
#: ../inc/class-gitium-submenu-settings.php:46
|
||||
msgid ""
|
||||
"Webhook URL regenerates. Please make sure you update any external references."
|
||||
msgstr ""
|
||||
"Webhook URL se regenera. Por favor, asegúrese de actualizar todas las "
|
||||
"referencias externas."
|
||||
|
||||
#: ../inc/class-gitium-submenu-settings.php:55
|
||||
msgid "Public key successfully regenerated."
|
||||
msgstr "Clave pública regenera con éxito."
|
||||
|
||||
#: ../inc/class-gitium-submenu-settings.php:61
|
||||
msgid "Webhook URL"
|
||||
msgstr "URL Webhook"
|
||||
|
||||
#: ../inc/class-gitium-submenu-settings.php:65
|
||||
msgid "Regenerate Webhook"
|
||||
msgstr "Regenerar Webhook"
|
||||
|
||||
#: ../inc/class-gitium-submenu-settings.php:67
|
||||
msgid "Pinging this URL triggers an update from remote repository."
|
||||
msgstr ""
|
||||
"Hacer ping en esta URL desencadena una actualización del repositorio remoto."
|
||||
|
||||
#: ../inc/class-gitium-submenu-settings.php:77
|
||||
msgid "Public Key"
|
||||
msgstr "Clave Pública"
|
||||
|
||||
#: ../inc/class-gitium-submenu-settings.php:116
|
||||
msgid "Gitium Settings"
|
||||
msgstr "Ajustes Gitium"
|
||||
|
||||
#: ../inc/class-gitium-submenu-settings.php:121
|
||||
msgid "Be careful when you modify this list!"
|
||||
msgstr "¡Tenga cuidado al modificar esta lista!"
|
||||
|
||||
#: ../inc/class-gitium-submenu-settings.php:126
|
||||
msgid "Save"
|
||||
msgstr "Guardar"
|
||||
|
||||
#: ../inc/class-gitium-help.php:26
|
||||
msgid "Gitium"
|
||||
msgstr "Gitium"
|
||||
|
||||
#: ../inc/class-gitium-help.php:27
|
||||
msgid "F.A.Q."
|
||||
msgstr "PF"
|
||||
|
||||
#: ../inc/class-gitium-help.php:32
|
||||
msgid ""
|
||||
"Gitium enables continuous deployment for WordPress integrating with tools "
|
||||
"such as Github, Bitbucket or Travis-CI. Plugin and theme updates, installs "
|
||||
"and removals are automatically versioned."
|
||||
msgstr ""
|
||||
"Gitium permite el despliegue continuo para integración de WordPress con "
|
||||
"herramientas como Github, Bitbucket o Travis-CI. El plugin y las "
|
||||
"actualizaciones de temas, instalaciones y eliminaciones están versionadas "
|
||||
"automáticamente."
|
||||
|
||||
#: ../inc/class-gitium-help.php:33
|
||||
msgid ""
|
||||
"Ninja code edits from the WordPress editor are also tracked into version "
|
||||
"control. Gitium is designed for sane development environments."
|
||||
msgstr ""
|
||||
"Las ediciones Código Ninja desde el editor de WordPress también son "
|
||||
"rastreadas en el control de versiones. Gitium está diseñado para entornos de "
|
||||
"desarrollo sanos."
|
||||
|
||||
#: ../inc/class-gitium-help.php:34
|
||||
msgid ""
|
||||
"Staging and production can follow different branches of the same repository. "
|
||||
"You can deploy code simply trough git push."
|
||||
msgstr ""
|
||||
"Puesta en escena y producción pueden seguir diferentes ramas del mismo "
|
||||
"repositorio. Puede implementar código simplemente a través git push."
|
||||
|
||||
#: ../inc/class-gitium-help.php:35
|
||||
msgid ""
|
||||
"Gitium requires <code>git</code> command line tool minimum version 1.7 "
|
||||
"installed on the server and <code>proc_open</code> PHP function enabled."
|
||||
msgstr ""
|
||||
"Gitium requiere la herramienta de línea de comandos<code> git </code>, "
|
||||
"mínimo la versión 1.7 instalada en el servidor y <code> proc_open </code> la "
|
||||
"función PHP habilitada."
|
||||
|
||||
#: ../inc/class-gitium-help.php:39
|
||||
msgid "Is this plugin considered stable?"
|
||||
msgstr "¿Es este plugin considerado estable?"
|
||||
|
||||
#: ../inc/class-gitium-help.php:39
|
||||
msgid ""
|
||||
"Right now this plugin is considered alpha quality and should be used in "
|
||||
"production environments only by adventurous kinds."
|
||||
msgstr ""
|
||||
"Ahora mismo este plugin se considera de calidad alfa y debe utilizarse en "
|
||||
"entornos de producción sólo por tipos aventureros."
|
||||
|
||||
#: ../inc/class-gitium-help.php:40
|
||||
msgid "What happens in case of conflicts?"
|
||||
msgstr "¿Qué sucede en caso de conflictos?"
|
||||
|
||||
#: ../inc/class-gitium-help.php:40
|
||||
msgid ""
|
||||
"The behavior in case of conflicts is to overwrite the changes on the origin "
|
||||
"repository with the local changes (ie. local modifications take precedence "
|
||||
"over remote ones)."
|
||||
msgstr ""
|
||||
"El comportamiento en caso de conflictos es sobrescribir los cambios en el "
|
||||
"repositorio de origen con los cambios locales (p.ej. las modificaciones "
|
||||
"locales toman precedencia sobre las remotas)."
|
||||
|
||||
#: ../inc/class-gitium-help.php:41
|
||||
msgid "How to deploy automatically after a push?"
|
||||
msgstr "¿Cómo implementar automáticamente después de un empujón?"
|
||||
|
||||
#: ../inc/class-gitium-help.php:41
|
||||
msgid ""
|
||||
"You can ping the webhook url after a push to automatically deploy the new "
|
||||
"code. The webhook url can be found under Code menu. This url plays well with "
|
||||
"Github or Bitbucket webhooks."
|
||||
msgstr ""
|
||||
"Puede hacer ping en la url webhook después de un empujón para distribuir "
|
||||
"automáticamente el nuevo código. La url webhook se puede encontrar en el "
|
||||
"menú Código. Esta url juega bien con Github o BitBucket WebHooks."
|
||||
|
||||
#: ../inc/class-gitium-help.php:42
|
||||
msgid "Does it works on multi site setups?"
|
||||
msgstr "¿Trabaja en múltiples configuraciones de sitio?"
|
||||
|
||||
#: ../inc/class-gitium-help.php:42
|
||||
msgid "Gitium is not supporting multisite setups at the moment."
|
||||
msgstr ""
|
||||
"Gitium no soporta a las configuraciones de múltiples sitios en este momento."
|
||||
|
||||
#: ../inc/class-gitium-help.php:43
|
||||
msgid "How does gitium handle submodules?"
|
||||
msgstr "¿Cómo manejar gitium los submódulos?"
|
||||
|
||||
#: ../inc/class-gitium-help.php:43
|
||||
msgid "Currently submodules are not supported."
|
||||
msgstr "Actualmente los submódulos no son compatibles."
|
||||
|
||||
#: ../inc/class-gitium-help.php:47
|
||||
msgid ""
|
||||
"In this step you must specify the <code>Remote URL</code>. This URL "
|
||||
"represents the link between the git sistem and your site."
|
||||
msgstr ""
|
||||
"En esta etapa, se debe especificar el <code> URL remoto </code>. Esta URL "
|
||||
"representa el enlace entre el sistema git y su sitio."
|
||||
|
||||
#: ../inc/class-gitium-help.php:48
|
||||
msgid "You can get this URL from your Git repository and it looks like this:"
|
||||
msgstr ""
|
||||
"Usted puede obtener esta dirección URL de su repositorio Git y se ve así:"
|
||||
|
||||
#: ../inc/class-gitium-help.php:49
|
||||
msgid "github.com -> git@github.com:user/example.git"
|
||||
msgstr "github.com -> git@github.com:user/example.git"
|
||||
|
||||
#: ../inc/class-gitium-help.php:50
|
||||
msgid "bitbucket.org -> git@bitbucket.org:user/glowing-happiness.git"
|
||||
msgstr "bitbucket.org -> git@bitbucket.org:user/glowing-happiness.git"
|
||||
|
||||
#: ../inc/class-gitium-help.php:51
|
||||
msgid ""
|
||||
"To go to the next step, fill the <code>Remote URL</code> and then press the "
|
||||
"<code>Fetch</code> button."
|
||||
msgstr ""
|
||||
"Para ir al siguiente paso, llene la <code> URL remota </code> y pulse el "
|
||||
"botón <code> Buscar </code>."
|
||||
|
||||
#: ../inc/class-gitium-help.php:52
|
||||
msgid ""
|
||||
"In this step you must select the <code>branch</code> you want to follow."
|
||||
msgstr ""
|
||||
"En este paso deberá seleccionar la <code> rama </code> que desea seguir."
|
||||
|
||||
#: ../inc/class-gitium-help.php:53
|
||||
msgid "Only this branch will have all of your code modifications."
|
||||
msgstr "Sólo esta rama tendrá todas sus modificaciones de código."
|
||||
|
||||
#: ../inc/class-gitium-help.php:54
|
||||
msgid ""
|
||||
"When you push the button <code>Merge & Push</code>, all code(plugins & "
|
||||
"themes) will be pushed on the git repository."
|
||||
msgstr ""
|
||||
"Cuando se presiona el botón <code> Combinar y Empujar </code>, todo el "
|
||||
"código (plugins y temas) serán empujados en el repositorio git."
|
||||
|
||||
#: ../inc/class-gitium-help.php:64
|
||||
msgid ""
|
||||
"On status page you can see what files are modified, and you can commit the "
|
||||
"changes to git."
|
||||
msgstr ""
|
||||
"En la página de estado se puede ver qué archivos son modificados, y usted "
|
||||
"puede confirmar los cambios a Git."
|
||||
|
||||
#: ../inc/class-gitium-help.php:69 ../inc/class-gitium-submenu-commits.php:29
|
||||
#: ../inc/class-gitium-submenu-commits.php:41
|
||||
msgid "Commits"
|
||||
msgstr "Commits"
|
||||
|
||||
#: ../inc/class-gitium-help.php:74
|
||||
msgid ""
|
||||
"You may be wondering what is the difference between author and committer."
|
||||
msgstr ""
|
||||
"Usted puede preguntarse cuál es la diferencia entre el autor y el comitter."
|
||||
|
||||
#: ../inc/class-gitium-help.php:75
|
||||
msgid ""
|
||||
"The <code>author</code> is the person who originally wrote the patch, "
|
||||
"whereas the <code>committer</code> is the person who last applied the patch."
|
||||
msgstr ""
|
||||
"El <code> autor </code> es la persona que originalmente escribió el parche, "
|
||||
"mientras que el <code> committer </code> es la persona que aplicó el parche "
|
||||
"al final."
|
||||
|
||||
#: ../inc/class-gitium-help.php:76
|
||||
msgid ""
|
||||
"So, if you send in a patch to a project and one of the core members applies "
|
||||
"the patch, both of you get credit — you as the author and the core member as "
|
||||
"the committer."
|
||||
msgstr ""
|
||||
"Por lo tanto, si usted envía en un parche para un proyecto y uno de los "
|
||||
"principales miembros aplica el parche, ambos consiguen crédito - usted como "
|
||||
"el autor y el miembro de núcleo como el commiter."
|
||||
|
||||
#: ../inc/class-gitium-help.php:86
|
||||
msgid "Each line from the gitignore file specifies a pattern."
|
||||
msgstr "Cada línea del archivo gitignore especifica un patrón."
|
||||
|
||||
#: ../inc/class-gitium-help.php:87
|
||||
msgid ""
|
||||
"When deciding whether to ignore a path, Git normally checks gitignore "
|
||||
"patterns from multiple sources, with the following order of precedence, from "
|
||||
"highest to lowest (within one level of precedence, the last matching pattern "
|
||||
"decides the outcome)"
|
||||
msgstr ""
|
||||
"A la hora de decidir si se debe pasar por alto una ruta, Git normalmente "
|
||||
"comprueba patrones gitignore de múltiples fuentes, con el siguiente orden, "
|
||||
"de de mayor a menor (dentro de un nivel de prioridad, la última "
|
||||
"coincidencia de patrones decide el resultado)"
|
||||
|
||||
#: ../inc/class-gitium-help.php:88
|
||||
#, php-format
|
||||
msgid "Read more on %s"
|
||||
msgstr "Leer más en %s"
|
||||
|
||||
#: ../inc/class-gitium-submenu-commits.php:28
|
||||
msgid "Git Commits"
|
||||
msgstr "Commits Git"
|
||||
|
||||
#: ../inc/class-gitium-submenu-commits.php:61
|
||||
#, php-format
|
||||
msgid "Last %s commits"
|
||||
msgstr "Últimos commits %s"
|
||||
|
||||
#: ../inc/class-gitium-submenu-commits.php:70
|
||||
#, php-format
|
||||
msgid "committed %s ago"
|
||||
msgstr "cometido hace %s"
|
||||
|
||||
#: ../inc/class-gitium-submenu-commits.php:82
|
||||
#, php-format
|
||||
msgid "authored %s ago"
|
||||
msgstr "Creado hace %s"
|
BIN
wp-content/plugins/gitium/languages/gitium-sr_RS.mo
Normal file
BIN
wp-content/plugins/gitium/languages/gitium-sr_RS.mo
Normal file
Binary file not shown.
538
wp-content/plugins/gitium/languages/gitium-sr_RS.po
Normal file
538
wp-content/plugins/gitium/languages/gitium-sr_RS.po
Normal file
@ -0,0 +1,538 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Gitium\n"
|
||||
"POT-Creation-Date: 2014-10-20 19:06+0200\n"
|
||||
"PO-Revision-Date: 2014-10-24 12:51+0200\n"
|
||||
"Last-Translator: Presslabs <ping@presslabs.com>\n"
|
||||
"Language-Team: Presslabs <ping@presslabs.com>\n"
|
||||
"Language: English\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 1.5.4\n"
|
||||
"X-Poedit-KeywordsList: __;_e\n"
|
||||
"X-Poedit-Basepath: .\n"
|
||||
"X-Poedit-SourceCharset: UTF-8\n"
|
||||
"X-Poedit-SearchPath-0: ..\n"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:34
|
||||
#: ../inc/class-gitium-submenu-configure.php:44
|
||||
msgid "Git Configuration"
|
||||
msgstr "Git konfiguracija"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:45
|
||||
msgid "Configuration"
|
||||
msgstr "Konfiguracija"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:59
|
||||
msgid "Keypair successfully regenerated."
|
||||
msgstr "Par ključeva uspešno regenerisan"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:78
|
||||
msgid "Initial commit"
|
||||
msgstr "Početna uputstva"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:94
|
||||
msgid "Please specify a valid repo."
|
||||
msgstr "Odaberite važeće spremište"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:99
|
||||
msgid "Could not push to remote"
|
||||
msgstr "Neuspelo potiskivanje u udaljeno spremište"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:113
|
||||
msgid "Merged existing code from "
|
||||
msgstr "Postojeći kod spojen sa"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:116
|
||||
msgid "Could not create initial commit -> "
|
||||
msgstr "Neuspelo kreiranje početnog uputstva ->"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:120
|
||||
msgid "Could not merge the initial commit -> "
|
||||
msgstr "Neuspelo spajanje početnog uputstva ->"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:129
|
||||
msgid "Remote URL"
|
||||
msgstr "URL udaljenog spremišta"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:132
|
||||
msgid ""
|
||||
"This URL provide access to a Git repository via SSH, HTTPS, or Subversion."
|
||||
msgstr ""
|
||||
"Ovaj URL obezbeđuje pristup Git skladištu putem SSH-a, HTTPS-a ili "
|
||||
"Subverzije."
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:133
|
||||
msgid ""
|
||||
"If you need to authenticate over \"https://\" instead of SSH use: "
|
||||
"<code>https://user:pass@github.com/user/example.git</code>"
|
||||
msgstr ""
|
||||
"Ako treba da proverite preko \"https://\" umesto SSH, koristite: "
|
||||
"<code>https://user:pass@github.com/user/example.git</code>"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:143
|
||||
msgid "Key pair"
|
||||
msgstr "Par ključeva"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:147
|
||||
#: ../inc/class-gitium-submenu-settings.php:80
|
||||
msgid "Regenerate Key"
|
||||
msgstr "Ključ za regenerisanje"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:149
|
||||
#: ../inc/class-gitium-submenu-settings.php:81
|
||||
msgid ""
|
||||
"If your code use ssh keybased authentication for git you need to allow write "
|
||||
"access to your repository using this key."
|
||||
msgstr ""
|
||||
"Ako vaš kod koristi git autentifikaciju na osnovu ssh ključa, morate pismeno "
|
||||
"dozvoliti pristup svom spremištu uz pomoć ovog ključa. "
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:150
|
||||
#: ../inc/class-gitium-submenu-settings.php:82
|
||||
msgid ""
|
||||
"Checkout instructions for <a href=\"https://help.github.com/articles/"
|
||||
"generating-ssh-keys#step-3-add-your-ssh-key-to-github\" target=\"_blank"
|
||||
"\">github</a> or <a href=\"https://confluence.atlassian.com/display/"
|
||||
"BITBUCKET/Add+an+SSH+key+to+an+account#AddanSSHkeytoanaccount-"
|
||||
"HowtoaddakeyusingSSHforOSXorLinux\" target=\"_blank\">bitbucket</a>."
|
||||
msgstr ""
|
||||
"Pogledajte uputstva na <a href=\"https://help.github.com/articles/generating-"
|
||||
"ssh-keys#step-3-add-your-ssh-key-to-github\" target=\"_blank\">github</a> "
|
||||
"ili <a href=\"https://confluence.atlassian.com/display/BITBUCKET/Add+an+SSH"
|
||||
"+key+to+an+account#AddanSSHkeytoanaccount-HowtoaddakeyusingSSHforOSXorLinux"
|
||||
"\" target=\"_blank\">bitbucket</a>."
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:160
|
||||
msgid "Warning!"
|
||||
msgstr "Upozorenje!"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:174
|
||||
#: ../inc/class-gitium-help.php:47
|
||||
msgid "Configuration step 1"
|
||||
msgstr "Konfiguracija, korak 1"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:175
|
||||
#: ../inc/class-gitium-submenu-configure.php:194
|
||||
msgid ""
|
||||
"If you need help to set this up, please click on the \"Help\" button from "
|
||||
"the top right corner of this screen."
|
||||
msgstr ""
|
||||
"Ako vam treba pomoć za ovo podešavanje, kliknite na taster \"Pomoć\" u "
|
||||
"gornjem desnom uglu ekrana."
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:183
|
||||
msgid "Fetch"
|
||||
msgstr "Uzmi"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:193
|
||||
#: ../inc/class-gitium-help.php:52
|
||||
msgid "Configuration step 2"
|
||||
msgstr "Konfiguracija, korak 2"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:202
|
||||
msgid "Choose tracking branch"
|
||||
msgstr "Odaberite ogranak za praćenje"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:215
|
||||
msgid "Merge & Push"
|
||||
msgstr "Spoji & Potisni"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:32
|
||||
#: ../inc/class-gitium-submenu-status.php:42
|
||||
msgid "Git Status"
|
||||
msgstr "Git Status"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:43
|
||||
#: ../inc/class-gitium-submenu-status.php:209 ../inc/class-gitium-help.php:59
|
||||
msgid "Status"
|
||||
msgstr "Status"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:53
|
||||
msgid "untracked"
|
||||
msgstr "nepraćen"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:54
|
||||
msgid "modified on remote"
|
||||
msgstr "modifikovan na udaljenom skladištu"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:55
|
||||
msgid "added to remote"
|
||||
msgstr "dodat udaljenom skladištu"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:56
|
||||
msgid "deleted from remote"
|
||||
msgstr "obrisan sa udaljenog skladišta"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:57
|
||||
#: ../inc/class-gitium-submenu-status.php:61
|
||||
msgid "deleted from work tree"
|
||||
msgstr "obrisan sa radnog drveta"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:58
|
||||
msgid "updated in work tree"
|
||||
msgstr "ažuriran u radnom drvetu"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:59
|
||||
#: ../inc/class-gitium-submenu-status.php:60
|
||||
msgid "added to work tree"
|
||||
msgstr "dodat radnom drvetu"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:73
|
||||
#, php-format
|
||||
msgid "renamed from `%s`"
|
||||
msgstr "ime `%s` promenjeno"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:88
|
||||
#: ../inc/class-gitium-submenu-settings.php:106
|
||||
msgid "The file `.gitignore` is saved!"
|
||||
msgstr "Datoteka `.gitignore` je sačuvana!"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:90
|
||||
#: ../inc/class-gitium-submenu-settings.php:108
|
||||
msgid "The file `.gitignore` could not be saved!"
|
||||
msgstr "Datoteka `.gitignore` ne može biti sačuvana!"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:100
|
||||
msgid "Could not enable the maintenance mode!"
|
||||
msgstr "Režim održavanja nije mogao biti aktiviran!"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:102
|
||||
#: ../inc/class-gitium-submenu-status.php:196
|
||||
#, php-format
|
||||
msgid "Merged changes from %s on %s"
|
||||
msgstr "Promene sa %s na %s spojene!"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:109
|
||||
msgid "Could not commit!"
|
||||
msgstr "Neuspelo izvršenje!"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:114
|
||||
msgid "Merge failed: "
|
||||
msgstr "Neuspelo spajanje:"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:116
|
||||
#, php-format
|
||||
msgid "Pushed commit: `%s`"
|
||||
msgstr "Preneto izvršenje: `%s`"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:125
|
||||
#, php-format
|
||||
msgid "Following remote branch <code>%s</code>."
|
||||
msgstr "Praćenje udaljenog ogranka<kod>%s</kod>."
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:127
|
||||
msgid "Everything is up to date"
|
||||
msgstr "Sve je ažurirano"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:130
|
||||
#, php-format
|
||||
msgid "You are %s commits ahead and %s behind remote."
|
||||
msgstr "Vi ste %s izvršenja ispred i %s iza udaljenog spremišta."
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:132
|
||||
#, php-format
|
||||
msgid "You are %s commits ahead remote."
|
||||
msgstr "Vi ste %s izvršenja ispred udaljenog spremišta."
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:134
|
||||
#, php-format
|
||||
msgid "You are %s commits behind remote."
|
||||
msgstr "Vi ste %s izvršenja iza udaljenog spremišta."
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:160
|
||||
msgid "Add this file to the `.gitignore` list."
|
||||
msgstr "Dodajte ovu datoteku `.gitignore` listi."
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:163
|
||||
msgid "Submodules are not supported in this version."
|
||||
msgstr "U ovoj verziji nisu podržani submoduli."
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:175
|
||||
#: ../inc/class-gitium-submenu-status.php:176
|
||||
msgid "Path"
|
||||
msgstr "Putanja"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:175
|
||||
#: ../inc/class-gitium-submenu-status.php:176
|
||||
msgid "Change"
|
||||
msgstr "Izmeni"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:181
|
||||
msgid "Nothing to commit, working directory clean."
|
||||
msgstr "Nema ničega za izvršenje, radni direktorijum je čist."
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:195
|
||||
msgid "Commit message"
|
||||
msgstr "Poruka o izvršenju"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:199
|
||||
msgid "Save changes"
|
||||
msgstr "Sačuvaj izmene"
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:209
|
||||
msgid "connected to"
|
||||
msgstr "povezan sa"
|
||||
|
||||
#: ../inc/class-gitium-submenu-settings.php:32 ../inc/class-gitium-help.php:81
|
||||
msgid "Settings"
|
||||
msgstr "Podešavanja"
|
||||
|
||||
#: ../inc/class-gitium-submenu-settings.php:46
|
||||
msgid ""
|
||||
"Webhook URL regenerates. Please make sure you update any external references."
|
||||
msgstr ""
|
||||
"Webhook URL se regeneriše. Proverite da li ste ažurirali eksterne reference."
|
||||
|
||||
#: ../inc/class-gitium-submenu-settings.php:55
|
||||
msgid "Public key successfully regenerated."
|
||||
msgstr "Javni ključ uspešno regenerisan."
|
||||
|
||||
#: ../inc/class-gitium-submenu-settings.php:61
|
||||
msgid "Webhook URL"
|
||||
msgstr "Webhook URL"
|
||||
|
||||
#: ../inc/class-gitium-submenu-settings.php:65
|
||||
msgid "Regenerate Webhook"
|
||||
msgstr "Regeneriši webhook"
|
||||
|
||||
#: ../inc/class-gitium-submenu-settings.php:67
|
||||
msgid "Pinging this URL triggers an update from remote repository."
|
||||
msgstr "Pingovanje ovog URL-a povlači ažuriranje iz udaljenog skladišta."
|
||||
|
||||
#: ../inc/class-gitium-submenu-settings.php:77
|
||||
msgid "Public Key"
|
||||
msgstr "Javni ključ"
|
||||
|
||||
#: ../inc/class-gitium-submenu-settings.php:116
|
||||
msgid "Gitium Settings"
|
||||
msgstr "Gitium podešavanja"
|
||||
|
||||
#: ../inc/class-gitium-submenu-settings.php:121
|
||||
msgid "Be careful when you modify this list!"
|
||||
msgstr "Oprezno menjajte ovu listu!"
|
||||
|
||||
#: ../inc/class-gitium-submenu-settings.php:126
|
||||
msgid "Save"
|
||||
msgstr "Sačuvaj"
|
||||
|
||||
#: ../inc/class-gitium-help.php:26
|
||||
msgid "Gitium"
|
||||
msgstr "Gitium"
|
||||
|
||||
#: ../inc/class-gitium-help.php:27
|
||||
msgid "F.A.Q."
|
||||
msgstr "Često postavljana pitanja"
|
||||
|
||||
#: ../inc/class-gitium-help.php:32
|
||||
msgid ""
|
||||
"Gitium enables continuous deployment for WordPress integrating with tools "
|
||||
"such as Github, Bitbucket or Travis-CI. Plugin and theme updates, installs "
|
||||
"and removals are automatically versioned."
|
||||
msgstr ""
|
||||
"Gitium omogućava kontinuiranu primenu WordPress integrisanja alatima, kao "
|
||||
"što su: Github, Bitbucket ili Travis-CI. Ažuriranja plugin-a i teme, "
|
||||
"instalacije i uklanjanja automatski su verzionirani."
|
||||
|
||||
#: ../inc/class-gitium-help.php:33
|
||||
msgid ""
|
||||
"Ninja code edits from the WordPress editor are also tracked into version "
|
||||
"control. Gitium is designed for sane development environments."
|
||||
msgstr ""
|
||||
"Nindža kod, koji uređuje iz WordPress uređivača, takođe se prati u kontroli "
|
||||
"verzije. Gitium je dizajniran za razumna razvojna okruženja."
|
||||
|
||||
#: ../inc/class-gitium-help.php:34
|
||||
msgid ""
|
||||
"Staging and production can follow different branches of the same repository. "
|
||||
"You can deploy code simply trough git push."
|
||||
msgstr ""
|
||||
"Postavljanje i proizvodnja mogu da prate različite grane istog spremišta. "
|
||||
"Možete da primenite kod jednostavno kroz git push."
|
||||
|
||||
#: ../inc/class-gitium-help.php:35
|
||||
msgid ""
|
||||
"Gitium requires <code>git</code> command line tool minimum version 1.7 "
|
||||
"installed on the server and <code>proc_open</code> PHP function enabled."
|
||||
msgstr ""
|
||||
"Gitium zahteva da na serveru bude instaliran <code>git</code> alat komandne "
|
||||
"linije, najmanje verzije 1.7 i <code>proc_open</code> aktiviranu PHP "
|
||||
"funkciju."
|
||||
|
||||
#: ../inc/class-gitium-help.php:39
|
||||
msgid "Is this plugin considered stable?"
|
||||
msgstr "Da li se ovaj plugin smatra stabilnim?"
|
||||
|
||||
#: ../inc/class-gitium-help.php:39
|
||||
msgid ""
|
||||
"Right now this plugin is considered alpha quality and should be used in "
|
||||
"production environments only by adventurous kinds."
|
||||
msgstr ""
|
||||
"Trenutno se smatra da ovaj plugin ima alfa kvalitet i treba ga koristiti u "
|
||||
"okruženjima produkcije isključivo avanturističkog karaktera."
|
||||
|
||||
#: ../inc/class-gitium-help.php:40
|
||||
msgid "What happens in case of conflicts?"
|
||||
msgstr "Šta se dešava u slučaju konflikta?"
|
||||
|
||||
#: ../inc/class-gitium-help.php:40
|
||||
msgid ""
|
||||
"The behavior in case of conflicts is to overwrite the changes on the origin "
|
||||
"repository with the local changes (ie. local modifications take precedence "
|
||||
"over remote ones)."
|
||||
msgstr ""
|
||||
"U slučaju konflikta treba poništiti izmene u prvobitnom spremištu, zajedno "
|
||||
"sa lokalnim izmenama (tj. Lokalne izmene imaju prednost u odnosu na "
|
||||
"udaljene)."
|
||||
|
||||
#: ../inc/class-gitium-help.php:41
|
||||
msgid "How to deploy automatically after a push?"
|
||||
msgstr "Kako izvršiti automatsko razmeštanje posle pritiska?"
|
||||
|
||||
#: ../inc/class-gitium-help.php:41
|
||||
msgid ""
|
||||
"You can ping the webhook url after a push to automatically deploy the new "
|
||||
"code. The webhook url can be found under Code menu. This url plays well with "
|
||||
"Github or Bitbucket webhooks."
|
||||
msgstr ""
|
||||
"Možete pingovati url za webhook nakon pritiska za automatsko razmeštanje "
|
||||
"novog koda. URL za webhook možete naći u meniju koda. Ovaj url dobro radi uz "
|
||||
"Github ili Bitbucket webhooks."
|
||||
|
||||
#: ../inc/class-gitium-help.php:42
|
||||
msgid "Does it works on multi site setups?"
|
||||
msgstr "Da li radi na podešavanjima višestrukih site-ova?"
|
||||
|
||||
#: ../inc/class-gitium-help.php:42
|
||||
msgid "Gitium is not supporting multisite setups at the moment."
|
||||
msgstr "Gitium trenutno ne podržava podešavanje višestrukih site-ova."
|
||||
|
||||
#: ../inc/class-gitium-help.php:43
|
||||
msgid "How does gitium handle submodules?"
|
||||
msgstr "Kako gitium upravlja submodulima?"
|
||||
|
||||
#: ../inc/class-gitium-help.php:43
|
||||
msgid "Currently submodules are not supported."
|
||||
msgstr "Trenutno, submoduli nisu podržani."
|
||||
|
||||
#: ../inc/class-gitium-help.php:47
|
||||
msgid ""
|
||||
"In this step you must specify the <code>Remote URL</code>. This URL "
|
||||
"represents the link between the git sistem and your site."
|
||||
msgstr ""
|
||||
"U ovom koraku morate odrediti <code>Udaljeni URL</code>. Ovaj URL "
|
||||
"predstavlja vezu između git sistema i vašeg site-a."
|
||||
|
||||
#: ../inc/class-gitium-help.php:48
|
||||
msgid "You can get this URL from your Git repository and it looks like this:"
|
||||
msgstr "Ovaj URL možete dobiti iz svog Git spremišta i on izgleda ovako:"
|
||||
|
||||
#: ../inc/class-gitium-help.php:49
|
||||
msgid "github.com -> git@github.com:user/example.git"
|
||||
msgstr "github.com -> git@github.com:user/example.git"
|
||||
|
||||
#: ../inc/class-gitium-help.php:50
|
||||
msgid "bitbucket.org -> git@bitbucket.org:user/glowing-happiness.git"
|
||||
msgstr "bitbucket.org -> git@bitbucket.org:user/glowing-happines.git"
|
||||
|
||||
#: ../inc/class-gitium-help.php:51
|
||||
msgid ""
|
||||
"To go to the next step, fill the <code>Remote URL</code> and then press the "
|
||||
"<code>Fetch</code> button."
|
||||
msgstr ""
|
||||
"Da biste prešli na sledeći korak, popunite <code>Udaljeni URL</code> i "
|
||||
"pritisnite <code>Dobavi</code> taster."
|
||||
|
||||
#: ../inc/class-gitium-help.php:52
|
||||
msgid ""
|
||||
"In this step you must select the <code>branch</code> you want to follow."
|
||||
msgstr ""
|
||||
"U ovom koraku morate odabrati <code>ogranak</code> koji želite da pratite. "
|
||||
|
||||
#: ../inc/class-gitium-help.php:53
|
||||
msgid "Only this branch will have all of your code modifications."
|
||||
msgstr "Samo će ovaj ogranak imati sve vaše modifikacije koda."
|
||||
|
||||
#: ../inc/class-gitium-help.php:54
|
||||
msgid ""
|
||||
"When you push the button <code>Merge & Push</code>, all code(plugins & "
|
||||
"themes) will be pushed on the git repository."
|
||||
msgstr ""
|
||||
"Kad kliknete na taster <code>Spoji & Potisni</code> svi (plugin-ovi i teme) "
|
||||
"koda biće potisnuti u git spremište."
|
||||
|
||||
#: ../inc/class-gitium-help.php:64
|
||||
msgid ""
|
||||
"On status page you can see what files are modified, and you can commit the "
|
||||
"changes to git."
|
||||
msgstr ""
|
||||
"Na stranici statusa možete videti koje su datoteke izmenjene i možete uneti "
|
||||
"izmene u git."
|
||||
|
||||
#: ../inc/class-gitium-help.php:69 ../inc/class-gitium-submenu-commits.php:29
|
||||
#: ../inc/class-gitium-submenu-commits.php:41
|
||||
msgid "Commits"
|
||||
msgstr "Izvršenja"
|
||||
|
||||
#: ../inc/class-gitium-help.php:74
|
||||
msgid ""
|
||||
"You may be wondering what is the difference between author and committer."
|
||||
msgstr "Možda se pitate u čemu je razlika između autora i izvršioca?"
|
||||
|
||||
#: ../inc/class-gitium-help.php:75
|
||||
msgid ""
|
||||
"The <code>author</code> is the person who originally wrote the patch, "
|
||||
"whereas the <code>committer</code> is the person who last applied the patch."
|
||||
msgstr ""
|
||||
"<code>Autor</code> je osoba koja je originalno napisala zakrpu, dok je "
|
||||
"<code>izvršilac</code> osoba koja je poslednja primenila zakrpu."
|
||||
|
||||
#: ../inc/class-gitium-help.php:76
|
||||
msgid ""
|
||||
"So, if you send in a patch to a project and one of the core members applies "
|
||||
"the patch, both of you get credit — you as the author and the core member as "
|
||||
"the committer."
|
||||
msgstr ""
|
||||
"Dakle, ako pošaljete zakrpu projektu i jedan od ključnih članova je primeni "
|
||||
"- oboje dobijate zasluge - vi kao autor, a ključni član kao izvršilac."
|
||||
|
||||
#: ../inc/class-gitium-help.php:86
|
||||
msgid "Each line from the gitignore file specifies a pattern."
|
||||
msgstr "Svaka linija iz gitignore datoteke označava šablon."
|
||||
|
||||
#: ../inc/class-gitium-help.php:87
|
||||
msgid ""
|
||||
"When deciding whether to ignore a path, Git normally checks gitignore "
|
||||
"patterns from multiple sources, with the following order of precedence, from "
|
||||
"highest to lowest (within one level of precedence, the last matching pattern "
|
||||
"decides the outcome)"
|
||||
msgstr ""
|
||||
"Kad odlučujete o tome da li ćete ignorisati putanju, Git obično proverava "
|
||||
"gitignore šablone iz višestrukih izvora, sa sledećim redosledom - od "
|
||||
"najvišeg do najnižeg (u okviru jednog nivoa prednosti, poslednji šablon koji "
|
||||
"se poklapa odlučuje o ishodu)."
|
||||
|
||||
#: ../inc/class-gitium-help.php:88
|
||||
#, php-format
|
||||
msgid "Read more on %s"
|
||||
msgstr "Pročitajte više o %s"
|
||||
|
||||
#: ../inc/class-gitium-submenu-commits.php:28
|
||||
msgid "Git Commits"
|
||||
msgstr "Git izvršenja"
|
||||
|
||||
#: ../inc/class-gitium-submenu-commits.php:61
|
||||
#, php-format
|
||||
msgid "Last %s commits"
|
||||
msgstr "Poslednja %s izvršenja"
|
||||
|
||||
#: ../inc/class-gitium-submenu-commits.php:70
|
||||
#, php-format
|
||||
msgid "committed %s ago"
|
||||
msgstr "izvršena pre %s"
|
||||
|
||||
#: ../inc/class-gitium-submenu-commits.php:82
|
||||
#, php-format
|
||||
msgid "authored %s ago"
|
||||
msgstr "autorizovana pre %s"
|
489
wp-content/plugins/gitium/languages/gitium.pot
Normal file
489
wp-content/plugins/gitium/languages/gitium.pot
Normal file
@ -0,0 +1,489 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Gitium\n"
|
||||
"POT-Creation-Date: 2014-10-20 19:06+0200\n"
|
||||
"PO-Revision-Date: 2014-10-20 19:06+0200\n"
|
||||
"Last-Translator: Presslabs <ping@presslabs.com>\n"
|
||||
"Language-Team: Presslabs <ping@presslabs.com>\n"
|
||||
"Language: English\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 1.5.4\n"
|
||||
"X-Poedit-KeywordsList: __;_e\n"
|
||||
"X-Poedit-Basepath: .\n"
|
||||
"X-Poedit-SourceCharset: UTF-8\n"
|
||||
"X-Poedit-SearchPath-0: ..\n"
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:34
|
||||
#: ../inc/class-gitium-submenu-configure.php:44
|
||||
msgid "Git Configuration"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:45
|
||||
msgid "Configuration"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:59
|
||||
msgid "Keypair successfully regenerated."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:78
|
||||
msgid "Initial commit"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:94
|
||||
msgid "Please specify a valid repo."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:99
|
||||
msgid "Could not push to remote"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:113
|
||||
msgid "Merged existing code from "
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:116
|
||||
msgid "Could not create initial commit -> "
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:120
|
||||
msgid "Could not merge the initial commit -> "
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:129
|
||||
msgid "Remote URL"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:132
|
||||
msgid ""
|
||||
"This URL provide access to a Git repository via SSH, HTTPS, or Subversion."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:133
|
||||
msgid ""
|
||||
"If you need to authenticate over \"https://\" instead of SSH use: "
|
||||
"<code>https://user:pass@github.com/user/example.git</code>"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:143
|
||||
msgid "Key pair"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:147
|
||||
#: ../inc/class-gitium-submenu-settings.php:80
|
||||
msgid "Regenerate Key"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:149
|
||||
#: ../inc/class-gitium-submenu-settings.php:81
|
||||
msgid ""
|
||||
"If your code use ssh keybased authentication for git you need to allow write "
|
||||
"access to your repository using this key."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:150
|
||||
#: ../inc/class-gitium-submenu-settings.php:82
|
||||
msgid ""
|
||||
"Checkout instructions for <a href=\"https://help.github.com/articles/"
|
||||
"generating-ssh-keys#step-3-add-your-ssh-key-to-github\" target=\"_blank"
|
||||
"\">github</a> or <a href=\"https://confluence.atlassian.com/display/"
|
||||
"BITBUCKET/Add+an+SSH+key+to+an+account#AddanSSHkeytoanaccount-"
|
||||
"HowtoaddakeyusingSSHforOSXorLinux\" target=\"_blank\">bitbucket</a>."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:160
|
||||
msgid "Warning!"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:174
|
||||
#: ../inc/class-gitium-help.php:47
|
||||
msgid "Configuration step 1"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:175
|
||||
#: ../inc/class-gitium-submenu-configure.php:194
|
||||
msgid ""
|
||||
"If you need help to set this up, please click on the \"Help\" button from "
|
||||
"the top right corner of this screen."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:183
|
||||
msgid "Fetch"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:193
|
||||
#: ../inc/class-gitium-help.php:52
|
||||
msgid "Configuration step 2"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:202
|
||||
msgid "Choose tracking branch"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-configure.php:215
|
||||
msgid "Merge & Push"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:32
|
||||
#: ../inc/class-gitium-submenu-status.php:42
|
||||
msgid "Git Status"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:43
|
||||
#: ../inc/class-gitium-submenu-status.php:209 ../inc/class-gitium-help.php:59
|
||||
msgid "Status"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:53
|
||||
msgid "untracked"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:54
|
||||
msgid "modified on remote"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:55
|
||||
msgid "added to remote"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:56
|
||||
msgid "deleted from remote"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:57
|
||||
#: ../inc/class-gitium-submenu-status.php:61
|
||||
msgid "deleted from work tree"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:58
|
||||
msgid "updated in work tree"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:59
|
||||
#: ../inc/class-gitium-submenu-status.php:60
|
||||
msgid "added to work tree"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:73
|
||||
#, php-format
|
||||
msgid "renamed from `%s`"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:88
|
||||
#: ../inc/class-gitium-submenu-settings.php:106
|
||||
msgid "The file `.gitignore` is saved!"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:90
|
||||
#: ../inc/class-gitium-submenu-settings.php:108
|
||||
msgid "The file `.gitignore` could not be saved!"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:100
|
||||
msgid "Could not enable the maintenance mode!"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:102
|
||||
#: ../inc/class-gitium-submenu-status.php:196
|
||||
#, php-format
|
||||
msgid "Merged changes from %s on %s"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:109
|
||||
msgid "Could not commit!"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:114
|
||||
msgid "Merge failed: "
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:116
|
||||
#, php-format
|
||||
msgid "Pushed commit: `%s`"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:125
|
||||
#, php-format
|
||||
msgid "Following remote branch <code>%s</code>."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:127
|
||||
msgid "Everything is up to date"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:130
|
||||
#, php-format
|
||||
msgid "You are %s commits ahead and %s behind remote."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:132
|
||||
#, php-format
|
||||
msgid "You are %s commits ahead remote."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:134
|
||||
#, php-format
|
||||
msgid "You are %s commits behind remote."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:160
|
||||
msgid "Add this file to the `.gitignore` list."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:163
|
||||
msgid "Submodules are not supported in this version."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:175
|
||||
#: ../inc/class-gitium-submenu-status.php:176
|
||||
msgid "Path"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:175
|
||||
#: ../inc/class-gitium-submenu-status.php:176
|
||||
msgid "Change"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:181
|
||||
msgid "Nothing to commit, working directory clean."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:195
|
||||
msgid "Commit message"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:199
|
||||
msgid "Save changes"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-status.php:209
|
||||
msgid "connected to"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-settings.php:32 ../inc/class-gitium-help.php:81
|
||||
msgid "Settings"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-settings.php:46
|
||||
msgid ""
|
||||
"Webhook URL regenerates. Please make sure you update any external references."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-settings.php:55
|
||||
msgid "Public key successfully regenerated."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-settings.php:61
|
||||
msgid "Webhook URL"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-settings.php:65
|
||||
msgid "Regenerate Webhook"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-settings.php:67
|
||||
msgid "Pinging this URL triggers an update from remote repository."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-settings.php:77
|
||||
msgid "Public Key"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-settings.php:116
|
||||
msgid "Gitium Settings"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-settings.php:121
|
||||
msgid "Be careful when you modify this list!"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-settings.php:126
|
||||
msgid "Save"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:26
|
||||
msgid "Gitium"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:27
|
||||
msgid "F.A.Q."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:32
|
||||
msgid ""
|
||||
"Gitium enables continuous deployment for WordPress integrating with tools "
|
||||
"such as Github, Bitbucket or Travis-CI. Plugin and theme updates, installs "
|
||||
"and removals are automatically versioned."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:33
|
||||
msgid ""
|
||||
"Ninja code edits from the WordPress editor are also tracked into version "
|
||||
"control. Gitium is designed for sane development environments."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:34
|
||||
msgid ""
|
||||
"Staging and production can follow different branches of the same repository. "
|
||||
"You can deploy code simply trough git push."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:35
|
||||
msgid ""
|
||||
"Gitium requires <code>git</code> command line tool minimum version 1.7 "
|
||||
"installed on the server and <code>proc_open</code> PHP function enabled."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:39
|
||||
msgid "Is this plugin considered stable?"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:39
|
||||
msgid ""
|
||||
"Right now this plugin is considered alpha quality and should be used in "
|
||||
"production environments only by adventurous kinds."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:40
|
||||
msgid "What happens in case of conflicts?"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:40
|
||||
msgid ""
|
||||
"The behavior in case of conflicts is to overwrite the changes on the origin "
|
||||
"repository with the local changes (ie. local modifications take precedence "
|
||||
"over remote ones)."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:41
|
||||
msgid "How to deploy automatically after a push?"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:41
|
||||
msgid ""
|
||||
"You can ping the webhook url after a push to automatically deploy the new "
|
||||
"code. The webhook url can be found under Code menu. This url plays well with "
|
||||
"Github or Bitbucket webhooks."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:42
|
||||
msgid "Does it works on multi site setups?"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:42
|
||||
msgid "Gitium is not supporting multisite setups at the moment."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:43
|
||||
msgid "How does gitium handle submodules?"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:43
|
||||
msgid "Currently submodules are not supported."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:47
|
||||
msgid ""
|
||||
"In this step you must specify the <code>Remote URL</code>. This URL "
|
||||
"represents the link between the git sistem and your site."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:48
|
||||
msgid "You can get this URL from your Git repository and it looks like this:"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:49
|
||||
msgid "github.com -> git@github.com:user/example.git"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:50
|
||||
msgid "bitbucket.org -> git@bitbucket.org:user/glowing-happiness.git"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:51
|
||||
msgid ""
|
||||
"To go to the next step, fill the <code>Remote URL</code> and then press the "
|
||||
"<code>Fetch</code> button."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:52
|
||||
msgid ""
|
||||
"In this step you must select the <code>branch</code> you want to follow."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:53
|
||||
msgid "Only this branch will have all of your code modifications."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:54
|
||||
msgid ""
|
||||
"When you push the button <code>Merge & Push</code>, all code(plugins & "
|
||||
"themes) will be pushed on the git repository."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:64
|
||||
msgid ""
|
||||
"On status page you can see what files are modified, and you can commit the "
|
||||
"changes to git."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:69 ../inc/class-gitium-submenu-commits.php:29
|
||||
#: ../inc/class-gitium-submenu-commits.php:41
|
||||
msgid "Commits"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:74
|
||||
msgid ""
|
||||
"You may be wondering what is the difference between author and committer."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:75
|
||||
msgid ""
|
||||
"The <code>author</code> is the person who originally wrote the patch, "
|
||||
"whereas the <code>committer</code> is the person who last applied the patch."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:76
|
||||
msgid ""
|
||||
"So, if you send in a patch to a project and one of the core members applies "
|
||||
"the patch, both of you get credit — you as the author and the core member as "
|
||||
"the committer."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:86
|
||||
msgid "Each line from the gitignore file specifies a pattern."
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:87
|
||||
msgid ""
|
||||
"When deciding whether to ignore a path, Git normally checks gitignore "
|
||||
"patterns from multiple sources, with the following order of precedence, from "
|
||||
"highest to lowest (within one level of precedence, the last matching pattern "
|
||||
"decides the outcome)"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-help.php:88
|
||||
#, php-format
|
||||
msgid "Read more on %s"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-commits.php:28
|
||||
msgid "Git Commits"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-commits.php:61
|
||||
#, php-format
|
||||
msgid "Last %s commits"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-commits.php:70
|
||||
#, php-format
|
||||
msgid "committed %s ago"
|
||||
msgstr ""
|
||||
|
||||
#: ../inc/class-gitium-submenu-commits.php:82
|
||||
#, php-format
|
||||
msgid "authored %s ago"
|
||||
msgstr ""
|
239
wp-content/plugins/gitium/readme.txt
Normal file
239
wp-content/plugins/gitium/readme.txt
Normal file
@ -0,0 +1,239 @@
|
||||
=== Gitium ===
|
||||
|
||||
Contributors: PressLabs
|
||||
Donate link: https://www.presslabs.com/gitium/
|
||||
Tags: git, version, versioning, deployment, version-control, github, bitbucket, travis, code, revision, testing, development, branch, production, staging, debug, plugin, gitium, presslabs, simple
|
||||
Requires at least: 3.9
|
||||
Tested up to: 5.2.2
|
||||
Requires PHP: 5.6
|
||||
License: GPLv2
|
||||
Stable tag: 1.0.3
|
||||
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
|
||||
Automatic git version control and deployment for your plugins and themes integrated into wp-admin.
|
||||
|
||||
|
||||
== Description ==
|
||||
|
||||
Gitium enables continuous deployment for WordPress, integrating with tools such as Github, Bitbucket or Travis-CI. Theme or plugin updates, installs and removals are all automatically versioned. Ninja code edits from the WordPress editor are also tracked by the version control system.
|
||||
|
||||
Gitium is designed with sane development environments in mind, allowing staging and production to follow different branches of the same repository. You can also deploy code by simply using `git push`.
|
||||
|
||||
Gitium requires `git` command line tool with a minimum version of 1.7 installed on the server and the `proc_open` PHP function enabled.
|
||||
|
||||
You can find more documentation on [Presslabs](https://www.presslabs.com/help/gitium/general).
|
||||
|
||||
|
||||
== Screenshots ==
|
||||
|
||||
1. Setup step 1: Get SSH Key
|
||||
2. Setup step 2: Set SSH Key (Github)
|
||||
3. Setup step 3: Add remote repository
|
||||
4. Setup step 4: Choose following branch
|
||||
5. Commit local changes
|
||||
|
||||
|
||||
== Installation ==
|
||||
|
||||
= Manual Installation =
|
||||
1. Upload `gitium.zip` to the `/wp-content/plugins/` directory;
|
||||
2. Extract the `gitium.zip` archive into the `/wp-content/plugins/` directory;
|
||||
3. Activate the plugin through the 'Plugins' menu in WordPress.
|
||||
|
||||
Alternatively, go into your WordPress dashboard and click on Plugins -> Add Plugin and search for `Gitium`. Then, click on Install and, after that, on Activate Now.
|
||||
|
||||
|
||||
= Usage =
|
||||
|
||||
Activate the plugin and follow the on-screen instructions under the `Gitium` menu.
|
||||
|
||||
_IMPORTANT_: Gitium does its best not to version your WordPress core, neither your `/wp-content/uploads` folder.
|
||||
|
||||
== Frequently Asked Questions ==
|
||||
|
||||
= Could not connect to remote repository? =
|
||||
|
||||
If you encounter this kind of error you can try to fix it by setting the proper username of the .git directory.
|
||||
|
||||
Example: chown -R www-data:www-data .git
|
||||
|
||||
= Is this plugin considered stable? =
|
||||
|
||||
Yes, we consider the plugin stable after extensive usage in production environments at Presslabs, with hundreds of users and powering sites with hundreds of millions of pageviews per month.
|
||||
|
||||
= What will happen in case of conflicts? =
|
||||
|
||||
The behavior in case of conflicts is to overwrite the changes on the `origin` repository with the local changes (ie. local modifications take precedence over remote ones).
|
||||
|
||||
= How to deploy automatically after a push? =
|
||||
|
||||
You can ping the webhook url after a push to automatically deploy the new code. The webhook url can be found under `Gitium` menu, `Settings` section. This url also plays well with Github or Bitbucket webhooks.
|
||||
|
||||
= Does it works on multi site setups? =
|
||||
|
||||
Gitium does not support multisite setups at the moment.
|
||||
|
||||
= How does gitium handle submodules? =
|
||||
|
||||
Submodules are currently not supported.
|
||||
|
||||
== Upgrade Notice ==
|
||||
= 1.0.3 =
|
||||
Fixed wrong redirection for multisite installations during initial setup
|
||||
|
||||
== Changelog ==
|
||||
= 1.0.3 =
|
||||
* Fixed wrong redirection for multisite installations during initial setup
|
||||
|
||||
= 1.0.2 =
|
||||
* Full PHP 7+ compatibility
|
||||
* Hotfix - Fixed the blank pages being displayed instead of success of failure messages;
|
||||
* Hotfix - Fixed the push process when other remote branches had changes;
|
||||
* Hotfix - Fixed the missing ssh / key handling with fatal errors during activation;
|
||||
* Added - More success messages in certain cases.
|
||||
|
||||
= 1.0.1 =
|
||||
* Hotfix - Fix race condition on Code Editor Save
|
||||
|
||||
= 1.0 =
|
||||
* Fixed WP 4.9 Compatibility
|
||||
|
||||
= 1.0-rc12 =
|
||||
* Bumped plugin version
|
||||
|
||||
= 1.0-rc11 =
|
||||
* Hotfixed an error that prevented gitium to error_log properly.
|
||||
|
||||
= 1.0-rc10 =
|
||||
* Bumped wordpress tested version
|
||||
|
||||
= 1.0-rc9 =
|
||||
* PHP7 compat and wp-cli
|
||||
|
||||
= 1.0-rc8 =
|
||||
* Fix some indents
|
||||
* Add some more tests
|
||||
* Fix the submenu configure logic
|
||||
|
||||
= 1.0-rc7 =
|
||||
* Test remote url from git wrapper
|
||||
* Remove the phpmd package from test environment
|
||||
* Set WP_DEBUG to false on tests
|
||||
* Refactoring
|
||||
* Abort the cherry-pick - changes are already there
|
||||
* Fix the race condition
|
||||
* Add acquire and release logs for gitium lock
|
||||
* Add explanations to merge with accept mine logic
|
||||
|
||||
= 1.0-rc6 =
|
||||
* Delete all transients and options on uninstall hook
|
||||
* Add transients to is_versions and get_remote_tracking_branch functions
|
||||
* Update the composer
|
||||
* Check requirements before show the admin menu
|
||||
* Put the logs off by default(on test env)
|
||||
* Fix redirect issue and display errors
|
||||
* Create wordpress docker env command
|
||||
* PHP Warning: unlink #114
|
||||
|
||||
= 1.0-rc5 =
|
||||
* Fix delete plugin/theme bug on 4.6
|
||||
* Update the readme file
|
||||
|
||||
= 1.0-rc4 =
|
||||
* Fix merge with accept mine behind commits bug
|
||||
|
||||
= 1.0-rc3 =
|
||||
* Add support for multisite
|
||||
* Fix PHP error on merge & push
|
||||
|
||||
= 1.0-rc2 =
|
||||
* Change the default lockfile location
|
||||
* Fix a PHP Warning
|
||||
|
||||
= 1.0-rc1 =
|
||||
* Update the logic of merge and push
|
||||
* Add lock mechanism for fetch and merge
|
||||
* Fix repo stuck on merge_local branch
|
||||
* Tested up to 4.5.3
|
||||
|
||||
= 0.5.8-beta =
|
||||
* Add documentation for 'Could not connect to remote repository?'
|
||||
* Fix the update theme from Dashboard commit message & the install plugin commit message
|
||||
* Fix install/delete plugin/theme commit message
|
||||
* Add a test and rewrite the tests
|
||||
* Tested up to 4.5.2
|
||||
|
||||
= 0.5.7-beta =
|
||||
* Fix bug deleting plugins/themes causes wrong commit message
|
||||
* Fix bug wrong commit message
|
||||
* Fix bug updated function to stop maintenance mode hang
|
||||
* Fix bug undefined variable 'new_versions'
|
||||
* Add 'Merge changes' button for gitium webhook
|
||||
* Add gitium documentation for docker
|
||||
* Add more tests
|
||||
|
||||
= 0.5.6-beta =
|
||||
* Fix compatibility issues with wp-cli
|
||||
|
||||
= 0.5.5-beta =
|
||||
* Fix bug plugin deletion from plugins page did not trigger commit
|
||||
|
||||
= 0.5.4-beta =
|
||||
* Fix bug missing changes on similarly named plugins
|
||||
* Add requirements notices
|
||||
* Add requirements help section
|
||||
|
||||
= 0.5.3-beta =
|
||||
* Fix paths with spaces bug
|
||||
* Add a Disconnect from repo button
|
||||
* Fix POST var `path` conflicts
|
||||
* Fix travis tests
|
||||
|
||||
= 0.5.2-beta =
|
||||
* Add Contextual Help to Configuration page
|
||||
* Make the icon path relative
|
||||
* The key file is deleted properly
|
||||
* Update serbian translation
|
||||
* Make the resource type more specific
|
||||
* Fix Menu Bubble
|
||||
* Remove useless param for get_transient
|
||||
* Add Spanish Translation
|
||||
* Rename `gitium_version` transient
|
||||
* Fix git version notice
|
||||
* Delete .vimrc
|
||||
* Update .gitignore
|
||||
* Fix syntax error
|
||||
* Add better git version check
|
||||
* Fix add_query_arg vulnerability
|
||||
|
||||
= 0.5.1-beta =
|
||||
* Update Serbian Translation (by [Ogi Djuraskovic](http://firstsiteguide.com/))
|
||||
* Fix Menu Bubble
|
||||
|
||||
= 0.5-beta =
|
||||
* Add `Last 20 Commits` menu page
|
||||
* Add WordPress Contextual Help menu
|
||||
* Add `Settings` menu page
|
||||
* Move `Webhook URL` and `Public Key` fields to `Settings` page
|
||||
* Add menu icon
|
||||
* The `.gitignore` file can be edited
|
||||
* Fix commit message on theme/plugin update event
|
||||
* Refactoring
|
||||
|
||||
= 0.4-beta =
|
||||
* Add `Bitbucket` documentation link
|
||||
* Add the action `gitium_before_merge_with_accept_mine`
|
||||
* Moved to `travis-ci.org`
|
||||
* Add new tests
|
||||
* Added code climate coverage reporting
|
||||
* Refactoring
|
||||
|
||||
= 0.3.2-alpha =
|
||||
* Fix plugin activation issues
|
||||
|
||||
= 0.3.1-alpha =
|
||||
* Fix issues with ssh repositories
|
||||
* Fix maintemance mode when webhook fails
|
||||
|
||||
= 0.3-alpha =
|
||||
* First alpha release
|
61
wp-content/plugins/gp-premium/backgrounds/functions/css.php
Normal file
61
wp-content/plugins/gp-premium/backgrounds/functions/css.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
// No direct access, please
|
||||
if ( ! defined( 'ABSPATH' ) ) exit;
|
||||
|
||||
if ( ! class_exists( 'GeneratePress_Backgrounds_CSS' ) ) {
|
||||
class GeneratePress_Backgrounds_CSS {
|
||||
|
||||
protected $_selector = '';
|
||||
protected $_selector_output = '';
|
||||
protected $_css = '';
|
||||
protected $_output = '';
|
||||
|
||||
public function set_selector( $selector = '' ) {
|
||||
// Render the css in the output string everytime the selector changes
|
||||
if ( $this->_selector !== '' ) {
|
||||
$this->add_selector_rules_to_output();
|
||||
}
|
||||
|
||||
$this->_selector = $selector;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function add_property( $property, $value, $url = '' ) {
|
||||
// If we don't have a value or our value is the same as our og default, bail
|
||||
if ( empty( $value ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set up our background image URL param if needed
|
||||
$url_start = ( '' !== $url ) ? "url('" : "";
|
||||
$url_end = ( '' !== $url ) ? "')" : "";
|
||||
|
||||
$this->_css .= $property . ':' . $url_start . $value . $url_end . ';';
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function add_selector_rules_to_output() {
|
||||
if ( ! empty( $this->_css ) ) {
|
||||
$this->_selector_output = $this->_selector;
|
||||
$selector_output = sprintf( '%1$s{%2$s}', $this->_selector_output, $this->_css );
|
||||
|
||||
$this->_output .= $selector_output;
|
||||
|
||||
// Reset the css
|
||||
$this->_css = '';
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function css_output() {
|
||||
// Add current selector's rules to output
|
||||
$this->add_selector_rules_to_output();
|
||||
|
||||
// Output minified css
|
||||
return $this->_output;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
1315
wp-content/plugins/gp-premium/backgrounds/functions/functions.php
Normal file
1315
wp-content/plugins/gp-premium/backgrounds/functions/functions.php
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,424 @@
|
||||
<?php
|
||||
// No direct access, please
|
||||
if ( ! defined( 'ABSPATH' ) ) exit;
|
||||
|
||||
if ( ! function_exists( 'generate_backgrounds_secondary_nav_customizer' ) ) {
|
||||
add_action( 'customize_register', 'generate_backgrounds_secondary_nav_customizer', 1000 );
|
||||
/**
|
||||
* Adds our Secondary Nav background image options
|
||||
*
|
||||
* These options are in their own function so we can hook it in late to
|
||||
* make sure Secondary Nav is activated.
|
||||
*
|
||||
* 1000 priority is there to make sure Secondary Nav is registered (999)
|
||||
* as we check to see if the layout control exists.
|
||||
*
|
||||
* Secondary Nav now uses 100 as a priority.
|
||||
*/
|
||||
function generate_backgrounds_secondary_nav_customizer( $wp_customize ) {
|
||||
// Bail if we don't have our defaults
|
||||
if ( ! function_exists( 'generate_secondary_nav_get_defaults' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure Secondary Nav is activated
|
||||
if ( ! $wp_customize->get_section( 'secondary_nav_section' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get our defaults
|
||||
$defaults = generate_secondary_nav_get_defaults();
|
||||
|
||||
if ( method_exists( $wp_customize, 'register_control_type' ) ) {
|
||||
$wp_customize->register_control_type( 'GeneratePress_Section_Shortcut_Control' );
|
||||
}
|
||||
|
||||
// Get our controls
|
||||
require_once GP_LIBRARY_DIRECTORY . 'customizer-helpers.php';
|
||||
|
||||
// Add our section
|
||||
$wp_customize->add_section(
|
||||
'secondary_bg_images_section',
|
||||
array(
|
||||
'title' => __( 'Secondary Navigation', 'gp-premium' ),
|
||||
'capability' => 'edit_theme_options',
|
||||
'description' => '',
|
||||
'panel' => 'generate_backgrounds_panel',
|
||||
'priority' => 21,
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_control(
|
||||
new GeneratePress_Section_Shortcut_Control(
|
||||
$wp_customize,
|
||||
'generate_secondary_navigation_background_image_shortcuts',
|
||||
array(
|
||||
'section' => 'secondary_bg_images_section',
|
||||
'element' => __( 'Secondary Navigation', 'gp-premium' ),
|
||||
'shortcuts' => array(
|
||||
'layout' => 'secondary_nav_section',
|
||||
'colors' => 'secondary_navigation_color_section',
|
||||
'typography' => 'secondary_font_section',
|
||||
),
|
||||
'settings' => ( isset( $wp_customize->selective_refresh ) ) ? array() : 'blogname',
|
||||
'priority' => 1,
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// Background
|
||||
$wp_customize->add_setting(
|
||||
'generate_secondary_nav_settings[nav_image]', array(
|
||||
'default' => $defaults['nav_image'],
|
||||
'type' => 'option',
|
||||
'capability' => 'edit_theme_options',
|
||||
'sanitize_callback' => 'esc_url_raw',
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_control(
|
||||
new WP_Customize_Image_Control(
|
||||
$wp_customize,
|
||||
'generate_secondary_backgrounds-nav-image',
|
||||
array(
|
||||
'section' => 'secondary_bg_images_section',
|
||||
'settings' => 'generate_secondary_nav_settings[nav_image]',
|
||||
'priority' => 750,
|
||||
'label' => __( 'Navigation', 'gp-premium' ),
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// Repeat
|
||||
$wp_customize->add_setting(
|
||||
'generate_secondary_nav_settings[nav_repeat]',
|
||||
array(
|
||||
'default' => $defaults['nav_repeat'],
|
||||
'type' => 'option',
|
||||
'sanitize_callback' => 'generate_premium_sanitize_choices',
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_control(
|
||||
'generate_secondary_nav_settings[nav_repeat]',
|
||||
array(
|
||||
'type' => 'select',
|
||||
'section' => 'secondary_bg_images_section',
|
||||
'choices' => array(
|
||||
'' => __( 'Repeat', 'gp-premium' ),
|
||||
'repeat-x' => __( 'Repeat x', 'gp-premium' ),
|
||||
'repeat-y' => __( 'Repeat y', 'gp-premium' ),
|
||||
'no-repeat' => __( 'No Repeat', 'gp-premium' ),
|
||||
),
|
||||
'settings' => 'generate_secondary_nav_settings[nav_repeat]',
|
||||
'priority' => 800
|
||||
)
|
||||
);
|
||||
|
||||
// Item background
|
||||
$wp_customize->add_setting(
|
||||
'generate_secondary_nav_settings[nav_item_image]', array(
|
||||
'default' => $defaults['nav_item_image'],
|
||||
'type' => 'option',
|
||||
'capability' => 'edit_theme_options',
|
||||
'sanitize_callback' => 'esc_url_raw',
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_control(
|
||||
new WP_Customize_Image_Control(
|
||||
$wp_customize,
|
||||
'generate_secondary_backgrounds-nav-item-image',
|
||||
array(
|
||||
'section' => 'secondary_bg_images_section',
|
||||
'settings' => 'generate_secondary_nav_settings[nav_item_image]',
|
||||
'priority' => 950,
|
||||
'label' => __( 'Navigation Item', 'gp-premium' ),
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// Item repeat
|
||||
$wp_customize->add_setting(
|
||||
'generate_secondary_nav_settings[nav_item_repeat]',
|
||||
array(
|
||||
'default' => $defaults['nav_item_repeat'],
|
||||
'type' => 'option',
|
||||
'sanitize_callback' => 'generate_premium_sanitize_choices',
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_control(
|
||||
'generate_secondary_nav_settings[nav_item_repeat]',
|
||||
array(
|
||||
'type' => 'select',
|
||||
'section' => 'secondary_bg_images_section',
|
||||
'choices' => array(
|
||||
'' => __( 'Repeat', 'gp-premium' ),
|
||||
'repeat-x' => __( 'Repeat x', 'gp-premium' ),
|
||||
'repeat-y' => __( 'Repeat y', 'gp-premium' ),
|
||||
'no-repeat' => __( 'No Repeat', 'gp-premium' ),
|
||||
),
|
||||
'settings' => 'generate_secondary_nav_settings[nav_item_repeat]',
|
||||
'priority' => 1000
|
||||
)
|
||||
);
|
||||
|
||||
// Item hover
|
||||
$wp_customize->add_setting(
|
||||
'generate_secondary_nav_settings[nav_item_hover_image]', array(
|
||||
'default' => $defaults['nav_item_hover_image'],
|
||||
'type' => 'option',
|
||||
'capability' => 'edit_theme_options',
|
||||
'sanitize_callback' => 'esc_url_raw',
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_control(
|
||||
new WP_Customize_Image_Control(
|
||||
$wp_customize,
|
||||
'generate_secondary_backgrounds-nav-item-hover-image',
|
||||
array(
|
||||
'section' => 'secondary_bg_images_section',
|
||||
'settings' => 'generate_secondary_nav_settings[nav_item_hover_image]',
|
||||
'priority' => 1150,
|
||||
'label' => __( 'Navigation Item Hover', 'gp-premium' ),
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// Item hover repeat
|
||||
$wp_customize->add_setting(
|
||||
'generate_secondary_nav_settings[nav_item_hover_repeat]',
|
||||
array(
|
||||
'default' => $defaults['nav_item_hover_repeat'],
|
||||
'type' => 'option',
|
||||
'sanitize_callback' => 'generate_premium_sanitize_choices',
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_control(
|
||||
'generate_secondary_nav_settings[nav_item_hover_repeat]',
|
||||
array(
|
||||
'type' => 'select',
|
||||
'section' => 'secondary_bg_images_section',
|
||||
'choices' => array(
|
||||
'' => __( 'Repeat', 'gp-premium' ),
|
||||
'repeat-x' => __( 'Repeat x', 'gp-premium' ),
|
||||
'repeat-y' => __( 'Repeat y', 'gp-premium' ),
|
||||
'no-repeat' => __( 'No Repeat', 'gp-premium' ),
|
||||
),
|
||||
'settings' => 'generate_secondary_nav_settings[nav_item_hover_repeat]',
|
||||
'priority' => 1200,
|
||||
)
|
||||
);
|
||||
|
||||
// Current background
|
||||
$wp_customize->add_setting(
|
||||
'generate_secondary_nav_settings[nav_item_current_image]', array(
|
||||
'default' => $defaults['nav_item_current_image'],
|
||||
'type' => 'option',
|
||||
'capability' => 'edit_theme_options',
|
||||
'sanitize_callback' => 'esc_url_raw',
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_control(
|
||||
new WP_Customize_Image_Control(
|
||||
$wp_customize,
|
||||
'generate_secondary_backgrounds-nav-item-current-image',
|
||||
array(
|
||||
'section' => 'secondary_bg_images_section',
|
||||
'settings' => 'generate_secondary_nav_settings[nav_item_current_image]',
|
||||
'priority' => 1350,
|
||||
'label' => __( 'Navigation Item Current', 'gp-premium' ),
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// Current repeat
|
||||
$wp_customize->add_setting(
|
||||
'generate_secondary_nav_settings[nav_item_current_repeat]',
|
||||
array(
|
||||
'default' => $defaults['nav_item_current_repeat'],
|
||||
'type' => 'option',
|
||||
'sanitize_callback' => 'generate_premium_sanitize_choices',
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_control(
|
||||
'generate_secondary_nav_settings[nav_item_current_repeat]',
|
||||
array(
|
||||
'type' => 'select',
|
||||
'section' => 'secondary_bg_images_section',
|
||||
'choices' => array(
|
||||
'' => __( 'Repeat', 'gp-premium' ),
|
||||
'repeat-x' => __( 'Repeat x', 'gp-premium' ),
|
||||
'repeat-y' => __( 'Repeat y', 'gp-premium' ),
|
||||
'no-repeat' => __( 'No Repeat', 'gp-premium' ),
|
||||
),
|
||||
'settings' => 'generate_secondary_nav_settings[nav_item_current_repeat]',
|
||||
'priority' => 1400,
|
||||
)
|
||||
);
|
||||
|
||||
// Sub-navigation section
|
||||
$wp_customize->add_section(
|
||||
'secondary_subnav_bg_images_section',
|
||||
array(
|
||||
'title' => __( 'Secondary Sub-Navigation', 'gp-premium' ),
|
||||
'capability' => 'edit_theme_options',
|
||||
'description' => '',
|
||||
'panel' => 'generate_backgrounds_panel',
|
||||
'priority' => 22,
|
||||
)
|
||||
);
|
||||
|
||||
// Item background
|
||||
$wp_customize->add_setting(
|
||||
'generate_secondary_nav_settings[sub_nav_item_image]', array(
|
||||
'default' => $defaults['sub_nav_item_image'],
|
||||
'type' => 'option',
|
||||
'capability' => 'edit_theme_options',
|
||||
'sanitize_callback' => 'esc_url_raw',
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_control(
|
||||
new WP_Customize_Image_Control(
|
||||
$wp_customize,
|
||||
'generate_secondary_backgrounds-sub-nav-item-image',
|
||||
array(
|
||||
'section' => 'secondary_subnav_bg_images_section',
|
||||
'settings' => 'generate_secondary_nav_settings[sub_nav_item_image]',
|
||||
'priority' => 1700,
|
||||
'label' => __( 'Sub-Navigation Item', 'gp-premium' ),
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// Item repeat
|
||||
$wp_customize->add_setting(
|
||||
'generate_secondary_nav_settings[sub_nav_item_repeat]',
|
||||
array(
|
||||
'default' => $defaults['sub_nav_item_repeat'],
|
||||
'type' => 'option',
|
||||
'sanitize_callback' => 'generate_premium_sanitize_choices',
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_control(
|
||||
'generate_secondary_nav_settings[sub_nav_item_repeat]',
|
||||
array(
|
||||
'type' => 'select',
|
||||
'section' => 'secondary_subnav_bg_images_section',
|
||||
'choices' => array(
|
||||
'' => __( 'Repeat', 'gp-premium' ),
|
||||
'repeat-x' => __( 'Repeat x', 'gp-premium' ),
|
||||
'repeat-y' => __( 'Repeat y', 'gp-premium' ),
|
||||
'no-repeat' => __( 'No Repeat', 'gp-premium' ),
|
||||
),
|
||||
'settings' => 'generate_secondary_nav_settings[sub_nav_item_repeat]',
|
||||
'priority' => 1800
|
||||
)
|
||||
);
|
||||
|
||||
// Item hover
|
||||
$wp_customize->add_setting(
|
||||
'generate_secondary_nav_settings[sub_nav_item_hover_image]', array(
|
||||
'default' => $defaults['sub_nav_item_hover_image'],
|
||||
'type' => 'option',
|
||||
'capability' => 'edit_theme_options',
|
||||
'sanitize_callback' => 'esc_url_raw',
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_control(
|
||||
new WP_Customize_Image_Control(
|
||||
$wp_customize,
|
||||
'generate_secondary_backgrounds-sub-nav-item-hover-image',
|
||||
array(
|
||||
'section' => 'secondary_subnav_bg_images_section',
|
||||
'settings' => 'generate_secondary_nav_settings[sub_nav_item_hover_image]',
|
||||
'priority' => 2000,
|
||||
'label' => __( 'Sub-Navigation Item Hover', 'gp-premium' ),
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// Item hover repeat
|
||||
$wp_customize->add_setting(
|
||||
'generate_secondary_nav_settings[sub_nav_item_hover_repeat]',
|
||||
array(
|
||||
'default' => $defaults['sub_nav_item_hover_repeat'],
|
||||
'type' => 'option',
|
||||
'sanitize_callback' => 'generate_premium_sanitize_choices',
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_control(
|
||||
'generate_secondary_nav_settings[sub_nav_item_hover_repeat]',
|
||||
array(
|
||||
'type' => 'select',
|
||||
'section' => 'secondary_subnav_bg_images_section',
|
||||
'choices' => array(
|
||||
'' => __( 'Repeat', 'gp-premium' ),
|
||||
'repeat-x' => __( 'Repeat x', 'gp-premium' ),
|
||||
'repeat-y' => __( 'Repeat y', 'gp-premium' ),
|
||||
'no-repeat' => __( 'No Repeat', 'gp-premium' ),
|
||||
),
|
||||
'settings' => 'generate_secondary_nav_settings[sub_nav_item_hover_repeat]',
|
||||
'priority' => 2100,
|
||||
)
|
||||
);
|
||||
|
||||
// Current background
|
||||
$wp_customize->add_setting(
|
||||
'generate_secondary_nav_settings[sub_nav_item_current_image]', array(
|
||||
'default' => $defaults['sub_nav_item_current_image'],
|
||||
'type' => 'option',
|
||||
'capability' => 'edit_theme_options',
|
||||
'sanitize_callback' => 'esc_url_raw',
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_control(
|
||||
new WP_Customize_Image_Control(
|
||||
$wp_customize,
|
||||
'generate_secondary_backgrounds-sub-nav-item-current-image',
|
||||
array(
|
||||
'section' => 'secondary_subnav_bg_images_section',
|
||||
'settings' => 'generate_secondary_nav_settings[sub_nav_item_current_image]',
|
||||
'priority' => 2300,
|
||||
'label' => __( 'Sub-Navigation Item Current', 'gp-premium' ),
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// Current background repeat
|
||||
$wp_customize->add_setting(
|
||||
'generate_secondary_nav_settings[sub_nav_item_current_repeat]',
|
||||
array(
|
||||
'default' => $defaults['sub_nav_item_current_repeat'],
|
||||
'type' => 'option',
|
||||
'sanitize_callback' => 'generate_premium_sanitize_choices',
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_control(
|
||||
'generate_secondary_nav_settings[sub_nav_item_current_repeat]',
|
||||
array(
|
||||
'type' => 'select',
|
||||
'section' => 'secondary_subnav_bg_images_section',
|
||||
'choices' => array(
|
||||
'' => __( 'Repeat', 'gp-premium' ),
|
||||
'repeat-x' => __( 'Repeat x', 'gp-premium' ),
|
||||
'repeat-y' => __( 'Repeat y', 'gp-premium' ),
|
||||
'no-repeat' => __( 'No Repeat', 'gp-premium' ),
|
||||
),
|
||||
'settings' => 'generate_secondary_nav_settings[sub_nav_item_current_repeat]',
|
||||
'priority' => 2400,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
/*
|
||||
Addon Name: Generate Backgrounds
|
||||
Author: Thomas Usborne
|
||||
Author URI: http://edge22.com
|
||||
*/
|
||||
|
||||
// No direct access, please
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Define the version
|
||||
if ( ! defined( 'GENERATE_BACKGROUNDS_VERSION' ) ) {
|
||||
define( 'GENERATE_BACKGROUNDS_VERSION', GP_PREMIUM_VERSION );
|
||||
}
|
||||
|
||||
// Include functions identical between standalone addon and GP Premium
|
||||
require plugin_dir_path( __FILE__ ) . 'functions/functions.php';
|
157
wp-content/plugins/gp-premium/blog/functions/columns.php
Normal file
157
wp-content/plugins/gp-premium/blog/functions/columns.php
Normal file
@ -0,0 +1,157 @@
|
||||
<?php
|
||||
defined( 'WPINC' ) or die;
|
||||
|
||||
if ( ! function_exists( 'generate_blog_get_columns' ) ) {
|
||||
/**
|
||||
* Initiate columns.
|
||||
*
|
||||
* @since 0.1
|
||||
*/
|
||||
function generate_blog_get_columns() {
|
||||
$generate_blog_settings = wp_parse_args(
|
||||
get_option( 'generate_blog_settings', array() ),
|
||||
generate_blog_get_defaults()
|
||||
);
|
||||
|
||||
// If columns are enabled, set to true
|
||||
$columns = ( true == $generate_blog_settings['column_layout'] ) ? true : false;
|
||||
|
||||
// If we're not dealing with posts, set it to false.
|
||||
// Check for is_home() to prevent bug in Yoast that throws off the post type check.
|
||||
$columns = ( 'post' == get_post_type() || is_search() || is_home() ) ? $columns : false;
|
||||
|
||||
// If masonry is enabled via filter, enable columns
|
||||
$columns = ( 'true' == apply_filters( 'generate_blog_masonry', 'false' ) ) ? true : $columns;
|
||||
|
||||
// If we're on a singular post or page, disable
|
||||
$columns = ( is_singular() ) ? false : $columns;
|
||||
|
||||
// Turn off columns if we're on a WooCommerce search page
|
||||
if ( function_exists( 'is_woocommerce' ) ) {
|
||||
$columns = ( is_woocommerce() && is_search() ) ? false : $columns;
|
||||
}
|
||||
|
||||
// Bail if there's no search results
|
||||
if ( is_search() ) {
|
||||
global $wp_query;
|
||||
if ( 0 == $wp_query->post_count ) {
|
||||
$columns = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the result
|
||||
return apply_filters( 'generate_blog_columns', $columns );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'generate_blog_get_masonry' ) ) {
|
||||
/**
|
||||
* Check if masonry is enabled.
|
||||
* This function is a mess with strings as bools etc.. Will re-write in a big upate to get lots of testing.
|
||||
*/
|
||||
function generate_blog_get_masonry() {
|
||||
$generate_blog_settings = wp_parse_args(
|
||||
get_option( 'generate_blog_settings', array() ),
|
||||
generate_blog_get_defaults()
|
||||
);
|
||||
|
||||
// If masonry is enabled via option or filter, enable it.
|
||||
if ( $generate_blog_settings['masonry'] || 'true' == apply_filters( 'generate_blog_masonry', 'false' ) ) {
|
||||
$masonry = 'true';
|
||||
} else {
|
||||
$masonry = 'false';
|
||||
}
|
||||
|
||||
// Allow masonry to be turned off using a boolean.
|
||||
if ( false === apply_filters( 'generate_blog_masonry', 'false' ) ) {
|
||||
$masonry = 'false';
|
||||
}
|
||||
|
||||
return $masonry;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'generate_blog_add_columns_container' ) ) {
|
||||
add_action( 'generate_before_main_content', 'generate_blog_add_columns_container' );
|
||||
/**
|
||||
* Add columns container
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
function generate_blog_add_columns_container() {
|
||||
if ( ! generate_blog_get_columns() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$columns = generate_blog_get_column_count();
|
||||
|
||||
printf(
|
||||
'<div class="generate-columns-container %1$s">%2$s',
|
||||
'false' !== generate_blog_get_masonry() ? 'masonry-container are-images-unloaded' : '',
|
||||
'false' !== generate_blog_get_masonry() ? '<div class="grid-sizer ' . esc_attr( 'grid-' . esc_attr( $columns ) ) . ' tablet-grid-50 mobile-grid-100"></div>' : ''
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'generate_blog_add_ending_columns_container' ) ) {
|
||||
add_action( 'generate_after_main_content', 'generate_blog_add_ending_columns_container' );
|
||||
/**
|
||||
* Add closing columns container
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
function generate_blog_add_ending_columns_container() {
|
||||
if ( ! generate_blog_get_columns() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
echo '</div><!-- .generate-columns-contaier -->';
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'generate_blog_columns_css' ) ) {
|
||||
/**
|
||||
* Add inline CSS
|
||||
*/
|
||||
function generate_blog_columns_css() {
|
||||
$generate_blog_settings = wp_parse_args(
|
||||
get_option( 'generate_blog_settings', array() ),
|
||||
generate_blog_get_defaults()
|
||||
);
|
||||
|
||||
if ( function_exists( 'generate_spacing_get_defaults' ) ) {
|
||||
$spacing_settings = wp_parse_args(
|
||||
get_option( 'generate_spacing_settings', array() ),
|
||||
generate_spacing_get_defaults()
|
||||
);
|
||||
}
|
||||
|
||||
$separator = ( function_exists('generate_spacing_get_defaults') ) ? absint( $spacing_settings['separator'] ) : 20;
|
||||
|
||||
$return = '';
|
||||
if ( generate_blog_get_columns() ) {
|
||||
$return .= '.generate-columns {margin-bottom: ' . $separator . 'px;padding-left: ' . $separator . 'px;}';
|
||||
$return .= '.generate-columns-container {margin-left: -' . $separator . 'px;}';
|
||||
$return .= '.page-header {margin-bottom: ' . $separator . 'px;margin-left: ' . $separator . 'px}';
|
||||
$return .= '.generate-columns-container > .paging-navigation {margin-left: ' . $separator . 'px;}';
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'generate_blog_get_column_count' ) ) {
|
||||
/**
|
||||
* Get our column grid class
|
||||
*/
|
||||
function generate_blog_get_column_count() {
|
||||
$generate_blog_settings = wp_parse_args(
|
||||
get_option( 'generate_blog_settings', array() ),
|
||||
generate_blog_get_defaults()
|
||||
);
|
||||
|
||||
$count = $generate_blog_settings['columns'];
|
||||
|
||||
return apply_filters( 'generate_blog_get_column_count', $count );
|
||||
}
|
||||
}
|
1
wp-content/plugins/gp-premium/blog/functions/css/style-min.css
vendored
Normal file
1
wp-content/plugins/gp-premium/blog/functions/css/style-min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
224
wp-content/plugins/gp-premium/blog/functions/css/style.css
Normal file
224
wp-content/plugins/gp-premium/blog/functions/css/style.css
Normal file
@ -0,0 +1,224 @@
|
||||
.post-image-above-header .inside-article .post-image,
|
||||
.post-image-above-header .inside-article .featured-image {
|
||||
margin-top:0;
|
||||
margin-bottom:2em;
|
||||
}
|
||||
|
||||
.post-image-aligned-left .inside-article .post-image,
|
||||
.post-image-aligned-left .inside-article .featured-image {
|
||||
margin-top:0;
|
||||
margin-right:2em;
|
||||
float:left;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.post-image-aligned-center .post-image,
|
||||
.post-image-aligned-center .featured-image {
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
.post-image-aligned-right .inside-article .post-image,
|
||||
.post-image-aligned-right .inside-article .featured-image {
|
||||
margin-top:0;
|
||||
margin-left:2em;
|
||||
float:right;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.post-image-below-header.post-image-aligned-right .inside-article .post-image,
|
||||
.post-image-below-header.post-image-aligned-right .inside-article .featured-image,
|
||||
.post-image-below-header.post-image-aligned-center .inside-article .featured-image,
|
||||
.post-image-below-header.post-image-aligned-left .inside-article .post-image,
|
||||
.post-image-below-header.post-image-aligned-left .inside-article .featured-image {
|
||||
margin-top:2em;
|
||||
}
|
||||
|
||||
.post-image-aligned-left > .featured-image,
|
||||
.post-image-aligned-right > .featured-image {
|
||||
float: none;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.post-image-aligned-left .featured-image {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.post-image-aligned-right .featured-image {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.post-image-aligned-left .inside-article:before,
|
||||
.post-image-aligned-left .inside-article:after,
|
||||
.post-image-aligned-right .inside-article:before,
|
||||
.post-image-aligned-right .inside-article:after {
|
||||
content: "";
|
||||
display: table;
|
||||
}
|
||||
|
||||
.post-image-aligned-left .inside-article:after,
|
||||
.post-image-aligned-right .inside-article:after {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.post-image-aligned-left .inside-article,
|
||||
.post-image-aligned-right .inside-article {
|
||||
zoom: 1; /* For IE 6/7 (trigger hasLayout) */
|
||||
}
|
||||
|
||||
.one-container.right-sidebar.post-image-aligned-center .no-featured-image-padding .post-image,
|
||||
.one-container.both-right.post-image-aligned-center .no-featured-image-padding .post-image,
|
||||
.one-container.right-sidebar.post-image-aligned-center .no-featured-image-padding .featured-image,
|
||||
.one-container.both-right.post-image-aligned-center .no-featured-image-padding .featured-image {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.one-container.left-sidebar.post-image-aligned-center .no-featured-image-padding .post-image,
|
||||
.one-container.both-left.post-image-aligned-center .no-featured-image-padding .post-image,
|
||||
.one-container.left-sidebar.post-image-aligned-center .no-featured-image-padding .featured-image,
|
||||
.one-container.both-left.post-image-aligned-center .no-featured-image-padding .featured-image {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.one-container.both-sidebars.post-image-aligned-center .no-featured-image-padding .post-image,
|
||||
.one-container.both-sidebars.post-image-aligned-center .no-featured-image-padding .featured-image,
|
||||
.one-container.post-image-aligned-center .no-featured-image-padding.generate-columns .post-image,
|
||||
.one-container.post-image-aligned-center .no-featured-image-padding.generate-columns .featured-image {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.masonry-enabled .page-header {
|
||||
position: relative !important;
|
||||
}
|
||||
|
||||
.separate-containers .site-main > .generate-columns-container {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.masonry-container.are-images-unloaded,
|
||||
.load-more.are-images-unloaded,
|
||||
.masonry-enabled #nav-below {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
/* columns */
|
||||
.generate-columns-container:not(.masonry-container) {
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-flex-flow: row wrap;
|
||||
-ms-flex-flow: row wrap;
|
||||
flex-flow: row wrap;
|
||||
|
||||
-webkit-align-items: stretch;
|
||||
-ms-flex-align: stretch;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.generate-columns-container:not(.masonry-container) .generate-columns {
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.generate-columns .inside-article {
|
||||
width: 100%;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.generate-columns-activated.post-image-aligned-left .generate-columns-container article:not(.featured-column) .post-image,
|
||||
.generate-columns-activated.post-image-aligned-right .generate-columns-container article:not(.featured-column) .post-image {
|
||||
float: none;
|
||||
text-align: center;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.generate-columns-container .paging-navigation,
|
||||
.generate-columns-container .page-header {
|
||||
-webkit-box-flex: 1;
|
||||
-webkit-flex: 1 1 100%;
|
||||
-ms-flex: 1 1 100%;
|
||||
flex: 1 1 100%;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.generate-columns-container .paging-navigation {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.no-sidebar .generate-columns-container .inside-article > * {
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.load-more:not(.has-svg-icon) .button.loading:before {
|
||||
content: "\e900";
|
||||
display: inline-block;
|
||||
font-family: "GP Premium";
|
||||
speak: none;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
line-height: 1;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-animation: spin 2s infinite linear;
|
||||
animation: spin 2s infinite linear;
|
||||
margin-right: 7px;
|
||||
}
|
||||
|
||||
.load-more .button:not(.loading) .gp-icon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.load-more .gp-icon svg {
|
||||
-webkit-animation: spin 2s infinite linear;
|
||||
animation: spin 2s infinite linear;
|
||||
margin-right: 7px;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.generate-columns-activated .generate-columns-container {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
.generate-columns-container > * {
|
||||
padding-left: 0;
|
||||
}
|
||||
.generate-columns-container .page-header {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width:768px) {
|
||||
body:not(.post-image-aligned-center) .inside-article .post-image,
|
||||
body:not(.post-image-aligned-center) .featured-image,
|
||||
body:not(.post-image-aligned-center) .inside-article .featured-image {
|
||||
margin-right: 0;
|
||||
margin-left: 0;
|
||||
float: none;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.load-more {
|
||||
display: block;
|
||||
text-align:center;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
1115
wp-content/plugins/gp-premium/blog/functions/customizer.php
Normal file
1115
wp-content/plugins/gp-premium/blog/functions/customizer.php
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user