Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00% covered (danger)
0.00%
0 / 1
75.00% covered (warning)
75.00%
3 / 4
CRAP
97.22% covered (success)
97.22%
35 / 36
InterwikiSorter
0.00% covered (danger)
0.00%
0 / 1
75.00% covered (warning)
75.00%
3 / 4
16
97.22% covered (success)
97.22%
35 / 36
 __construct
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
4 / 4
 sortLinks
100.00% covered (success)
100.00%
1 / 1
4
100.00% covered (success)
100.00%
8 / 8
 compareLinks
0.00% covered (danger)
0.00%
0 / 1
7.02
92.31% covered (success)
92.31%
12 / 13
 buildSortOrder
100.00% covered (success)
100.00%
1 / 1
4
100.00% covered (success)
100.00%
11 / 11
<?php
namespace InterwikiSorting;
/**
 * Language sorting utility functions.
 *
 * @license GPL-2.0-or-later
 * @author Nikola Smolenski <smolensk@eunet.rs>
 * @author Katie Filbert < aude.wiki@gmail.com >
 * @author Thiemo Kreuz
 */
class InterwikiSorter {
    private const SORT_CODE = 'code';
    /**
     * @var array[]
     */
    private $sortOrders;
    /**
     * @var string
     */
    private $sort;
    /**
     * @var string[]
     */
    private $sortPrepend;
    /**
     * @var int[]|null
     */
    private $sortOrder = null;
    /**
     * @param string $sort
     * @param array[] $sortOrders
     * @param string[] $sortPrepend
     */
    public function __construct( $sort, array $sortOrders = [], array $sortPrepend = [] ) {
        $this->sort = $sort;
        $this->sortOrders = $sortOrders;
        $this->sortPrepend = $sortPrepend;
    }
    /**
     * Sort an array of links in-place
     * Copied from InterlanguageExtension rev 114818
     *
     * @param string[] $links
     *
     * @return string[]
     */
    public function sortLinks( array $links ) {
        if ( $this->sortOrder === null ) {
            $this->sortOrder = $this->buildSortOrder( $this->sort, $this->sortOrders );
        }
        // Prepare the array for sorting.
        foreach ( $links as $k => $langLink ) {
            $links[$k] = explode( ':', $langLink, 2 );
        }
        usort( $links, [ $this, 'compareLinks' ] );
        // Restore the sorted array.
        foreach ( $links as $k => $langLink ) {
            $links[$k] = implode( ':', $langLink );
        }
        return $links;
    }
    /**
     * usort() callback function, compares the links on the basis of $sortOrder
     *
     * @param string[] $a
     * @param string[] $b
     *
     * @return int
     */
    private function compareLinks( array $a, array $b ) {
        $a = $a[0];
        $b = $b[0];
        if ( $a === $b ) {
            return 0;
        }
        $aIndex = array_key_exists( $a, $this->sortOrder ) ? $this->sortOrder[$a] : null;
        $bIndex = array_key_exists( $b, $this->sortOrder ) ? $this->sortOrder[$b] : null;
        if ( $aIndex === $bIndex ) {
            // If we encounter multiple unknown languages, which may happen if the sort table is not
            // updated, we list them alphabetically.
            return strcmp( $a, $b );
        } elseif ( $aIndex === null ) {
            // Unknown languages must go under the known languages.
            return 1;
        } elseif ( $bIndex === null ) {
            return -1;
        } else {
            return $aIndex - $bIndex;
        }
    }
    /**
     * Build sort order to be used by compareLinks().
     *
     * @param string $sort
     * @param array[] $sortOrders
     *
     * @return int[]
     */
    private function buildSortOrder( $sort, array $sortOrders ) {
        if ( $sort === self::SORT_CODE ) {
            // The concept of known/unknown languages is irrelevant in strict code order.
            $sortOrder = [];
        } elseif ( !array_key_exists( $sort, $sortOrders ) ) {
            // Something went wrong, but we can use default "code" order.
            wfDebugLog(
                __CLASS__,
                __FUNCTION__ . ': Invalid or unknown sort order specified for interwiki links.'
            );
            $sortOrder = [];
        } else {
            $sortOrder = $sortOrders[$sort];
        }
        if ( $this->sortPrepend !== [] ) {
            $sortOrder = array_unique( array_merge( $this->sortPrepend, $sortOrder ) );
        }
        return array_flip( $sortOrder );
    }
}