Compare commits
3 Commits
d56d46490a
...
6c5e503eb2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6c5e503eb2 | ||
|
|
b01e7e0e88 | ||
|
|
158fb53d24 |
BIN
dist/oribi-tech-sync.zip
vendored
BIN
dist/oribi-tech-sync.zip
vendored
Binary file not shown.
@@ -8,6 +8,168 @@
|
|||||||
|
|
||||||
if ( ! defined( 'ABSPATH' ) ) exit;
|
if ( ! defined( 'ABSPATH' ) ) exit;
|
||||||
|
|
||||||
|
// ─── Admin bar pull buttons (front-end) ─────────────────────────────────────
|
||||||
|
add_action( 'admin_bar_menu', function ( WP_Admin_Bar $wp_admin_bar ) {
|
||||||
|
if ( is_admin() ) return;
|
||||||
|
if ( ! is_user_logged_in() ) return;
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) return;
|
||||||
|
|
||||||
|
// "Pull All" — visible everywhere on the front-end
|
||||||
|
$wp_admin_bar->add_node( [
|
||||||
|
'id' => 'oribi-sync-pull-all',
|
||||||
|
'title' => '<span class="ab-icon dashicons dashicons-update" aria-hidden="true"></span><span class="ab-label">Pull All</span>',
|
||||||
|
'href' => '#',
|
||||||
|
'meta' => [
|
||||||
|
'title' => 'Pull all pages and theme from Git',
|
||||||
|
],
|
||||||
|
] );
|
||||||
|
|
||||||
|
// "Pull Page" — only on singular pages/posts
|
||||||
|
if ( is_singular() ) {
|
||||||
|
$post = get_queried_object();
|
||||||
|
if ( $post instanceof WP_Post ) {
|
||||||
|
$wp_admin_bar->add_node( [
|
||||||
|
'id' => 'oribi-sync-pull',
|
||||||
|
'title' => '<span class="ab-icon dashicons dashicons-download" aria-hidden="true"></span><span class="ab-label">Pull Page</span>',
|
||||||
|
'href' => '#',
|
||||||
|
'meta' => [
|
||||||
|
'title' => 'Pull this page and theme from Git',
|
||||||
|
],
|
||||||
|
] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 100 );
|
||||||
|
|
||||||
|
// AJAX handler for the admin bar "Pull All" button
|
||||||
|
add_action( 'wp_ajax_oribi_sync_pull_all_pages', function () {
|
||||||
|
check_ajax_referer( 'oribi_sync_pull_all_pages' );
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) wp_send_json_error( 'Permission denied.', 403 );
|
||||||
|
|
||||||
|
$result = oribi_sync_run();
|
||||||
|
$result['ok'] ? wp_send_json_success( $result ) : wp_send_json_error( $result, 500 );
|
||||||
|
} );
|
||||||
|
|
||||||
|
// AJAX handler for the admin bar pull button (no REST API exposure)
|
||||||
|
add_action( 'wp_ajax_oribi_sync_pull_page', function () {
|
||||||
|
check_ajax_referer( 'oribi_sync_pull_page' );
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) wp_send_json_error( 'Permission denied.', 403 );
|
||||||
|
|
||||||
|
$post_id = (int) ( $_POST['post_id'] ?? 0 );
|
||||||
|
if ( $post_id < 1 ) wp_send_json_error( 'Missing or invalid post_id.', 400 );
|
||||||
|
|
||||||
|
$result = oribi_sync_pull_page_from_repo( $post_id );
|
||||||
|
$result['ok'] ? wp_send_json_success( $result ) : wp_send_json_error( $result, 500 );
|
||||||
|
} );
|
||||||
|
|
||||||
|
// Front-end script for the "Pull All" admin bar button
|
||||||
|
add_action( 'wp_footer', function () {
|
||||||
|
if ( ! is_user_logged_in() ) return;
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) return;
|
||||||
|
if ( ! is_admin_bar_showing() ) return;
|
||||||
|
|
||||||
|
$ajax_url = admin_url( 'admin-ajax.php' );
|
||||||
|
$nonce_all = wp_create_nonce( 'oribi_sync_pull_all_pages' );
|
||||||
|
?>
|
||||||
|
<script>
|
||||||
|
(function () {
|
||||||
|
'use strict';
|
||||||
|
var btn = document.getElementById('wp-admin-bar-oribi-sync-pull-all');
|
||||||
|
if (!btn) return;
|
||||||
|
|
||||||
|
btn.addEventListener('click', function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
var link = btn.querySelector('a');
|
||||||
|
var label = btn.querySelector('.ab-label');
|
||||||
|
if (link) { link.style.opacity = '0.5'; link.style.pointerEvents = 'none'; }
|
||||||
|
if (label) { label.textContent = 'Pulling…'; }
|
||||||
|
|
||||||
|
var data = new URLSearchParams({
|
||||||
|
action: 'oribi_sync_pull_all_pages',
|
||||||
|
_ajax_nonce: <?php echo wp_json_encode( $nonce_all ); ?>
|
||||||
|
});
|
||||||
|
|
||||||
|
fetch(<?php echo wp_json_encode( $ajax_url ); ?>, {
|
||||||
|
method: 'POST',
|
||||||
|
credentials: 'same-origin',
|
||||||
|
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||||
|
body: data.toString()
|
||||||
|
})
|
||||||
|
.then(function (r) { return r.json(); })
|
||||||
|
.then(function () {
|
||||||
|
var url = new URL(window.location.href);
|
||||||
|
url.searchParams.set('_nocache', Date.now());
|
||||||
|
window.location.replace(url.toString());
|
||||||
|
})
|
||||||
|
.catch(function (err) {
|
||||||
|
if (label) { label.textContent = 'Pull All'; }
|
||||||
|
if (link) { link.style.opacity = ''; link.style.pointerEvents = ''; }
|
||||||
|
alert('Oribi Sync pull failed: ' + err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
<?php
|
||||||
|
} );
|
||||||
|
|
||||||
|
// Front-end script that wires up the admin bar pull button
|
||||||
|
add_action( 'wp_footer', function () {
|
||||||
|
if ( ! is_user_logged_in() ) return;
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) return;
|
||||||
|
if ( ! is_singular() ) return;
|
||||||
|
if ( ! is_admin_bar_showing() ) return;
|
||||||
|
|
||||||
|
$post = get_queried_object();
|
||||||
|
if ( ! $post instanceof WP_Post ) return;
|
||||||
|
|
||||||
|
$ajax_url = admin_url( 'admin-ajax.php' );
|
||||||
|
$nonce = wp_create_nonce( 'oribi_sync_pull_page' );
|
||||||
|
$post_id = (int) $post->ID;
|
||||||
|
?>
|
||||||
|
<script>
|
||||||
|
(function () {
|
||||||
|
'use strict';
|
||||||
|
var btn = document.getElementById('wp-admin-bar-oribi-sync-pull');
|
||||||
|
if (!btn) return;
|
||||||
|
|
||||||
|
btn.addEventListener('click', function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
var link = btn.querySelector('a');
|
||||||
|
var label = btn.querySelector('.ab-label');
|
||||||
|
if (link) { link.style.opacity = '0.5'; link.style.pointerEvents = 'none'; }
|
||||||
|
if (label) { label.textContent = 'Pulling…'; }
|
||||||
|
|
||||||
|
var data = new URLSearchParams({
|
||||||
|
action: 'oribi_sync_pull_page',
|
||||||
|
_ajax_nonce: <?php echo wp_json_encode( $nonce ); ?>,
|
||||||
|
post_id: <?php echo $post_id; ?>
|
||||||
|
});
|
||||||
|
|
||||||
|
fetch(<?php echo wp_json_encode( $ajax_url ); ?>, {
|
||||||
|
method: 'POST',
|
||||||
|
credentials: 'same-origin',
|
||||||
|
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||||
|
body: data.toString()
|
||||||
|
})
|
||||||
|
.then(function (r) { return r.json(); })
|
||||||
|
.then(function () {
|
||||||
|
// Hard reload — cache-busting param forces a fresh response
|
||||||
|
var url = new URL(window.location.href);
|
||||||
|
url.searchParams.set('_nocache', Date.now());
|
||||||
|
window.location.replace(url.toString());
|
||||||
|
})
|
||||||
|
.catch(function (err) {
|
||||||
|
if (label) { label.textContent = 'Pull Page'; }
|
||||||
|
if (link) { link.style.opacity = ''; link.style.pointerEvents = ''; }
|
||||||
|
alert('Oribi Sync pull failed: ' + err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
<?php
|
||||||
|
} );
|
||||||
|
|
||||||
// ─── Register admin menu ──────────────────────────────────────────────────────
|
// ─── Register admin menu ──────────────────────────────────────────────────────
|
||||||
add_action( 'admin_menu', function () {
|
add_action( 'admin_menu', function () {
|
||||||
add_options_page(
|
add_options_page(
|
||||||
|
|||||||
@@ -1,153 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* Oribi Sync — REST API endpoints.
|
|
||||||
*
|
|
||||||
* POST /wp-json/oribi-sync/v1/sync — Trigger a sync
|
|
||||||
* POST /wp-json/oribi-sync/v1/sync — With ?dry_run=1 for preview
|
|
||||||
* GET /wp-json/oribi-sync/v1/status — Get last sync status
|
|
||||||
* POST /wp-json/oribi-sync/v1/webhook — Webhook trigger (secret-based auth)
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ( ! defined( 'ABSPATH' ) ) exit;
|
|
||||||
|
|
||||||
add_action( 'rest_api_init', function () {
|
|
||||||
|
|
||||||
// ── Trigger sync ──────────────────────────────────────────────────────
|
|
||||||
register_rest_route( 'oribi-sync/v1', '/sync', [
|
|
||||||
'methods' => 'POST',
|
|
||||||
'callback' => 'oribi_sync_rest_sync',
|
|
||||||
'permission_callback' => function () {
|
|
||||||
return current_user_can( 'manage_options' );
|
|
||||||
},
|
|
||||||
] );
|
|
||||||
|
|
||||||
// ── Sync status ───────────────────────────────────────────────────────
|
|
||||||
register_rest_route( 'oribi-sync/v1', '/status', [
|
|
||||||
'methods' => 'GET',
|
|
||||||
'callback' => 'oribi_sync_rest_status',
|
|
||||||
'permission_callback' => function () {
|
|
||||||
return current_user_can( 'manage_options' );
|
|
||||||
},
|
|
||||||
] );
|
|
||||||
|
|
||||||
// ── Push page to repo ──────────────────────────────────────────────────
|
|
||||||
register_rest_route( 'oribi-sync/v1', '/push', [
|
|
||||||
'methods' => 'POST',
|
|
||||||
'callback' => 'oribi_sync_rest_push',
|
|
||||||
'permission_callback' => function () {
|
|
||||||
return current_user_can( 'manage_options' );
|
|
||||||
},
|
|
||||||
] );
|
|
||||||
|
|
||||||
// ── Push all synced pages to repo ──────────────────────────────────────
|
|
||||||
register_rest_route( 'oribi-sync/v1', '/push-all', [
|
|
||||||
'methods' => 'POST',
|
|
||||||
'callback' => 'oribi_sync_rest_push_all',
|
|
||||||
'permission_callback' => function () {
|
|
||||||
return current_user_can( 'manage_options' );
|
|
||||||
},
|
|
||||||
] );
|
|
||||||
|
|
||||||
// ── Webhook (secret-based auth, no WP login required) ─────────────────
|
|
||||||
register_rest_route( 'oribi-sync/v1', '/webhook', [
|
|
||||||
'methods' => 'POST',
|
|
||||||
'callback' => 'oribi_sync_rest_webhook',
|
|
||||||
'permission_callback' => '__return_true', // Auth handled in callback
|
|
||||||
] );
|
|
||||||
} );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* REST: Trigger sync.
|
|
||||||
*/
|
|
||||||
function oribi_sync_rest_sync( WP_REST_Request $request ): WP_REST_Response {
|
|
||||||
$dry_run = (bool) $request->get_param( 'dry_run' );
|
|
||||||
$result = oribi_sync_run( $dry_run );
|
|
||||||
|
|
||||||
// After pulling, push local changes back (skip during dry-run)
|
|
||||||
if ( ! $dry_run ) {
|
|
||||||
$push = oribi_sync_push_all();
|
|
||||||
$result['push'] = $push['results'];
|
|
||||||
}
|
|
||||||
|
|
||||||
return new WP_REST_Response( $result, $result['ok'] ? 200 : 500 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* REST: Get last sync status.
|
|
||||||
*/
|
|
||||||
function oribi_sync_rest_status(): WP_REST_Response {
|
|
||||||
return new WP_REST_Response( [
|
|
||||||
'last_run' => get_option( 'oribi_sync_last_run', null ),
|
|
||||||
'log' => array_slice( get_option( 'oribi_sync_log', [] ), 0, 5 ),
|
|
||||||
'repo' => get_option( 'oribi_sync_repo', '' ),
|
|
||||||
'branch' => get_option( 'oribi_sync_branch', 'main' ),
|
|
||||||
'provider' => oribi_sync_get_provider(),
|
|
||||||
'has_pat' => ! empty( get_option( 'oribi_sync_pat', '' ) ),
|
|
||||||
] );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* REST: Webhook trigger.
|
|
||||||
*
|
|
||||||
* Validates using a shared secret stored in the WP option oribi_sync_webhook_secret
|
|
||||||
* or the constant ORIBI_SYNC_WEBHOOK_SECRET.
|
|
||||||
*
|
|
||||||
* Accepts GitHub-style X-Hub-Signature-256 header, or a simple
|
|
||||||
* Authorization: Bearer <secret> header.
|
|
||||||
*/
|
|
||||||
function oribi_sync_rest_webhook( WP_REST_Request $request ): WP_REST_Response {
|
|
||||||
$secret = defined( 'ORIBI_SYNC_WEBHOOK_SECRET' )
|
|
||||||
? ORIBI_SYNC_WEBHOOK_SECRET
|
|
||||||
: get_option( 'oribi_sync_webhook_secret', '' );
|
|
||||||
|
|
||||||
if ( empty( $secret ) ) {
|
|
||||||
return new WP_REST_Response( [ 'error' => 'Webhook secret not configured.' ], 403 );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check Authorization: Bearer <secret>
|
|
||||||
$auth = $request->get_header( 'Authorization' );
|
|
||||||
if ( $auth && preg_match( '/^Bearer\s+(.+)$/i', $auth, $m ) ) {
|
|
||||||
if ( ! hash_equals( $secret, $m[1] ) ) {
|
|
||||||
return new WP_REST_Response( [ 'error' => 'Invalid secret.' ], 403 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Check GitHub X-Hub-Signature-256
|
|
||||||
elseif ( $sig = $request->get_header( 'X-Hub-Signature-256' ) ) {
|
|
||||||
$body = $request->get_body();
|
|
||||||
$expected = 'sha256=' . hash_hmac( 'sha256', $body, $secret );
|
|
||||||
if ( ! hash_equals( $expected, $sig ) ) {
|
|
||||||
return new WP_REST_Response( [ 'error' => 'Invalid signature.' ], 403 );
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return new WP_REST_Response( [ 'error' => 'Missing authentication.' ], 403 );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run sync
|
|
||||||
$result = oribi_sync_run();
|
|
||||||
|
|
||||||
return new WP_REST_Response( $result, $result['ok'] ? 200 : 500 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* REST: Push a single page to the repo.
|
|
||||||
*/
|
|
||||||
function oribi_sync_rest_push( WP_REST_Request $request ): WP_REST_Response {
|
|
||||||
$post_id = (int) $request->get_param( 'post_id' );
|
|
||||||
if ( $post_id < 1 ) {
|
|
||||||
return new WP_REST_Response( [ 'ok' => false, 'message' => 'Missing or invalid post_id.' ], 400 );
|
|
||||||
}
|
|
||||||
|
|
||||||
$opts = [];
|
|
||||||
$message = $request->get_param( 'message' );
|
|
||||||
if ( ! empty( $message ) ) {
|
|
||||||
$opts['message'] = sanitize_text_field( $message );
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = oribi_sync_push_page( $post_id, $opts );
|
|
||||||
|
|
||||||
return new WP_REST_Response( $result, $result['ok'] ? 200 : 500 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* REST: Push all synced pages to the repo.
|
|
||||||
*/
|
|
||||||
@@ -531,6 +531,133 @@ function oribi_sync_apply_theme_files( string $api_base, string $branch, string
|
|||||||
return $out;
|
return $out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pull a single page (and theme files) from the repo.
|
||||||
|
*
|
||||||
|
* Used by the admin-bar "Pull Page" button to re-sync only the page currently
|
||||||
|
* being viewed plus all theme files, then returns a result array.
|
||||||
|
*
|
||||||
|
* @param int $post_id WordPress post ID.
|
||||||
|
*
|
||||||
|
* @return array{ok: bool, created: string[], updated: string[], skipped: string[], errors: string[], theme_updated: string[]}
|
||||||
|
*/
|
||||||
|
function oribi_sync_pull_page_from_repo( int $post_id ): array {
|
||||||
|
$result = [
|
||||||
|
'ok' => true,
|
||||||
|
'created' => [],
|
||||||
|
'updated' => [],
|
||||||
|
'skipped' => [],
|
||||||
|
'errors' => [],
|
||||||
|
'theme_updated' => [],
|
||||||
|
];
|
||||||
|
|
||||||
|
$post = get_post( $post_id );
|
||||||
|
if ( ! $post ) {
|
||||||
|
$result['ok'] = false;
|
||||||
|
$result['errors'][] = 'Post not found.';
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
$slug = $post->post_name;
|
||||||
|
|
||||||
|
// ── Gather settings ────────────────────────────────────────────────────
|
||||||
|
$repo_url = get_option( 'oribi_sync_repo', '' );
|
||||||
|
$branch = get_option( 'oribi_sync_branch', 'main' ) ?: 'main';
|
||||||
|
$pat = oribi_sync_get_pat();
|
||||||
|
|
||||||
|
if ( empty( $repo_url ) || empty( $pat ) ) {
|
||||||
|
$result['ok'] = false;
|
||||||
|
$result['errors'][] = 'Repository URL or PAT is not configured.';
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
$parsed = oribi_sync_parse_repo_url( $repo_url );
|
||||||
|
if ( is_wp_error( $parsed ) ) {
|
||||||
|
$result['ok'] = false;
|
||||||
|
$result['errors'][] = $parsed->get_error_message();
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
$provider = oribi_sync_get_provider();
|
||||||
|
$api_base = oribi_sync_api_base( $provider, $parsed );
|
||||||
|
|
||||||
|
// ── Fetch tree ─────────────────────────────────────────────────────────
|
||||||
|
$tree = oribi_sync_fetch_tree( $api_base, $branch, $provider, $pat );
|
||||||
|
if ( is_wp_error( $tree ) ) {
|
||||||
|
$result['ok'] = false;
|
||||||
|
$result['errors'][] = 'Tree fetch failed: ' . $tree->get_error_message();
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Find the matching page file ────────────────────────────────────────
|
||||||
|
$page_files = oribi_sync_filter_tree( $tree, 'Pages' );
|
||||||
|
$target_entry = null;
|
||||||
|
|
||||||
|
foreach ( $page_files as $entry ) {
|
||||||
|
$file_slug = oribi_sync_filename_to_slug( basename( $entry['path'] ) );
|
||||||
|
if ( $file_slug === $slug ) {
|
||||||
|
$target_entry = $entry;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! $target_entry ) {
|
||||||
|
$result['skipped'][] = $slug . ' (not found in Pages/ directory)';
|
||||||
|
} else {
|
||||||
|
$raw_content = oribi_sync_fetch_file( $api_base, $branch, $target_entry['path'], $provider, $pat );
|
||||||
|
if ( is_wp_error( $raw_content ) ) {
|
||||||
|
$result['errors'][] = $target_entry['path'] . ': ' . $raw_content->get_error_message();
|
||||||
|
$result['ok'] = false;
|
||||||
|
} else {
|
||||||
|
$raw_content = trim( $raw_content );
|
||||||
|
$ext = strtolower( pathinfo( basename( $target_entry['path'] ), PATHINFO_EXTENSION ) );
|
||||||
|
|
||||||
|
if ( $ext === 'php' ) {
|
||||||
|
$content = oribi_sync_execute_php( $raw_content, $slug );
|
||||||
|
if ( is_wp_error( $content ) ) {
|
||||||
|
$result['errors'][] = $target_entry['path'] . ': ' . $content->get_error_message();
|
||||||
|
$result['ok'] = false;
|
||||||
|
$content = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$content = $raw_content;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $content !== null ) {
|
||||||
|
$checksum = hash( 'sha256', $raw_content );
|
||||||
|
$git_sha = $target_entry['sha'] ?? '';
|
||||||
|
|
||||||
|
$update = wp_update_post( [
|
||||||
|
'ID' => $post->ID,
|
||||||
|
'post_content' => $content,
|
||||||
|
'post_status' => 'publish',
|
||||||
|
], true );
|
||||||
|
|
||||||
|
if ( is_wp_error( $update ) ) {
|
||||||
|
$result['errors'][] = $slug . ': ' . $update->get_error_message();
|
||||||
|
$result['ok'] = false;
|
||||||
|
} else {
|
||||||
|
update_post_meta( $post->ID, '_oribi_sync_checksum', $checksum );
|
||||||
|
update_post_meta( $post->ID, '_oribi_sync_git_sha', $git_sha );
|
||||||
|
update_post_meta( $post->ID, '_oribi_sync_source', $repo_url . '@' . $branch . ':' . $target_entry['path'] );
|
||||||
|
update_post_meta( $post->ID, '_oribi_sync_last_run', current_time( 'mysql' ) );
|
||||||
|
update_post_meta( $post->ID, '_wp_page_template', 'default' );
|
||||||
|
$result['updated'][] = $slug;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Sync theme files ───────────────────────────────────────────────────
|
||||||
|
$theme_sync = oribi_sync_apply_theme_files( $api_base, $branch, $provider, $pat, false, $tree );
|
||||||
|
$result['theme_updated'] = $theme_sync['updated'];
|
||||||
|
foreach ( $theme_sync['errors'] as $err ) {
|
||||||
|
$result['errors'][] = '[theme] ' . $err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch theme files from the repo (for preview / apply).
|
* Fetch theme files from the repo (for preview / apply).
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ require_once ORIBI_SYNC_DIR . 'includes/sync-engine.php';
|
|||||||
require_once ORIBI_SYNC_DIR . 'includes/push-client.php';
|
require_once ORIBI_SYNC_DIR . 'includes/push-client.php';
|
||||||
require_once ORIBI_SYNC_DIR . 'includes/post-sync.php';
|
require_once ORIBI_SYNC_DIR . 'includes/post-sync.php';
|
||||||
require_once ORIBI_SYNC_DIR . 'includes/admin.php';
|
require_once ORIBI_SYNC_DIR . 'includes/admin.php';
|
||||||
require_once ORIBI_SYNC_DIR . 'includes/rest.php';
|
|
||||||
require_once ORIBI_SYNC_DIR . 'includes/theme-preview.php';
|
require_once ORIBI_SYNC_DIR . 'includes/theme-preview.php';
|
||||||
|
|
||||||
// ─── Activation / Deactivation ────────────────────────────────────────────────
|
// ─── Activation / Deactivation ────────────────────────────────────────────────
|
||||||
|
|||||||
Reference in New Issue
Block a user