如果我们可以编写我们希望导入的类别层次结构,这不是很方便吗
apple|Apple|Apple products
iphone-6s|Iphone 6s|Apple Iphone 6s
iphone-6s-battery|Iphone 6s battery|Apple Iphone 6s battery
iphone-8-battery|Iphone 8 battery|Apple Iphone 8 battery
每行为:
term slug|term name|term description
以及缩进定义的层次结构。
示例#1
使用空格进行缩进和
|
作为列分隔符:
$import = \'
a1|A1|Term description
a11|A11|Term description
a111|A111|Term description
a112|A112|Term description
a12|A12|Term description
\';
wpse324129_bulk_terms_importer( $import, \'category\', \'|\', PHP_EOL );
这将导入以下条款:
示例#2
另一个使用制表符进行缩进和逗号作为列分隔符的示例:
$import = \'
a1,A1,"Term description, including column delimiter"
a11,A11, "Term description, including column delimiter"
a111,A111,"Term description, including column delimiter"
a112,A112,"Term description, including column delimiter"
a12,A12,"Term description, including column delimiter"
\';
wpse324129_bulk_terms_importer( $import, \'category\', \',\', PHP_EOL );
将术语导入为:
实现
这是这样一个从字符串批量导入术语的函数的初稿:
/**
* Bulk Term Importer
*
* Bulk import terms with a given hierarchy, defined by indentation (tab or space).
*
* @version 0.1.3
*
* @see https://wordpress.stackexchange.com/a/324157/26350
*
* @param string $import Terms to import
* @param string $tax Taxonomy. Default \'category\'.
* @param string $col_delimiter Column delimiter. Default \'|\'.
* @param string $row_delimiter Row delimiter. Default PHP_EOL.
*/
function wpse324129_bulk_term_importer( $import, $tax = \'category\', $col_delimiter = \'|\', $row_delimiter = PHP_EOL ) {
$rows = explode( $row_delimiter, trim( $import ) );
$level = 0;
$prev_term_id = 0;
$ancestors = new \\SplStack(); // Last-In First-Out.
foreach( $rows as $row ) {
$cols = str_getcsv( $row, $col_delimiter );
if ( 3 !== count( $cols ) ) {
throw new Exception( __( \'Incorrect number of columns\', \'wpse\' ) );
}
$term_slug = $cols[0];
$term_name = $cols[1];
$term_desc = $cols[2];
// Hierarchy traversal level (non negative).
$level = strlen( $term_slug ) - strlen( ltrim( $term_slug ) );
// Push the previous term to the ancestors stack if we go inner (right).
if ( $level > $ancestors->count() ) {
$ancestors->push( $prev_term_id );
} // After: level === ancestors count
// Reduce the ancestors\' stack when we go outer (left).
while ( $level < $ancestors->count() ) {
$ancestors->pop();
} // After: level === ancestors count
// Arguments for term creation.
$args = [
\'description\' => $term_desc,
\'slug\' => $term_slug,
];
// Check parent term and add to the term creation arguments if needed.
if ( $prev_term_id > 0 && $ancestors->count() > 0 ) {
$parent_id = $ancestors->top(); // The parent is the one on the top.
$parent_term = get_term_by( \'term_id\', $parent_id, $tax, ARRAY_A );
if ( isset( $parent_term[\'term_id\'] ) ) {
$args[\'parent\'] = $parent_term[\'term_id\'];
}
}
// Check if current term slug exists and insert if needed.
$term = get_term_by( \'slug\', $term_slug, $tax, ARRAY_A );
if ( ! isset( $term[\'term_id\'] ) ) {
$result = wp_insert_term( $term_name, $tax, $args );
if ( is_wp_error( $result ) ) {
throw new Exception( __( \'Could not insert term!\', \'wpse\' ) );
}
$prev_term_id = $result[\'term_id\'];
} else {
$prev_term_id = $term[\'term_id\'];
}
}
}
当我们插入一个术语时,我们需要知道它的父项。因此,我们需要在遍历层次结构时收集直接项祖先。这个
stack 是一种合适的数据结构,其中最后一项是第一项(后进先出)。在PHP 5.3+中,我们可以使用
SplStack
已经实现了如下方法
pop()
,
push()
,
top()
和
count()
.
通过将当前级别与当前祖先的数量进行比较,我们可以确定是内部(右)还是外部(左),并相应地调整堆栈。当我们向左移动时减少堆栈,当我们向右移动时推动堆栈。
对于大型导入,可以通过wp-cli
以避免超时。
希望您可以进一步扩展此功能以满足您的需要,例如使用格式验证器以及如何处理现有条款(我们目前不影响这些条款)。
测试前请备份!