| 1 |
<?php |
| 2 |
/** |
| 3 |
* @package Polylang |
| 4 |
*/ |
| 5 |
|
| 6 |
/** |
| 7 |
* Class for handling term slugs. |
| 8 |
* |
| 9 |
* @since 3.7 |
| 10 |
*/ |
| 11 |
class PLL_Term_Slug { |
| 12 |
|
| 13 |
/** |
| 14 |
* @var PLL_Model |
| 15 |
*/ |
| 16 |
private $model; |
| 17 |
|
| 18 |
/** |
| 19 |
* @var string |
| 20 |
*/ |
| 21 |
private $slug; |
| 22 |
|
| 23 |
/** |
| 24 |
* @var string |
| 25 |
*/ |
| 26 |
private $taxonomy; |
| 27 |
|
| 28 |
/** |
| 29 |
* @var string |
| 30 |
*/ |
| 31 |
private $name; |
| 32 |
|
| 33 |
/** |
| 34 |
* @var int |
| 35 |
*/ |
| 36 |
private $term_id; |
| 37 |
|
| 38 |
/** |
| 39 |
* @var PLL_Language |
| 40 |
*/ |
| 41 |
private $lang; |
| 42 |
|
| 43 |
/** |
| 44 |
* @var int |
| 45 |
*/ |
| 46 |
private $parent; |
| 47 |
|
| 48 |
/** |
| 49 |
* Constructor. |
| 50 |
* |
| 51 |
* @since 3.7 |
| 52 |
* |
| 53 |
* @param PLL_Model $model Instance of PLL_Model. |
| 54 |
* @param string $slug The term slug. |
| 55 |
* @param string $taxonomy The term taxonomy. |
| 56 |
* @param string $name The term name. |
| 57 |
* @param int $term_id The term ID if exists, or 0 if there's no need to know that we are editing an existing term. |
| 58 |
*/ |
| 59 |
public function __construct( PLL_Model $model, string $slug, string $taxonomy, string $name, int $term_id = 0 ) { |
| 60 |
$this->model = $model; |
| 61 |
$this->slug = $slug; |
| 62 |
$this->taxonomy = $taxonomy; |
| 63 |
$this->name = $name; |
| 64 |
$this->term_id = $term_id; |
| 65 |
} |
| 66 |
|
| 67 |
/** |
| 68 |
* Tells if the suffix can be added or not. |
| 69 |
* |
| 70 |
* @since 3.7 |
| 71 |
* |
| 72 |
* @return bool True if the suffix can be added, false otherwise. |
| 73 |
*/ |
| 74 |
private function can_add_suffix() { |
| 75 |
/** |
| 76 |
* Filters the subsequently inserted term language. |
| 77 |
* |
| 78 |
* @since 3.3 |
| 79 |
* |
| 80 |
* @param PLL_Language|null $lang Found language object, null otherwise. |
| 81 |
* @param string $taxonomy Term taxonomy. |
| 82 |
* @param string $slug Term slug |
| 83 |
*/ |
| 84 |
$lang = apply_filters( 'pll_inserted_term_language', null, $this->taxonomy, $this->slug ); |
| 85 |
if ( ! $lang instanceof PLL_Language ) { |
| 86 |
return false; |
| 87 |
} |
| 88 |
$this->lang = $lang; |
| 89 |
|
| 90 |
$this->parent = 0; |
| 91 |
if ( is_taxonomy_hierarchical( $this->taxonomy ) ) { |
| 92 |
/** |
| 93 |
* Filters the subsequently inserted term parent. |
| 94 |
* |
| 95 |
* @since 3.3 |
| 96 |
* |
| 97 |
* @param int $parent Parent term ID, 0 if none. |
| 98 |
* @param string $taxonomy Term taxonomy. |
| 99 |
* @param string $slug Term slug |
| 100 |
*/ |
| 101 |
$this->parent = apply_filters( 'pll_inserted_term_parent', 0, $this->taxonomy, $this->slug ); |
| 102 |
|
| 103 |
$this->slug .= $this->maybe_get_parent_suffix(); |
| 104 |
} |
| 105 |
|
| 106 |
if ( ! $this->slug ) { |
| 107 |
if ( $this->model->term_exists( $this->name, $this->taxonomy, $this->parent, $this->lang ) ) { |
| 108 |
// Returns the current empty slug if the term exists with the same name and an empty slug. |
| 109 |
// Same as WP does when providing a term with a name that already exists and no slug. |
| 110 |
return false; |
| 111 |
} else { |
| 112 |
$this->slug = sanitize_title( $this->name ); |
| 113 |
} |
| 114 |
} |
| 115 |
|
| 116 |
if ( ! term_exists( $this->slug, $this->taxonomy ) ) { |
| 117 |
return false; |
| 118 |
} |
| 119 |
|
| 120 |
return true; |
| 121 |
} |
| 122 |
|
| 123 |
/** |
| 124 |
* Returns the parent suffix for the slug only if parent slug is the same as the given one. |
| 125 |
* Recursively appends the parents slugs like WordPress does. |
| 126 |
* |
| 127 |
* @since 3.3 |
| 128 |
* @since 3.7 Moved from `PLL_Share_Term_Slug`to `PLL_Term_Slug`. |
| 129 |
* |
| 130 |
* @return string Parents slugs if they are the same as the child slug, empty string otherwise. |
| 131 |
*/ |
| 132 |
private function maybe_get_parent_suffix() { |
| 133 |
$parent_suffix = ''; |
| 134 |
$the_parent = get_term( $this->parent, $this->taxonomy ); |
| 135 |
|
| 136 |
if ( ! $the_parent instanceof WP_Term || $the_parent->slug !== $this->slug ) { |
| 137 |
return $parent_suffix; |
| 138 |
} |
| 139 |
|
| 140 |
/** |
| 141 |
* Mostly copied from {@see wp_unique_term_slug()}. |
| 142 |
*/ |
| 143 |
while ( ! empty( $the_parent ) ) { |
| 144 |
$parent_term = get_term( $the_parent, $this->taxonomy ); |
| 145 |
if ( ! $parent_term instanceof WP_Term ) { |
| 146 |
break; |
| 147 |
} |
| 148 |
$parent_suffix .= '-' . $parent_term->slug; |
| 149 |
if ( ! term_exists( $this->slug . $parent_suffix ) ) { |
| 150 |
break; |
| 151 |
} |
| 152 |
$the_parent = $parent_term->parent; |
| 153 |
} |
| 154 |
|
| 155 |
return $parent_suffix; |
| 156 |
} |
| 157 |
|
| 158 |
/** |
| 159 |
* Returns the term slug, suffixed or not. |
| 160 |
* |
| 161 |
* @since 3.7 |
| 162 |
* |
| 163 |
* @param string $separator The separator for the slug suffix. |
| 164 |
* @return string The suffixed slug, or not if the lang isn't defined. |
| 165 |
*/ |
| 166 |
public function get_suffixed_slug( string $separator ): string { |
| 167 |
if ( ! $this->can_add_suffix() ) { |
| 168 |
return $this->slug; |
| 169 |
} |
| 170 |
|
| 171 |
$term_id = (int) $this->model->term_exists_by_slug( $this->slug, $this->lang, $this->taxonomy, $this->parent ); |
| 172 |
|
| 173 |
// If no term exists in the given language with that slug, it can be created, or if we are editing the existing term. |
| 174 |
if ( ! $term_id || $this->term_id === $term_id ) { |
| 175 |
return $this->slug . $separator . $this->lang->slug; |
| 176 |
} |
| 177 |
|
| 178 |
return $this->slug; |
| 179 |
} |
| 180 |
} |
| 181 |
|