1<?php 2 3/** 4 * The definition of a parameter of a function or procedure. 5 */ 6 7namespace PhpMyAdmin\SqlParser\Components; 8 9use PhpMyAdmin\SqlParser\Component; 10use PhpMyAdmin\SqlParser\Context; 11use PhpMyAdmin\SqlParser\Parser; 12use PhpMyAdmin\SqlParser\Token; 13use PhpMyAdmin\SqlParser\TokensList; 14 15/** 16 * The definition of a parameter of a function or procedure. 17 * 18 * @category Components 19 * 20 * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL-2.0+ 21 */ 22class ParameterDefinition extends Component 23{ 24 /** 25 * The name of the new column. 26 * 27 * @var string 28 */ 29 public $name; 30 31 /** 32 * Parameter's direction (IN, OUT or INOUT). 33 * 34 * @var string 35 */ 36 public $inOut; 37 38 /** 39 * The data type of thew new column. 40 * 41 * @var DataType 42 */ 43 public $type; 44 45 /** 46 * Constructor. 47 * 48 * @param string $name parameter's name 49 * @param string $inOut parameter's directional type (IN / OUT or None) 50 * @param DataType $type parameter's type 51 */ 52 public function __construct($name = null, $inOut = null, $type = null) 53 { 54 $this->name = $name; 55 $this->inOut = $inOut; 56 $this->type = $type; 57 } 58 59 /** 60 * @param Parser $parser the parser that serves as context 61 * @param TokensList $list the list of tokens that are being parsed 62 * @param array $options parameters for parsing 63 * 64 * @return ParameterDefinition[] 65 */ 66 public static function parse(Parser $parser, TokensList $list, array $options = array()) 67 { 68 $ret = array(); 69 70 $expr = new self(); 71 72 /** 73 * The state of the parser. 74 * 75 * Below are the states of the parser. 76 * 77 * 0 -----------------------[ ( ]------------------------> 1 78 * 79 * 1 ----------------[ IN / OUT / INOUT ]----------------> 1 80 * 1 ----------------------[ name ]----------------------> 2 81 * 82 * 2 -------------------[ data type ]--------------------> 3 83 * 84 * 3 ------------------------[ , ]-----------------------> 1 85 * 3 ------------------------[ ) ]-----------------------> (END) 86 * 87 * @var int 88 */ 89 $state = 0; 90 91 for (; $list->idx < $list->count; ++$list->idx) { 92 /** 93 * Token parsed at this moment. 94 * 95 * @var Token 96 */ 97 $token = $list->tokens[$list->idx]; 98 99 // End of statement. 100 if ($token->type === Token::TYPE_DELIMITER) { 101 break; 102 } 103 104 // Skipping whitespaces and comments. 105 if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) { 106 continue; 107 } 108 109 if ($state === 0) { 110 if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) { 111 $state = 1; 112 } 113 continue; 114 } elseif ($state === 1) { 115 if (($token->value === 'IN') || ($token->value === 'OUT') || ($token->value === 'INOUT')) { 116 $expr->inOut = $token->value; 117 ++$list->idx; 118 } elseif ($token->value === ')') { 119 ++$list->idx; 120 break; 121 } else { 122 $expr->name = $token->value; 123 $state = 2; 124 } 125 } elseif ($state === 2) { 126 $expr->type = DataType::parse($parser, $list); 127 $state = 3; 128 } elseif ($state === 3) { 129 $ret[] = $expr; 130 $expr = new self(); 131 if ($token->value === ',') { 132 $state = 1; 133 } elseif ($token->value === ')') { 134 ++$list->idx; 135 break; 136 } 137 } 138 } 139 140 // Last iteration was not saved. 141 if (isset($expr->name) && ($expr->name !== '')) { 142 $ret[] = $expr; 143 } 144 145 --$list->idx; 146 147 return $ret; 148 } 149 150 /** 151 * @param ParameterDefinition[] $component the component to be built 152 * @param array $options parameters for building 153 * 154 * @return string 155 */ 156 public static function build($component, array $options = array()) 157 { 158 if (is_array($component)) { 159 return '(' . implode(', ', $component) . ')'; 160 } 161 162 $tmp = ''; 163 if (! empty($component->inOut)) { 164 $tmp .= $component->inOut . ' '; 165 } 166 167 return trim( 168 $tmp . Context::escape($component->name) . ' ' . $component->type 169 ); 170 } 171} 172