77use InvalidArgumentException ;
88use PDOException ;
99use tommyknocker \pdodb \connection \ConnectionInterface ;
10- use tommyknocker \pdodb \dialects \DialectInterface ;
1110use tommyknocker \pdodb \helpers \RawValue ;
11+ use tommyknocker \pdodb \query \interfaces \ConditionBuilderInterface ;
12+ use tommyknocker \pdodb \query \interfaces \ExecutionEngineInterface ;
13+ use tommyknocker \pdodb \query \interfaces \ParameterManagerInterface ;
14+ use tommyknocker \pdodb \query \traits \CommonDependenciesTrait ;
15+ use tommyknocker \pdodb \query \traits \ExternalReferenceProcessingTrait ;
16+ use tommyknocker \pdodb \query \traits \IdentifierQuotingTrait ;
17+ use tommyknocker \pdodb \query \traits \RawValueResolutionTrait ;
18+ use tommyknocker \pdodb \query \traits \TableManagementTrait ;
1219
1320class ConditionBuilder implements ConditionBuilderInterface
1421{
15- protected ConnectionInterface $ connection ;
16- protected DialectInterface $ dialect ;
17- protected ParameterManagerInterface $ parameterManager ;
18- protected ExecutionEngineInterface $ executionEngine ;
19- protected RawValueResolver $ rawValueResolver ;
22+ use CommonDependenciesTrait ;
23+ use RawValueResolutionTrait ;
24+ use TableManagementTrait ;
25+ use IdentifierQuotingTrait ;
26+ use ExternalReferenceProcessingTrait ;
2027
2128 /** @var array<int, string|array<string, mixed>> */
2229 protected array $ where = [];
@@ -27,9 +34,6 @@ class ConditionBuilder implements ConditionBuilderInterface
2734 /** @var string|null table name */
2835 protected ?string $ table = null ;
2936
30- /** @var string|null Table prefix */
31- protected ?string $ prefix = null ;
32-
3337 /** @var array<int, string> ORDER BY expressions */
3438 protected array $ order = [];
3539
@@ -42,37 +46,7 @@ public function __construct(
4246 ExecutionEngineInterface $ executionEngine ,
4347 RawValueResolver $ rawValueResolver
4448 ) {
45- $ this ->connection = $ connection ;
46- $ this ->dialect = $ connection ->getDialect ();
47- $ this ->parameterManager = $ parameterManager ;
48- $ this ->executionEngine = $ executionEngine ;
49- $ this ->rawValueResolver = $ rawValueResolver ;
50- }
51-
52- /**
53- * Set table name.
54- *
55- * @param string $table
56- *
57- * @return self
58- */
59- public function setTable (string $ table ): self
60- {
61- $ this ->table = $ table ;
62- return $ this ;
63- }
64-
65- /**
66- * Set table prefix.
67- *
68- * @param string|null $prefix
69- *
70- * @return self
71- */
72- public function setPrefix (?string $ prefix ): self
73- {
74- $ this ->prefix = $ prefix ;
75- return $ this ;
49+ $ this ->initializeCommonDependencies ($ connection , $ parameterManager , $ executionEngine , $ rawValueResolver );
7650 }
7751
7852 /**
@@ -547,37 +521,6 @@ protected function buildSelectSql(): string
547521 return trim ($ sql );
548522 }
549523
550- /**
551- * Quote qualified identifier.
552- *
553- * @param string $name
554- *
555- * @return string
556- */
557- protected function quoteQualifiedIdentifier (string $ name ): string
558- {
559- // If looks like an expression (contains spaces, parentheses, commas or quotes)
560- // treat as raw expression but DO NOT accept suspicious unquoted parts silently.
561- if (preg_match ('/[`\[" \'\s\(\),]/ ' , $ name )) {
562- // allow already-quoted or complex expressions to pass through,
563- // but still protect obvious injection attempts by checking for dangerous tokens
564- if (preg_match ('/;|--|\bDROP\b|\bDELETE\b|\bINSERT\b|\bUPDATE\b|\bSELECT\b|\bUNION\b/i ' , $ name )) {
565- throw new InvalidArgumentException ('Unsafe SQL expression provided as identifier/expression. ' );
566- }
567- return $ name ;
568- }
569-
570- $ parts = explode ('. ' , $ name );
571- foreach ($ parts as $ p ) {
572- // require valid simple identifier parts
573- if (!preg_match ('/^[A-Za-z_][A-Za-z0-9_]*$/ ' , $ p )) {
574- throw new InvalidArgumentException ("Invalid identifier part: {$ p }" );
575- }
576- }
577- $ quoted = array_map (fn ($ p ) => $ this ->dialect ->quoteIdentifier ($ p ), $ parts );
578- return implode ('. ' , $ quoted );
579- }
580-
581524 /**
582525 * Normalize operator (trim and uppercase).
583526 *
@@ -589,75 +532,4 @@ protected function normalizeOperator(string $operator): string
589532 {
590533 return strtoupper (trim ($ operator ));
591534 }
592-
593- /**
594- * Resolve RawValue instances.
595- *
596- * @param string|RawValue $value
597- *
598- * @return string
599- */
600- protected function resolveRawValue (string |RawValue $ value ): string
601- {
602- return $ this ->rawValueResolver ->resolveRawValue ($ value );
603- }
604-
605- /**
606- * Normalizes a table name by prefixing it with the database prefix if it is set.
607- *
608- * @param string|null $table
609- *
610- * @return string The normalized table name.
611- */
612- protected function normalizeTable (?string $ table = null ): string
613- {
614- $ table = $ table ?: $ this ->table ;
615- return $ this ->dialect ->quoteTable ($ this ->prefix . $ table );
616- }
617-
618- /**
619- * Check if a string represents an external table reference.
620- *
621- * @param string $reference The reference to check (e.g., 'users.id')
622- *
623- * @return bool True if it's an external reference
624- */
625- protected function isExternalReference (string $ reference ): bool
626- {
627- // Check if it matches table.column pattern
628- if (!preg_match ('/^[a-zA-Z_][a-zA-Z0-9_]*\.[a-zA-Z_][a-zA-Z0-9_]*$/ ' , $ reference )) {
629- return false ;
630- }
631-
632- $ table = explode ('. ' , $ reference )[0 ];
633- return !$ this ->isTableInCurrentQuery ($ table );
634- }
635-
636- /**
637- * Check if a table is referenced in the current query.
638- *
639- * @param string $tableName The table name to check
640- *
641- * @return bool True if table is in current query
642- */
643- protected function isTableInCurrentQuery (string $ tableName ): bool
644- {
645- return $ this ->table === $ tableName ;
646- }
647-
648- /**
649- * Automatically convert external references to RawValue.
650- *
651- * @param mixed $value The value to process
652- *
653- * @return mixed Processed value
654- */
655- protected function processExternalReferences (mixed $ value ): mixed
656- {
657- if (is_string ($ value ) && $ this ->isExternalReference ($ value )) {
658- return new RawValue ($ value );
659- }
660-
661- return $ value ;
662- }
663535}
0 commit comments