| Server IP : 148.113.13.24 / Your IP : 216.73.217.94 Web Server : Apache/2.4.59 (Ubuntu) mod_fcgid/2.3.9 OpenSSL/3.0.2 System : Linux o1.zxs.ovh 5.15.0-186-generic #196-Ubuntu SMP Sat Jun 20 16:09:34 UTC 2026 x86_64 User : b051826 ( 1041) PHP Version : 8.2.19 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,exec,system,passthru,shell_exec,proc_open,popen MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /home/b051826/web/zenpathjapan.com/public_html/wp-content/themes/zenpathjapan/ |
Upload File : |
<?php
/**
* content-import.php — one-shot, idempotent content importer.
* Run via Tools → ZenPath Import (AJAX, stepwise) or WP-CLI: `wp zpj import`.
* Re-running updates existing items instead of duplicating.
*/
defined('ABSPATH') || exit;
/* ------------------------------------------------------------------ *
* Helpers
* ------------------------------------------------------------------ */
/** Read a content HTML file from the theme. */
function zpj_imp_html($slug) {
$f = get_template_directory() . '/content/' . $slug . '.html';
return is_readable($f) ? file_get_contents($f) : '';
}
/** Idempotent attachment from a theme image file. Reused via _zpj_src meta. */
function zpj_imp_attach($name, $title = '') {
if (!$name) return 0;
$src = get_template_directory() . '/assets/i/' . $name . '.jpg';
if (!is_readable($src)) return 0;
// already imported?
$found = get_posts([
'post_type' => 'attachment',
'post_status' => 'inherit',
'numberposts' => 1,
'fields' => 'ids',
'meta_key' => '_zpj_src',
'meta_value' => $name,
]);
if (!empty($found)) return (int) $found[0];
require_once ABSPATH . 'wp-admin/includes/image.php';
require_once ABSPATH . 'wp-admin/includes/file.php';
require_once ABSPATH . 'wp-admin/includes/media.php';
$upload = wp_upload_bits($name . '.jpg', null, file_get_contents($src));
if (!empty($upload['error'])) return 0;
$ftype = wp_check_filetype($upload['file'], null);
$att = [
'post_mime_type' => $ftype['type'] ?: 'image/jpeg',
'post_title' => $title ?: $name,
'post_status' => 'inherit',
];
$id = wp_insert_attachment($att, $upload['file']);
if (is_wp_error($id) || !$id) return 0;
wp_update_attachment_metadata($id, wp_generate_attachment_metadata($id, $upload['file']));
update_post_meta($id, '_zpj_src', $name);
return (int) $id;
}
/** Idempotent category by slug. */
function zpj_imp_term($c) {
$term = get_term_by('slug', $c['slug'], 'category');
if ($term) {
wp_update_term($term->term_id, 'category', ['name' => $c['name'], 'description' => $c['desc']]);
$id = $term->term_id;
} else {
$res = wp_insert_term($c['name'], 'category', ['slug' => $c['slug'], 'description' => $c['desc']]);
if (is_wp_error($res)) return 0;
$id = $res['term_id'];
}
update_term_meta($id, 'zpj_color', $c['color']);
return (int) $id;
}
/**
* Editorial WP user. Fallback chain: by login -> by email -> create -> retry suffix.
* login = editorial ; email = editorial@{domain} (NOT info@, avoids admin collision).
*/
function zpj_imp_editorial() {
$domain = parse_url(home_url(), PHP_URL_HOST);
$domain = preg_replace('/^www\./', '', (string) $domain) ?: 'zenpathjapan.com';
$email = 'editorial@' . $domain;
$u = get_user_by('login', 'editorial');
if ($u) return $u->ID;
$u = get_user_by('email', $email);
if ($u) return $u->ID;
$uid = wp_insert_user([
'user_login' => 'editorial',
'user_email' => $email,
'user_pass' => wp_generate_password(20, true, true),
'display_name' => get_bloginfo('name') . ' 編集部',
'role' => 'editor',
]);
if (is_wp_error($uid)) {
// retry with a suffix if login/email already taken in some form
$uid = wp_insert_user([
'user_login' => 'editorial_zpj',
'user_email' => 'editorial+zpj@' . $domain,
'user_pass' => wp_generate_password(20, true, true),
'display_name' => get_bloginfo('name') . ' 編集部',
'role' => 'editor',
]);
if (is_wp_error($uid)) return (int) get_current_user_id();
}
return (int) $uid;
}
/** Find a post/page by slug regardless of status. */
function zpj_imp_find($slug, $type) {
$hit = get_posts([
'name' => $slug,
'post_type' => $type,
'post_status' => 'any',
'numberposts' => 1,
'fields' => 'ids',
]);
return !empty($hit) ? (int) $hit[0] : 0;
}
/** Idempotent article import. */
function zpj_imp_article($a, $author_id) {
$content = zpj_imp_html($a['slug']);
$cat = get_term_by('slug', $a['cat'], 'category');
$args = [
'post_title' => $a['title'],
'post_name' => $a['slug'],
'post_content' => $content,
'post_status' => 'publish',
'post_type' => 'post',
'post_author' => $author_id,
];
$id = zpj_imp_find($a['slug'], 'post');
if ($id) { $args['ID'] = $id; wp_update_post($args); }
else { $id = wp_insert_post($args); }
if ($id && !is_wp_error($id)) {
if ($cat) wp_set_post_categories($id, [(int) $cat->term_id]);
$thumb = zpj_imp_attach($a['slug'], $a['title']);
if ($thumb) set_post_thumbnail($id, $thumb);
}
return (int) $id;
}
/** Idempotent page import. */
function zpj_imp_page($p) {
$content = ($p['slug'] === 'blog') ? '' : zpj_imp_html($p['slug']);
$args = [
'post_title' => $p['title'],
'post_name' => $p['slug'],
'post_content' => $content,
'post_status' => 'publish',
'post_type' => 'page',
];
$id = zpj_imp_find($p['slug'], 'page');
if ($id) { $args['ID'] = $id; wp_update_post($args); }
else { $id = wp_insert_post($args); }
if ($id && !is_wp_error($id) && !empty($p['banner'])) {
$thumb = zpj_imp_attach($p['banner'], $p['title']);
if ($thumb) set_post_thumbnail($id, $thumb);
}
return (int) $id;
}
/** Rebuild primary + footer menus from data (idempotent: wipe & rebuild items). */
function zpj_imp_menus() {
$data = zpj_dataset('menus');
foreach (['primary' => '主メニュー', 'footer' => 'フッターメニュー'] as $loc => $menu_name) {
$menu = wp_get_nav_menu_object($menu_name);
$menu_id = $menu ? $menu->term_id : wp_create_nav_menu($menu_name);
if (is_wp_error($menu_id)) continue;
// clear existing items for a clean rebuild
foreach (wp_get_nav_menu_items($menu_id) ?: [] as $it) {
wp_delete_post($it->ID, true);
}
if ($loc === 'primary') {
foreach ($data['primary'] as $node) {
if (!empty($node['children'])) {
$parent = wp_update_nav_menu_item($menu_id, 0, [
'menu-item-title' => $node['label'],
'menu-item-url' => '#',
'menu-item-status' => 'publish',
'menu-item-type' => 'custom',
]);
foreach ($node['children'] as $cslug) {
$term = get_term_by('slug', $cslug, 'category');
if (!$term) continue;
wp_update_nav_menu_item($menu_id, 0, [
'menu-item-title' => $term->name,
'menu-item-object' => 'category',
'menu-item-object-id' => $term->term_id,
'menu-item-type' => 'taxonomy',
'menu-item-parent-id' => $parent,
'menu-item-status' => 'publish',
]);
}
} else {
$pid = zpj_imp_find($node['slug'], 'page');
if (!$pid) continue;
wp_update_nav_menu_item($menu_id, 0, [
'menu-item-title' => $node['label'],
'menu-item-object' => 'page',
'menu-item-object-id' => $pid,
'menu-item-type' => 'post_type',
'menu-item-status' => 'publish',
]);
}
}
} else {
foreach ($data['footer'] as $slug) {
$pid = zpj_imp_find($slug, 'page');
if (!$pid) continue;
wp_update_nav_menu_item($menu_id, 0, [
'menu-item-object' => 'page',
'menu-item-object-id' => $pid,
'menu-item-type' => 'post_type',
'menu-item-status' => 'publish',
]);
}
}
$locations = get_theme_mod('nav_menu_locations', []);
$locations[$loc] = $menu_id;
set_theme_mod('nav_menu_locations', $locations);
}
return true;
}
/** Reset: remove previously imported content for a clean re-import (idempotent). */
function zpj_imp_reset() {
// imported attachments (tagged with _zpj_src)
$atts = get_posts([
'post_type' => 'attachment', 'post_status' => 'any', 'numberposts' => -1,
'fields' => 'ids', 'meta_key' => '_zpj_src',
]);
foreach ($atts as $id) wp_delete_attachment($id, true);
// imported posts + pages (by slug from theme-data)
foreach (zpj_dataset('articles') as $a) {
$id = zpj_imp_find($a['slug'], 'post');
if ($id) wp_delete_post($id, true);
}
foreach (zpj_dataset('pages') as $p) {
$id = zpj_imp_find($p['slug'], 'page');
if ($id) wp_delete_post($id, true);
}
// theme menus
foreach (['主メニュー', 'フッターメニュー'] as $mn) {
$m = wp_get_nav_menu_object($mn);
if ($m) wp_delete_nav_menu($m->term_id);
}
// theme categories (by slug); posts already removed
foreach (zpj_dataset('categories') as $c) {
$t = get_term_by('slug', $c['slug'], 'category');
if ($t) wp_delete_term($t->term_id, 'category');
}
// detach front-page options so finalize re-sets them cleanly
update_option('show_on_front', 'posts');
delete_option('page_on_front');
delete_option('page_for_posts');
return true;
}
/** Finalize: static front page + posts page. */
function zpj_imp_finalize() {
$home = zpj_imp_find('home', 'page');
$blog = zpj_imp_find('blog', 'page');
if ($home) {
update_option('show_on_front', 'page');
update_option('page_on_front', $home);
}
if ($blog) update_option('page_for_posts', $blog);
flush_rewrite_rules(false);
return true;
}
/* ------------------------------------------------------------------ *
* Step machine (25 steps) — shared by AJAX + WP-CLI
* ------------------------------------------------------------------ */
function zpj_imp_steps() {
$steps = [];
$steps[] = ['key' => 'categories', 'label' => 'カテゴリーを作成'];
$steps[] = ['key' => 'user', 'label' => '編集ユーザーを準備'];
foreach (zpj_dataset('articles') as $a) {
$steps[] = ['key' => 'article', 'slug' => $a['slug'], 'label' => '記事: ' . $a['title']];
}
foreach (zpj_dataset('pages') as $p) {
$steps[] = ['key' => 'page', 'slug' => $p['slug'], 'label' => 'ページ: ' . $p['title']];
}
$steps[] = ['key' => 'menus', 'label' => 'メニューを再構築'];
$steps[] = ['key' => 'finalize', 'label' => 'フロントページ設定'];
return $steps;
}
function zpj_imp_run_step($i) {
$steps = zpj_imp_steps();
if (!isset($steps[$i])) return false;
$s = $steps[$i];
static $author = null;
switch ($s['key']) {
case 'categories':
foreach (zpj_dataset('categories') as $c) zpj_imp_term($c);
break;
case 'user':
$GLOBALS['_zpj_author'] = zpj_imp_editorial();
break;
case 'article':
$aid = $GLOBALS['_zpj_author'] ?? zpj_imp_editorial();
foreach (zpj_dataset('articles') as $a) {
if ($a['slug'] === $s['slug']) { zpj_imp_article($a, $aid); break; }
}
break;
case 'page':
foreach (zpj_dataset('pages') as $p) {
if ($p['slug'] === $s['slug']) { zpj_imp_page($p); break; }
}
break;
case 'menus': zpj_imp_menus(); break;
case 'finalize': zpj_imp_finalize(); break;
}
return $s['label'];
}
/* ------------------------------------------------------------------ *
* AJAX driver (admin only)
* ------------------------------------------------------------------ */
add_action('admin_menu', function () {
add_management_page('ZenPath Import', 'ZenPath Import', 'manage_options', 'zpj-import', 'zpj_imp_admin_page');
});
function zpj_imp_admin_page() {
$total = count(zpj_imp_steps());
$nonce = wp_create_nonce('zpj_import');
?>
<div class="wrap">
<h1>ZenPath Japan — コンテンツインポート</h1>
<p>カテゴリー・記事(12)・ページ(10)・メニュー・フロントページ設定を投入します。再実行は安全です(重複しません)。</p>
<p><label><input type="checkbox" id="zpj-imp-reset"> インポート前にリセットする(既存のインポート済みコンテンツを削除)</label></p>
<p><button class="button button-primary" id="zpj-imp-go">インポート開始</button></p>
<div id="zpj-imp-bar" style="height:14px;background:#eee;border-radius:7px;overflow:hidden;max-width:560px">
<div id="zpj-imp-fill" style="height:100%;width:0;background:#A8634A;transition:width .2s"></div>
</div>
<p id="zpj-imp-log" style="font-family:monospace"></p>
</div>
<script>
(function(){
var total = <?php echo (int) $total; ?>, nonce = '<?php echo esc_js($nonce); ?>';
var btn = document.getElementById('zpj-imp-go'),
fill = document.getElementById('zpj-imp-fill'),
log = document.getElementById('zpj-imp-log'),
reset = document.getElementById('zpj-imp-reset');
function step(i){
if(i>=total){ log.textContent='完了しました ✓'; btn.disabled=false; return; }
var fd = new FormData();
fd.append('action','zpj_import'); fd.append('step',i); fd.append('_n',nonce);
fetch(ajaxurl,{method:'POST',body:fd,credentials:'same-origin'})
.then(function(r){return r.json();})
.then(function(d){
fill.style.width = Math.round((i+1)/total*100)+'%';
log.textContent = (i+1)+'/'+total+' — '+(d.data&&d.data.label?d.data.label:'');
step(i+1);
})
.catch(function(){ log.textContent='エラーが発生しました(step '+i+')'; btn.disabled=false; });
}
function begin(){ log.textContent='開始...'; step(0); }
btn.addEventListener('click',function(){
btn.disabled=true;
if(reset && reset.checked){
log.textContent='リセット中...';
var fd=new FormData(); fd.append('action','zpj_reset'); fd.append('_n',nonce);
fetch(ajaxurl,{method:'POST',body:fd,credentials:'same-origin'})
.then(function(r){return r.json();}).then(begin).catch(begin);
} else { begin(); }
});
})();
</script>
<?php
}
add_action('wp_ajax_zpj_import', function () {
if (!current_user_can('manage_options') || !check_ajax_referer('zpj_import', '_n', false)) {
wp_send_json_error(['label' => 'unauthorized'], 403);
}
$i = isset($_POST['step']) ? (int) $_POST['step'] : -1;
$label = zpj_imp_run_step($i);
if ($label === false) wp_send_json_error(['label' => 'no step']);
wp_send_json_success(['step' => $i, 'label' => $label]);
});
/* ------------------------------------------------------------------ *
* WP-CLI: wp zpj import
* ------------------------------------------------------------------ */
add_action('wp_ajax_zpj_reset', function () {
if (!current_user_can('manage_options') || !check_ajax_referer('zpj_import', '_n', false)) {
wp_send_json_error(['label' => 'unauthorized'], 403);
}
zpj_imp_reset();
wp_send_json_success(['label' => 'reset done']);
});
/* ------------------------------------------------------------------ *
* WP-CLI: wp zpj import [--reset] | wp zpj reset
* ------------------------------------------------------------------ */
if (defined('WP_CLI') && WP_CLI) {
WP_CLI::add_command('zpj import', function ($args, $assoc) {
if (!empty($assoc['reset'])) {
zpj_imp_reset();
WP_CLI::log('reset: previous import removed');
}
$steps = zpj_imp_steps();
foreach ($steps as $i => $s) {
$label = zpj_imp_run_step($i);
WP_CLI::log(sprintf('[%d/%d] %s', $i + 1, count($steps), $label));
}
WP_CLI::success('ZenPath import complete (idempotent).');
});
WP_CLI::add_command('zpj reset', function () {
zpj_imp_reset();
WP_CLI::success('ZenPath imported content removed.');
});
}