public function sort()
    {
        $args = func_get_args();

        if (count($args)==0) {
            return $this;
        }
        if (count($args)>2) {
            throw new InvalidArgumentException('This method takes zero, one or two arguments');
        }
        $columnsToSort = [];

        // One argument and it's a string
        if (count($args)==1 && is_string($args[0])) {
            list($column, $direction) = $this->parseSortColumn($args[0]);
            $columnsToSort[$column] = $direction;
        } elseif (count($args)==2) {
            list($column, $direction) = $this->parseSortColumn($args[0], $args[1]);
            $columnsToSort[$column] = $direction;
        } elseif (is_array($args[0])) {
            foreach ($args[0] as $key => $value) {
                list($column, $direction) = $this->parseSortColumn($key, $value);
                $columnsToSort[$column] = $direction;
            }
        } else {
            throw new InvalidArgumentException("Bad arguments passed to sort()");
        }

        // Store the original keys of the items as a sort fallback, so we can preserve the original order in the event
        // that array_multisort is unable to work out a sort order for them. This also prevents array_multisort trying
        // to inspect object properties which can result in errors with circular dependencies
        $originalKeys = array_keys($this->items);

        // This the main sorting algorithm that supports infinite sorting params
        $multisortArgs = [];
        $values = [];
        $firstRun = true;
        foreach ($columnsToSort as $column => $direction) {
            // The reason these are added to columns is of the references, otherwise when the foreach
            // is done, all $values and $direction look the same
            $values[$column] = [];
            $sortDirection[$column] = $direction;
            // We need to subtract every value into a temporary array for sorting
            foreach ($this->items as $index => $item) {
                $values[$column][] = strtolower($this->extractValue($item, $column));
            }
            // PHP 5.3 requires below arguments to be reference when using array_multisort together
            // with call_user_func_array
            // First argument is the 'value' array to be sorted
            $multisortArgs[] = &$values[$column];
            // First argument is the direction to be sorted,
            $multisortArgs[] = &$sortDirection[$column];
            if ($firstRun) {
                $multisortArgs[] = SORT_REGULAR;
            }
            $firstRun = false;
        }

        $multisortArgs[] = &$originalKeys;

        $list = clone $this;
        // As the last argument we pass in a reference to the items that all the sorting will be applied upon
        $multisortArgs[] = &$list->items;
        call_user_func_array('array_multisort', $multisortArgs);
        return $list;
    }