Assuming that your sorting functions actually works and assuming that I'm really really really bad with regex, I've implemented a class that does the job for you:
<?php
class sorter {
private $_array = array();
function __construct($array) {
$this->_array = $array;
}
public function elaborate() {
if (preg_match("~([0-9]+|[0-9])~", $this->_array[0])) {
usort ($this->_array, array('sorter','sort_numeric'));
}
else {
if (preg_match("~(?=^(X)(?=(L)$))|(?=^(L)$)|(?=^(M)$)~", $this->_array[0])) {
usort ($this->_array, array('sorter','sort_size'));
}
else {
usort ($this->_array, array('sorter','sort_text'));
}
}
return $this->_array;
}
protected static function sort_numeric($a, $b) {
return $a - $b;
}
protected static function sort_size($a, $b) {
static $sizes = array('XXS', 'XS', 'S', 'M', 'L', 'XL', 'XXL');
$asize = 100;
$apos = -1;
$bsize = 100;
$bpos = -1;
foreach ($sizes AS $val => $str) {
if (($pos = strpos($a, $str)) !== FALSE && ($apos < 0 || $pos < $apos)) {
$asize = $val;
$apos = $pos;
}
if (($pos = strpos($b, $str)) !== FALSE && ($bpos < 0 || $pos < $bpos)) {
$bsize = $val;
$bpos = $pos;
}
}
return ($asize == $bsize ? 0 : ($asize > $bsize ? 1 : -1));
}
protected static function sort_text($a, $b) {
static $sizes = array("extra small","small","quite small?","something a bit too small","you surely don't fit there.","medium","big","very big","huge","enormous!");
$asize = 100;
$apos = -1;
$bsize = 100;
$bpos = -1;
foreach ($sizes AS $val => $str) {
if (($pos = strpos($a, $str)) !== FALSE && ($apos < 0 || $pos < $apos)) {
$asize = $val;
$apos = $pos;
}
if (($pos = strpos($b, $str)) !== FALSE && ($bpos < 0 || $pos < $bpos)) {
$bsize = $val;
$bpos = $pos;
}
}
return ($asize == $bsize ? 0 : ($asize > $bsize ? 1 : -1));
}
}
?>
For the "type 3" you are talking about, it's basically the EXACT same as the type 2, you just need to implement an array containing the elements the text should contain.
Usage of the code above, following 3 examples:
<?php
$type1 = array("120 cm","100 x 160 cm","10 mm x 30 cm");
$type2 = array("XL","XS","XXL","M");
$type3 = array("very big","small","extra small","something a bit too small");
$sorter = new sorter($type1);
echo "<pre>";
print_r($sorter->elaborate());
echo "</pre>";
$sorter = new sorter($type2);
echo "<pre>";
print_r($sorter->elaborate());
echo "</pre>";
$sorter = new sorter($type3);
echo "<pre>";
print_r($sorter->elaborate());
echo "</pre>";
?>
Output :
Array
(
[0] => 10 mm x 30 cm
[1] => 100 x 160 cm
[2] => 120 cm
)
Array
(
[0] => XS
[1] => M
[2] => XL
[3] => XXL
)
Array
(
[0] => extra small
[1] => small
[2] => something a bit too small
[3] => very big
)
The logic behind this is quite easy:
The first regex checks if any number is inside the first element of the array. If so, it sorts it using the sort_numeric function.
The second regex checks whether the first element of the array starts either with X and finish with L or starts and end with M or L (which should cover the majority of the cases if I'm not wrong): if it does, it uses the sort_size function, else sort_text.
Working sandbox :
http://sandbox.onlinephpfunctions.com/code/9362377a481b0f4f2d33ccdfa4347f4e7c005e92