Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 64
0.00% covered (danger)
0.00%
0 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
CargoLuaLibrary
0.00% covered (danger)
0.00%
0 / 64
0.00% covered (danger)
0.00%
0 / 6
420
0.00% covered (danger)
0.00%
0 / 1
 register
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 cargoQuery
0.00% covered (danger)
0.00%
0 / 31
0.00% covered (danger)
0.00%
0 / 1
42
 cargoFormat
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
30
 convertLuaTableToArray
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
42
 cargoStore
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 cargoDeclare
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3/**
4 * Class for exposing the parser functions for Cargo to Lua.
5 * The functions are available via mw.ext.cargo Lua table.
6 *
7 * @author Yaron Koren.
8 * @author Alexander Mashin.
9 */
10
11class CargoLuaLibrary extends Scribunto_LuaLibraryBase {
12
13    /**
14     * Register two Lua bindings: mw.ext.cargo.query and mw.ext.cargo.format
15     * @return array|null
16     */
17    public function register() {
18        $lib = [
19            'query' => [ $this, 'cargoQuery' ],
20            'format' => [ $this, 'cargoFormat' ],
21            'store' => [ $this, 'cargoStore' ],
22            'declare' => [ $this, 'cargoDeclare' ]
23        ];
24        return $this->getEngine()->registerInterface( __DIR__ . '/../cargo.lua', $lib, [] );
25    }
26
27    /**
28     * Implementation of mw.ext.cargo.query.
29     *
30     * @param string $tables
31     * @param string $fields
32     * @param array|null $args
33     * @return array[]
34     * @throws MWException
35     * @throws Scribunto_LuaError
36     */
37    public function cargoQuery( $tables, $fields, $args ): array {
38        $this->checkType( 'query', 1, $tables, 'string' );
39        $this->checkType( 'query', 2, $fields, 'string' );
40        $this->checkTypeOptional( 'query', 3, $args, 'table', [] );
41
42        $where = $args['where'] ?? null;
43        $join = $args['join'] ?? null;
44        $groupBy = $args['groupBy'] ?? null;
45        $having = $args['having'] ?? null;
46        $orderBy = $args['orderBy'] ?? null;
47        $limit = $args['limit'] ?? null;
48        $offset = $args['offset'] ?? null;
49
50        try {
51            $query = CargoSQLQuery::newFromValues( $tables, $fields, $where, $join,
52                $groupBy, $having, $orderBy, $limit, $offset );
53            $rows = $query->run();
54        } catch ( Exception $e ) {
55            // Allow for error handling within Lua.
56            throw new Scribunto_LuaError( $e->getMessage() );
57        }
58
59        $result = [];
60
61        $fieldArray = CargoUtils::smartSplit( ',', $fields );
62
63        $rowIndex = 1; // because Lua arrays start at 1
64        foreach ( $rows as $row ) {
65            $values = [];
66            foreach ( $fieldArray as $fieldString ) {
67                $alias = $query->getAliasForFieldString( $fieldString );
68                if ( !isset( $row[$alias] ) ) {
69                    if ( !$GLOBALS["wgCargoLegacyNullLuaFieldsAsEmptyString"] ) {
70                        continue;
71                    }
72                    $row[$alias] = "";
73                }
74                $nameArray = CargoUtils::smartSplit( '=', $fieldString );
75                $name = $nameArray[ count( $nameArray ) - 1 ];
76                $values[$name] = htmlspecialchars_decode( $row[$alias] );
77            }
78            $result[$rowIndex++] = $values;
79        }
80
81        return [ $result ];
82    }
83
84    /**
85     * Implementation of mw.ext.cargo.formatTable().
86     *
87     * @param array[] $values A 2D row-based array of associative arrays corresponding to a Lua table.
88     * @param array $params Parameters, as passed to {{#cargo_query:}}.
89     * @return array [ [ 0 => string, 'noparse' => bool, 'isHTML' => bool ] ].
90     */
91    public function cargoFormat( array $values, array $params ): array {
92        $mappings = [];
93        $rows = [];
94        foreach ( self::convertLuaTableToArray( $values ) as $row ) {
95            if ( is_array( $row ) ) {
96                $rows[] = $row;
97                foreach ( $row as $key => $value ) {
98                    if ( !isset( $mappings[$key] ) ) {
99                        $mappings[$key] = $key;
100                    }
101                }
102            }
103        }
104        return [
105            CargoDisplayFormat::formatArray( $this->getParser(), $rows, $mappings, self::convertLuaTableToArray( $params ) )
106        ];
107    }
108
109    /**
110     * Convert 1-based Lua table to 0-based PHP array.
111     *
112     * @param mixed $table
113     *
114     * @return mixed
115     */
116    private static function convertLuaTableToArray( $table ) {
117        if ( is_array( $table ) ) {
118            $converted = [];
119            foreach ( $table as $key => $value ) {
120                if ( is_int( $key ) || is_string( $key ) ) {
121                    $new_key = is_int( $key ) ? $key - 1 : $key;
122                    $converted[$new_key] = self::convertLuaTableToArray( $value );
123                }
124            }
125            return $converted;
126        }
127        return $table;
128    }
129
130    /**
131     * Implementation of mw.ext.cargo.store.
132     *
133     * @param string $table
134     * @param array $args
135     */
136    public function cargoStore( string $table, array $args ) {
137        $this->checkType( 'query', 1, $table, 'string' );
138        $this->checkType( 'query', 2, $args, 'table' );
139        $parser = $this->getParser();
140        CargoStore::storeTable( $parser, $table, $args );
141    }
142
143    /**
144     * Implementation of mw.ext.cargo.declare.
145     *
146     * @param array $args
147     */
148    public function cargoDeclare( array $args ) {
149        $this->checkType( 'query', 1, $args, 'table' );
150        $parser = $this->getParser();
151        CargoDeclare::declareTable( $parser, $args );
152    }
153}