| 1 |  |  | <?php | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  | namespace SpareParts\Pillar\Assistant\Dibi; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  | use SpareParts\Enum\Converter\MapConverter; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  | use SpareParts\Pillar\Assistant\Dibi\Sorting\ISorting; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  | use SpareParts\Pillar\Assistant\Dibi\Sorting\SortingDirectionEnum; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  | use SpareParts\Pillar\Mapper\Dibi\ColumnInfo; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  | use SpareParts\Pillar\Mapper\Dibi\IEntityMapping; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  | use SpareParts\Pillar\Mapper\Dibi\TableInfo; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  | class Fluent extends \DibiFluent | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 |  |  | { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  | 	 * @var IEntityMapping | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  | 	protected $entityMapping; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 |  |  | 	 * @var IEntityFactory | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 |  |  | 	protected $entityFactory; | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 22 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 23 | 4 |  | 	public function __construct(\DibiConnection $connection, IEntityMapping $entityMapping, IEntityFactory $entityFactory = null) | 
            
                                                                        
                            
            
                                    
            
            
                | 24 |  |  | 	{ | 
            
                                                                        
                            
            
                                    
            
            
                | 25 | 4 |  | 		parent::__construct($connection); | 
            
                                                                        
                            
            
                                    
            
            
                | 26 | 4 |  | 		if ($entityFactory) { | 
            
                                                                        
                            
            
                                    
            
            
                | 27 | 1 |  | 			$this->setupResult('setRowFactory', function (array $data) use ($entityFactory, $entityMapping) { | 
            
                                                                        
                            
            
                                    
            
            
                | 28 | 1 |  | 				return $entityFactory->createEntity($entityMapping->getEntityClassName(), $data); | 
            
                                                                        
                            
            
                                    
            
            
                | 29 | 1 |  | 			}); | 
            
                                                                        
                            
            
                                    
            
            
                | 30 |  |  | 		} | 
            
                                                                        
                            
            
                                    
            
            
                | 31 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 32 | 4 |  | 		$this->entityMapping = $entityMapping; | 
            
                                                                        
                            
            
                                    
            
            
                | 33 | 4 |  | 		$this->entityFactory = $entityFactory; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 34 | 4 |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 35 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 36 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 37 |  |  | 	 * @return $this | 
            
                                                                                                            
                            
            
                                    
            
            
                | 38 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 39 | 1 |  | 	public function selectEntityProperties() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 40 |  |  | 	{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 41 | 1 |  | 		$propertyList = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 42 | 1 |  | 		foreach ($this->entityMapping->getTables() as $table) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 43 | 1 |  | 			foreach ($this->entityMapping->getColumnsForTable($table->getIdentifier()) as $column) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 44 |  |  | 				// each property may be mapped to multiple columns, we are using mapping to the FIRST ACTIVE table and ignoring the rest | 
            
                                                                                                            
                            
            
                                    
            
            
                | 45 | 1 |  | 				if (isset($propertyList[$column->getPropertyName()])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 46 | 1 |  | 					continue; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 47 |  |  | 				} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 |  |  | 				// do not select columns marked as "deprecated" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 49 | 1 |  | 				if ($column->isDeprecated()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 50 |  |  | 					continue; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 |  |  | 				} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 | 1 |  | 				$propertyList[$column->getPropertyName()] = true; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 | 1 |  | 				if ($column->getCustomSelectSql()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 |  |  | 					$this->select($column->getCustomSelectSql())->as($column->getPropertyName()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 |  |  | 				} else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 59 | 1 |  | 					$this->select('%n', sprintf( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 60 | 1 |  | 						'%s.%s', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 61 | 1 |  | 						$column->getTableInfo()->getIdentifier(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 62 | 1 |  | 						$column->getColumnName() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 63 | 1 |  | 					))->as($column->getPropertyName()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 64 |  |  | 				} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 65 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 66 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 | 1 |  | 		return $this; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 |  |  | 	 * @param string[] $propertyList If present, Pillar will try to include only those tables that are needed to select these properties. This might not work 100% of the times, mostly if there is a `silent mid-table` in the joins. In this case use @see $additionalTableList | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 |  |  | 	 * @param string[] $additionalTableList If present, those tables will be used instead of (default) all tables. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 |  |  | 	 * @return $this | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 | 4 |  | 	public function fromEntityDataSources(array $propertyList = null, array $additionalTableList = null) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 |  |  | 	{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 | 4 |  | 		$tables = $this->entityMapping->getTables(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 | 4 |  | 		$primaryTable = array_shift($tables); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 | 4 |  | 		$propertyTables = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 | 4 |  | 		if ($propertyList !== null) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 | 2 |  | 			$propertyTables = $this->preparePropertyTables($propertyList); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 | 4 |  | 		$additionalTables = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 | 4 |  | 		if ($additionalTableList !== null) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 |  |  | 			$additionalTables = array_filter($tables, function (TableInfo $tableInfo) use ($additionalTableList) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 |  |  | 				return in_array($tableInfo->getIdentifier(), $additionalTableList); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 |  |  | 			}); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 | 4 |  | 		$innerJoinTables = array_filter($tables, function (TableInfo $tableInfo) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 | 4 |  | 			return (strtolower(substr($tableInfo->getSqlJoinCode(), 0, 5)) === 'inner'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 | 4 |  | 		}); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 | 4 |  | 		if ($propertyList || $additionalTableList) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 99 |  |  | 			// in case I wish to restrict the result | 
            
                                                                                                            
                            
            
                                    
            
            
                | 100 | 2 |  | 			$tables = array_unique(array_merge($innerJoinTables, $propertyTables, $additionalTables)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 101 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 102 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 103 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 104 | 4 |  | 		$this->from(sprintf( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 105 | 4 |  | 			'`%s` AS `%s`', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 106 | 4 |  | 			$primaryTable->getName(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 107 | 4 |  | 			$primaryTable->getIdentifier() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 108 |  |  | 		)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 109 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 110 | 4 |  | 		foreach ($tables as $table) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 111 | 3 |  | 			$this->__call('', [$table->getSqlJoinCode()]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 112 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 113 | 4 |  | 		return $this; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 114 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 115 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 116 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 117 |  |  | 	 * @param string[] $propertyList | 
            
                                                                                                            
                            
            
                                    
            
            
                | 118 |  |  | 	 * @return TableInfo[] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 119 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 120 |  |  | 	private function preparePropertyTables(array $propertyList) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 121 |  |  | 	{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 122 |  |  | 		// tables that should not be important to select correct row (ie. left joins) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 |  |  | 		/** @var TableInfo[] $optionalTables */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 124 | 2 |  | 		$optionalTables = array_filter($this->entityMapping->getTables(), function (TableInfo $tableInfo) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 125 | 2 |  | 			return (strtolower(substr($tableInfo->getSqlJoinCode(), 0, 4)) === 'left'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 126 | 2 |  | 		}); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 127 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 128 | 2 |  | 		$propertyTables = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 |  |  | 		// find out which of those tables are important for the properties | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 | 2 |  | 		foreach ($optionalTables as $tableInfo) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 | 2 |  | 			$propertyInfoList = $this->entityMapping->getColumnsForTable($tableInfo->getIdentifier()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 132 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 133 | 2 |  | 			$tablePropertyNames = array_map(function (ColumnInfo $columnInfo) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 134 | 2 |  | 				return $columnInfo->getPropertyName(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 135 | 2 |  | 			}, $propertyInfoList); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 136 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 137 | 2 |  | 			if (count(array_intersect($tablePropertyNames, $propertyList))) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 138 | 2 |  | 				$propertyTables[] = $tableInfo; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 139 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 140 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 141 | 2 |  | 		return $propertyTables; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 142 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 143 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 144 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 145 |  |  | 	 * @param ISorting[] $sortingList | 
            
                                                                                                            
                            
            
                                    
            
            
                | 146 |  |  | 	 * @return $this | 
            
                                                                                                            
                            
            
                                    
            
            
                | 147 |  |  | 	 * @throws UnknownPropertyException | 
            
                                                                                                            
                            
            
                                    
            
            
                | 148 |  |  | 	 * @throws \SpareParts\Enum\Converter\UnableToConvertException | 
            
                                                                                                            
                            
            
                                    
            
            
                | 149 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 150 |  |  | 	public function applySorting(array $sortingList) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 151 |  |  | 	{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 152 |  |  | 		if (count($sortingList) === 0) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 153 |  |  | 			// don't try to apply empty $sortingList | 
            
                                                                                                            
                            
            
                                    
            
            
                | 154 |  |  | 			return $this; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 155 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 156 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 157 |  |  | 		/** @var ColumnInfo[] $sortableProperties */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 158 |  |  | 		$sortableProperties = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 159 |  |  | 		foreach ($this->entityMapping->getTables() as $tableInfo) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 160 |  |  | 			foreach ($this->entityMapping->getColumnsForTable($tableInfo->getIdentifier()) as $columnInfo) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 161 |  |  | 				if (isset($sortableProperties[$columnInfo->getPropertyName()])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 162 |  |  | 					continue; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 163 |  |  | 				} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 164 |  |  | 				$sortableProperties[$columnInfo->getPropertyName()] = $columnInfo; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 165 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 166 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 167 |  |  | 		$directionMap = new MapConverter([ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 168 |  |  | 			'ASC' => SortingDirectionEnum::ASCENDING(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 169 |  |  | 			'DESC' => SortingDirectionEnum::DESCENDING(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 170 |  |  | 		]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 171 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 172 |  |  | 		foreach ($sortingList as $sorting) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 173 |  |  | 			if (!isset($sortableProperties[$sorting->getProperty()])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 174 |  |  | 				throw new UnknownPropertyException(sprintf('Unable to map property: `%s` to entity: `%s`, please check whether the provided property name is correct.', $sorting->getProperty(), $this->entityMapping->getEntityClassName())); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 175 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 176 |  |  | 			$columnInfo = $sortableProperties[$sorting->getProperty()]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 177 |  |  | 			$this->orderBy( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 178 |  |  | 				'%n', sprintf( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 179 |  |  | 					'%s.%s', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 180 |  |  | 					$columnInfo->getTableInfo()->getIdentifier(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 181 |  |  | 					$columnInfo->getColumnName() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 182 |  |  | 				), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 183 |  |  | 				$directionMap->fromEnum($sorting->getDirection()) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 184 |  |  | 			); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 185 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 186 |  |  | 		return $this; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 187 |  |  | 	} | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 188 |  |  | } | 
            
                                                        
            
                                    
            
            
                | 189 |  |  |  |