PartService.php (6254B)
1 <?php 2 3 namespace PartKeepr\PartBundle\Services; 4 5 use Doctrine\ORM\EntityManager; 6 use PartKeepr\DoctrineReflectionBundle\Filter\Filter; 7 use PartKeepr\DoctrineReflectionBundle\Services\FilterService; 8 use PartKeepr\PartBundle\Entity\Part; 9 use PartKeepr\PartBundle\Entity\PartParameter; 10 use PartKeepr\PartBundle\Exceptions\NotAMetaPartException; 11 12 class PartService 13 { 14 /** 15 * The maximum number of parts allowed. 16 * 17 * @var int|bool 18 */ 19 private $partLimit; 20 21 /** 22 * Whether to check if the internal part number is unique or not. 23 * 24 * @var bool 25 */ 26 private $checkInternalPartNumberUniqueness; 27 28 /** 29 * @var EntityManager 30 */ 31 private $entityManager; 32 33 /** 34 * @var FilterService 35 */ 36 private $filterService; 37 38 public function __construct( 39 EntityManager $entityManager, 40 FilterService $filterService, 41 $partLimit = false, 42 $checkInternalPartNumberUniqueness = false 43 ) { 44 $this->entityManager = $entityManager; 45 $this->filterService = $filterService; 46 $this->partLimit = $partLimit; 47 $this->checkInternalPartNumberUniqueness = $checkInternalPartNumberUniqueness; 48 } 49 50 /** 51 * Returns the number of parts present in the system. 52 * 53 * @return mixed 54 */ 55 public function getPartCount() 56 { 57 $dql = 'SELECT COUNT(p) FROM PartKeepr\\PartBundle\\Entity\\Part p'; 58 $query = $this->entityManager->createQuery($dql); 59 60 return $query->getSingleScalarResult(); 61 } 62 63 /** 64 * Checks if the given internal part number is unique. 65 * 66 * @param string $internalPartNumber The internal part number to checkl 67 * @param Part|null $part An optional part to exclude within the check 68 * 69 * @return bool 70 */ 71 public function isInternalPartNumberUnique($internalPartNumber, Part $part = null) 72 { 73 if (!$this->checkInternalPartNumberUniqueness) { 74 return true; 75 } 76 77 /** 78 * Empty internal part numbers aren't checked. If you want to require an internal part number, set the 79 * field internalPartNumber to mandatory. 80 */ 81 if ($internalPartNumber == "") { 82 return true; 83 } 84 85 $dql = 'SELECT COUNT(p) FROM PartKeepr\\PartBundle\\Entity\\Part p WHERE p.internalPartNumber = :internalPartNumber'; 86 87 if ($part !== null) { 88 $dql .= " AND p.id != :partId"; 89 } 90 91 $query = $this->entityManager->createQuery($dql)->setParameter('internalPartNumber', $internalPartNumber); 92 93 if ($part !== null) { 94 $query->setParameter('partId', $part->getId()); 95 } 96 97 return $query->getSingleScalarResult() == 0 ? true : false; 98 } 99 100 /** 101 * Checks if the amount of parts is exceeded. 102 * 103 * @return bool 104 */ 105 public function checkPartLimit() 106 { 107 if ($this->partLimit !== false && $this->partLimit != "-1") { 108 if ($this->getPartCount() >= $this->partLimit) { 109 return true; 110 } 111 } 112 113 return false; 114 } 115 116 /** 117 * Returns the matching parts for a given meta part. 118 * 119 * @param Part $metaPart 120 * 121 * @return Part[] 122 */ 123 public function getMatchingMetaParts(Part $metaPart) 124 { 125 $paramCount = 0; 126 $paramPrefix = ":param"; 127 $results = []; 128 129 if (!$metaPart->isMetaPart()) { 130 throw new NotAMetaPartException(); 131 } 132 133 foreach ($metaPart->getMetaPartParameterCriterias() as $metaPartParameterCriteria) { 134 $qb = $this->entityManager->createQueryBuilder(); 135 $qb->select("p.id AS id") 136 ->from("PartKeeprPartBundle:PartParameter", "pp") 137 ->join("pp.part", "p") 138 ->where("1=1"); 139 140 $filter = new Filter(); 141 $filter->setOperator($metaPartParameterCriteria->getOperator()); 142 $filter->setProperty("name"); 143 144 switch ($metaPartParameterCriteria->getValueType()) { 145 case PartParameter::VALUE_TYPE_NUMERIC: 146 $expr = $this->filterService->getExpressionForFilter( 147 $filter, 148 "pp.normalizedValue", 149 $paramPrefix.$paramCount 150 ); 151 152 $qb->setParameter($paramPrefix.$paramCount, $metaPartParameterCriteria->getNormalizedValue()); 153 $paramCount++; 154 break; 155 case PartParameter::VALUE_TYPE_STRING: 156 $expr = $this->filterService->getExpressionForFilter( 157 $filter, 158 "pp.stringValue", 159 $paramPrefix.$paramCount 160 ); 161 $qb->setParameter($paramPrefix.$paramCount, $metaPartParameterCriteria->getStringValue()); 162 $paramCount++; 163 break; 164 default: 165 throw new \InvalidArgumentException("Unknown value type"); 166 } 167 168 $expr2 = $qb->expr()->eq("pp.name", $paramPrefix.$paramCount); 169 $qb->setParameter($paramPrefix.$paramCount, $metaPartParameterCriteria->getPartParameterName()); 170 171 $qb->andWhere( 172 $qb->expr()->andX($expr, $expr2) 173 ); 174 175 $result = []; 176 foreach ($qb->getQuery()->getScalarResult() as $partId) { 177 $result[] = $partId["id"]; 178 } 179 180 $results[] = $result; 181 } 182 183 if (count($results) > 1) { 184 $result = call_user_func_array("array_intersect", $results); 185 } else { 186 if (count($results) === 1) { 187 $result = $results[0]; 188 } else { 189 $result = []; 190 } 191 } 192 193 if (count($result) > 0) { 194 $qb = $this->entityManager->createQueryBuilder(); 195 $qb->select("p")->from("PartKeeprPartBundle:Part", "p") 196 ->where( 197 $qb->expr()->in("p.id", ":result") 198 ); 199 200 $qb->setParameter(":result", $result); 201 202 return $qb->getQuery()->getResult(); 203 } else { 204 return []; 205 } 206 } 207 }