(免责声明:这涉及核心WP破解,请小心处理)
我有一个多站点网络,我想让主博客(id==1)设置分类法activity_type
对于网络上的所有其他站点。
我使用下面的代码在自定义分类法中创建、编辑或删除术语时包含挂钩,然后在所有子网站上模拟该任务。这里没有涉及的是限制其他网站上的用户添加/编辑/删除术语-我使用了jQuery、CSS和remove_action
用于在子网站中隐藏这些UI元素的函数。
//When an activity type is added to the primary site, also add it to the sub-sites
function as_act_type_add ($term_id, $tt_id, $taxonomy){
$new_act_type = get_term($term_id, \'activity_type\', ARRAY_A);
//get parent data if necessary
$parent_term = get_term_by(\'term_id\', $new_act_type[\'parent\'], \'activity_type\', ARRAY_A);
$sites = as_network_ids();
foreach($sites as $site){
switch_to_blog($site);
$exist_check = term_exists($new_act_type[\'name\'], \'activity_type\'); //check if the created term exists on the subsite already
$site_parent = term_exists( $parent_term[\'name\'], \'activity_type\' ); //check if the parent term exists
$parent_term_id = $site_parent[\'term_id\']; // get numeric term id
if(is_array($exist_check)){
//do nothing - in the future, we want this to update the existing term but punt for now
} else {
wp_insert_term(
$new_act_type[\'name\'], // the term
\'activity_type\', // the taxonomy
array(
\'description\'=> $new_act_type[\'description\'],
\'slug\' => $new_act_type[\'slug\'],
\'parent\' => $parent_term_id
)
);
//since we might have added children, you have to delete the cache, or else they wont display right away
delete_option("activity_type_children");
} //end term_exists
restore_current_blog();
} //end foreach
//and delete cache for main site
delete_option("activity_type_children");
}
//triggered whenever a term is added
add_action("create_activity_type", "as_act_type_add", 10, 3);
function as_act_type_update($term_id, $tt_id, $taxonomy){
//the term hasnt been changed yet, but we want to get it anyway in case the name has been changed
$legacy_term = get_term($term_id, \'activity_type\', ARRAY_A);
$edited_act_type = $_POST;
if($edited_act_type[\'parent\']){
$parent_term = get_term_by(\'term_id\', $edited_act_type["parent"], \'activity_type\', ARRAY_A);
}
$sites = as_network_ids();
foreach($sites as $site){
switch_to_blog($site);
//cehck to see if the updated term exists on the site
$exist_check = term_exists($legacy_term[\'name\'], \'activity_type\');
if($parent_term){
//check to make sure we have the parent
$site_parent_term = term_exists($parent_term[\'name\'], \'activity_type\');
}
//if so, update it
if(is_array($exist_check)){
//since wp_update_term calls the edit_term hook, we need to unhook to avoid an infinite loop
remove_action("edit_activity_type", "as_act_type_update", 10, 3);
//update that fool
wp_update_term(
$exist_check[\'term_id\'], // the term id
\'activity_type\', // the taxonomy
array(
\'name\' => $edited_act_type[\'name\'],
\'description\' => $edited_act_type[\'description\'],
\'slug\' => $edited_act_type[\'slug\'],
\'parent\' => $site_parent_term[\'term_id\'] //if this doesnt exist, WP will default to 0, or no parent
)
);
} //end is_array check
restore_current_blog();
} //end foreach
} //end update term func
add_action("edit_activity_type", "as_act_type_update", 10, 3);
function as_act_type_delete($term_id, $tt_id, $taxonomy){
//somehow this also works with bulk delete- I didnt think it would but apprarently it does. sacrificial goat must have worked.
$deleted_act_type = get_site_transient( \'as_last_activity_type_delete\' ); //temp transient set in wp-includes/taxonomy.php to store deleted term data
if ( false === ( $deleted_act_type)) {
//do nothing if no transient available
} else {
//we have the deleted term data fromt he transient, so use it here
$sites = as_network_ids();
foreach($sites as $site){
switch_to_blog($site);
$exist_check = term_exists($deleted_act_type->name, \'activity_type\');
if(is_array($exist_check)){
//unhook action to avoid infinite loop
remove_action("delete_activity_type", "as_act_type_delete", 10, 3);
wp_delete_term($exist_check[\'term_id\'], \'activity_type\');
//add_action("delete_activity_type", "as_act_type_delete", 10, 3);
} //end exist check
restore_current_blog();
} //end foreach
//now clear the data from the transient
delete_site_transient( \'as_last_activity_type_delete\' );
} //end false check for transient
} //end update term
add_action("delete_activity_type", "as_act_type_delete", 9, 3);
这也需要对WP core进行黑客攻击(是的,要小心这种罪恶,因为这是一种可怕的越轨行为)。在里面
wp-includes/taxonomy.php
查找第1767行或
$term = (int) $term;
中的行
wp_delete_term
作用在此处,放置此行:
set_site_transient(\'as_last_activity_type_delete\',get_term($term,\'activity_type\'));
我可能也会在这里给自己留下一条评论,并在某处刺青一个提醒,因为你必须手动更新
taxonomy.php
every time you update WordPress. 这很糟糕,但我们设置这个瞬态的原因是,我们可以通过slug而不是ID来查找已删除的术语
delete_{tax_type}
为我们提供了已删除术语的term\\u id,但我们不能确定所有网站上的term\\u id是否相同,因此我们必须在删除之前获取术语slug。。。因此,核心黑客。我不喜欢它,我不为它感到骄傲,但它确实有效。如果你只关心将条款推送到你的网站,而不关心从你的主站点删除条款,那么你实际上可以跳过这一步,而不必破解核心-我需要能够从单个网站创建和删除条款,这是我找到的唯一方法。
您还会注意到我的代码中有一行出现这种情况$sites = as_network_ids();
. 这只是我在其他地方创建的一个助手函数,它返回所有网络博客ID的列表以及我用于许多其他函数的一些额外数据。您可以使用this function (警告:它已被正式弃用,但尚未被替换)或编写自己的SQL。