Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
6 / 6
CRAP
100.00% covered (success)
100.00%
1 / 1
Join
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
6 / 6
16
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
6
 getForeignTable
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getColumns
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getJoin
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 render
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
6
 __toString
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * Pop PHP Framework (http://www.popphp.org/)
4 *
5 * @link       https://github.com/popphp/popphp-framework
6 * @author     Nick Sagona, III <dev@nolainteractive.com>
7 * @copyright  Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com)
8 * @license    http://www.popphp.org/license     New BSD License
9 */
10
11/**
12 * @namespace
13 */
14namespace Pop\Db\Sql;
15
16/**
17 * Join class
18 *
19 * @category   Pop
20 * @package    Pop\Db
21 * @author     Nick Sagona, III <dev@nolainteractive.com>
22 * @copyright  Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com)
23 * @license    http://www.popphp.org/license     New BSD License
24 * @version    6.5.0
25 */
26class Join
27{
28
29    /**
30     * Allowed JOIN keywords
31     * @var array
32     */
33    protected static $allowedJoins = [
34        'JOIN', 'LEFT JOIN', 'RIGHT JOIN', 'FULL JOIN',
35        'OUTER JOIN', 'LEFT OUTER JOIN', 'RIGHT OUTER JOIN', 'FULL OUTER JOIN',
36        'INNER JOIN', 'LEFT INNER JOIN', 'RIGHT INNER JOIN', 'FULL INNER JOIN'
37    ];
38
39    /**
40     * SQL object
41     * @var ?AbstractSql
42     */
43    protected ?AbstractSql $sql = null;
44
45    /**
46     * Foreign table
47     * @var ?string
48     */
49    protected ?string $foreignTable = null;
50
51    /**
52     * Columns
53     * @var array
54     */
55    protected array $columns = [];
56
57    /**
58     * Join type
59     * @var string
60     */
61    protected string $join = 'JOIN';
62
63    /**
64     * Constructor
65     *
66     * Instantiate the JOIN object
67     *
68     * @param  AbstractSql $sql
69     * @param  mixed       $foreignTable
70     * @param  array       $columns
71     * @param  string      $join
72     * @throws Exception
73     */
74    public function __construct(AbstractSql $sql, mixed $foreignTable, array $columns, string $join = 'JOIN')
75    {
76        $this->sql = $sql;
77
78        // If it's a sub-select
79        if (($foreignTable instanceof Select) || ($foreignTable instanceof \Pop\Db\Sql)) {
80            $this->foreignTable = (string)$foreignTable;
81        } else if (is_array($foreignTable)) {
82            if (count($foreignTable) !== 1) {
83                throw new Exception('Error: Only one table can be used in JOIN clause.');
84            }
85            $alias = array_key_first($foreignTable);
86            $table = $foreignTable[$alias];
87            $this->foreignTable = $this->sql->quoteId($table) . ' AS ' . $this->sql->quoteId($alias);
88        } else {
89            $this->foreignTable = $this->sql->quoteId($foreignTable);
90        }
91
92        $this->columns = $columns;
93        $this->join    = (in_array(strtoupper($join), self::$allowedJoins)) ? strtoupper($join) : 'JOIN';
94    }
95
96    /**
97     * Get foreign table
98     *
99     * @return string
100     */
101    public function getForeignTable(): string
102    {
103        return $this->foreignTable;
104    }
105
106    /**
107     * Get columns
108     *
109     * @return array
110     */
111    public function getColumns(): array
112    {
113        return $this->columns;
114    }
115
116    /**
117     * Get JOIN type
118     *
119     * @return string
120     */
121    public function getJoin(): string
122    {
123        return $this->join;
124    }
125
126    /**
127     * Render JOIN
128     *
129     * @return string
130     */
131    public function render(): string
132    {
133        $columns = [];
134        foreach ($this->columns as $column1 => $column2) {
135            if (is_array($column2)) {
136                foreach ($column2 as $c) {
137                    $columns[] = ((str_contains($column1, '.')) ? $this->sql->quoteId($column1) : $column1) . ' = ' .
138                        ((str_contains($c, '.')) ? $this->sql->quoteId($c) : $c);
139                }
140            } else {
141                $columns[] = $this->sql->quoteId($column1) . ' = ' . $this->sql->quoteId($column2);
142            }
143        }
144
145        return $this->join . ' ' . $this->foreignTable . ' ON (' . implode(' AND ', $columns) . ')';
146    }
147
148    /**
149     * Return JOIN as string
150     *
151     * @return string
152     */
153    public function __toString(): string
154    {
155        return $this->render();
156    }
157
158}