app->l11nManager, $request, $response); $view->setTemplate('/Modules/Customs/Theme/Backend/sanction-view'); return $view; } /** * Backend method to handle basic search request * * @param RequestAbstract $request Request * @param ResponseAbstract $response Response * @param array $data Generic data * * @return RenderableInterface * * @api * * @since 1.0.0 */ public function viewSanctionDashboard(RequestAbstract $request, ResponseAbstract $response, array $data = []) : RenderableInterface { $view = new View($this->app->l11nManager, $request, $response); $view->setTemplate('/Modules/Customs/Theme/Backend/sanction-dashboard'); $view->data['sanctions'] = []; if (!$request->hasData('name')) { return $view; } $con = new \phpOMS\DataStorage\Database\Connection\SQLiteConnection([ 'db' => 'sqlite', 'database' => __DIR__ . '/../Data/customs.sqlite', ]); $con->connect(); $query = new Builder($con); $nameString = \str_replace(['.', ';', ',', '-'], ' ', $request->getDataString('name') ?? ''); $names = \explode(' ', $nameString); $fileSearchArray = $names; $name = ''; // US SDN and CONS foreach ($names as $idx => $n) { if (empty($n)) { continue; } $name .= ' AND (SDN_name LIKE :name' . $idx . ' OR alt_name LIKE :name' . $idx . ')'; $query->bind(['value' => '%' . $n . '%'], ':name'. $idx); } $name = \ltrim($name, ' AND'); $address = ''; if ($request->hasData('address')) { $address = 'AND (Address LIKE :address OR Address LIKE "%-0-%")'; $query->bind(['value' => '%' . $request->getDataString('address') . '%'], ':address'); $fileSearchArray[] = $request->getDataString('address'); } $city = ''; if ($request->hasData('city')) { $city = 'AND (City_Province_PostalCode LIKE :city OR City_Province_PostalCode LIKE "%-0-%")'; $query->bind(['value' => '%' . $request->getDataString('city') . '%'], ':city'); $fileSearchArray[] = $request->getDataString('city'); } $country = ''; if ($request->hasData('country')) { $country = 'AND (Country LIKE :country OR Country LIKE "%-0-%")'; $query->bind(['value' => '%' . $request->getDataString('country') . '%'], ':country'); $fileSearchArray[] = $request->getDataString('country'); } $sql = <<data['sanctions'] = \array_merge($view->data['sanctions'], $query->raw($sql)->execute()?->fetchAll() ?? []); $sql = <<data['sanctions'] = \array_merge($view->data['sanctions'], $query->raw($sql)->execute()?->fetchAll() ?? []); // EU Consolidated $name = ''; foreach ($names as $idx => $n) { if (empty($n)) { continue; } $name .= ' AND (sanction_eu_cons.NameAlias_WholeName LIKE :name' . $idx . ' OR sanction_eu_cons.NameAlias_Title LIKE :name' . $idx . ')'; $query->bind(['value' => '%' . $n . '%'], ':name' . $idx); } $name = \ltrim($name, ' AND'); $address = ''; if ($request->hasData('address')) { $address = 'AND (address_subquery.Address LIKE :address OR address_subquery.Address = "")'; $query->bind(['value' => '%' . $request->getDataString('address') . '%'], ':address'); } $city = ''; if ($request->hasData('city')) { $city = 'AND (address_subquery.City_Province_PostalCode LIKE :city OR address_subquery.City_Province_PostalCode = "")'; $query->bind(['value' => '%' . $request->getDataString('city') . '%'], ':city'); } $country = ''; if ($request->hasData('country')) { $country = 'AND (address_subquery.Country LIKE :country OR address_subquery.Country = "")'; $query->bind(['value' => '%' . $request->getDataString('country') . '%'], ':country'); } $birthday = ''; if ($request->hasData('birthday')) { $birthday = 'AND (DATE(sanction_eu_cons.BirthDate_BirthDate) = DATE(:birthday) OR sanction_eu_cons.BirthDate_BirthDate = "" OR DATE(address_subquery.BirthDate_BirthDate) = DATE(:birthday) OR address_subquery.BirthDate_BirthDate = "")'; $query->bind(['value' => $request->getDataString('birthday')], ':birthday'); } $identno = ''; if ($request->hasData('identno')) { $identno = 'AND (sanction_eu_cons.Identification_Number LIKE :identno OR sanction_eu_cons.Identification_Number = "" OR address_subquery.Identification_Number LIKE :identno OR address_subquery.Identification_Number = "")'; $query->bind(['value' => '%' . $request->getDataString('identno') . '%'], ':identno'); } $sql = << "" OR Address_City <> "" OR Address_CountryDescription <> "" ) AS address_subquery ON sanction_eu_cons.Entity_LogicalId = address_subquery.Entity_LogicalId WHERE {$name} {$address} {$city} {$country} {$birthday} {$identno} GROUP BY sanction_eu_cons.Entity_LogicalId, sanction_eu_cons.NameAlias_WholeName, sanction_eu_cons.NameAlias_Title, address_subquery.Address, address_subquery.City_Province_PostalCode, address_subquery.Country, sanction_eu_cons.Entity_Remark, 'EU_CONS' LIMIT 500; SQL; $view->data['sanctions'] = \array_merge($view->data['sanctions'], $query->raw($sql)->execute()?->fetchAll() ?? []); $con->close(); // EU 881/2002 $positions = SearchUtils::findInFile(__DIR__ . '/../Data/Sanctions/EU/CELEX 32002R0881 EN TXT.html', $fileSearchArray); $lex_881_2002 = []; $hashResults = []; foreach ($positions as $position) { if ($position['distance'] > 500) { continue; } $sanction = \trim(\strip_tags( SearchUtils::getTextExtract( __DIR__ . '/../Data/Sanctions/EU/CELEX 32002R0881 EN TXT.html', $position['start'], '' ) )); if (\in_array($hash = \sha1($sanction), $hashResults)) { continue; } $hashResults[] = $hash; $lex_881_2002[] = [ 'sanction_db' => 'EU_881/2002', 'Ent_num' => 'EU_881/2002', 'parsed' => $sanction, ]; } $view->data['sanctions'] = \array_merge($view->data['sanctions'], $lex_881_2002); // EU 753/2011 $positions = SearchUtils::findInFile(__DIR__ . '/../Data/Sanctions/EU/CELEX 32011R0753 EN TXT.html', $fileSearchArray); $lex_753_2011 = []; $hashResults = []; foreach ($positions as $position) { if ($position['distance'] > 500) { continue; } $sanction = \trim(\strip_tags( SearchUtils::getTextExtract( __DIR__ . '/../Data/Sanctions/EU/CELEX 32011R0753 EN TXT.html', $position['start'], '' ) )); if (\in_array($hash = \sha1($sanction), $hashResults)) { continue; } $hashResults[] = $hash; $lex_753_2011[] = [ 'sanction_db' => 'EU_753/2011', 'Ent_num' => 'EU_753/2011', 'parsed' => $sanction, ]; } $view->data['sanctions'] = \array_merge($view->data['sanctions'], $lex_753_2011); // EU 2024/385 $positions = SearchUtils::findInFile(__DIR__ . '/../Data/Sanctions/EU/CELEX 32011R0753 EN TXT.html', $fileSearchArray); $lex_2024_385 = []; $hashResults = []; foreach ($positions as $position) { if ($position['distance'] > 500) { continue; } $sanction = \trim(\strip_tags( SearchUtils::getTextExtract( __DIR__ . '/../Data/Sanctions/EU/CELEX 32011R0753 EN TXT.html', $position['start'], '' ) )); if (\in_array($hash = \sha1($sanction), $hashResults)) { continue; } $hashResults[] = $hash; $lex_2024_385[] = [ 'sanction_db' => 'EU_2024/385', 'Ent_num' => 'EU_2024/385', 'parsed' => $sanction, ]; } $view->data['sanctions'] = \array_merge($view->data['sanctions'], $lex_2024_385); return $view; } /** * Create HS code view * * @param RequestAbstract $request Request * @param ResponseAbstract $response Response * @param array $data Generic data * * @return RenderableInterface * * @api * * @since 1.0.0 */ public function viewHSCodeView(RequestAbstract $request, ResponseAbstract $response, array $data = []) : RenderableInterface { $view = new View($this->app->l11nManager, $request, $response); $view->setTemplate('/Modules/Customs/Theme/Backend/hscode-view'); $original = $request->getDataString('id') ?? ''; if (!$request->hasData('id') || \preg_match('/^[0-9 ]+$/', $original) !== 1 ) { return $view; } $con = new \phpOMS\DataStorage\Database\Connection\SQLiteConnection([ 'db' => 'sqlite', 'database' => __DIR__ . '/../Data/customs.sqlite', ]); $con->connect(); $length = \strlen($original); // Also the footnotes of goods_code XX, XXXX, XXXXXX apply besides the actual code $codes = [ $original, \substr($original, 0, 2) . \str_repeat('0', $length - 2), \substr($original, 0, 4) . \str_repeat('0', $length - 4), \substr($original, 0, 6) . \str_repeat('0', $length - 6), ]; $codeString = '"' . \implode('","', $codes) . '"'; $taricString = ''; foreach ($codes as $code) { $taricString .= ' OR taric_good.Goods_code LIKE "' . $code . '%"'; } $taricString = \trim($taricString, 'OR '); $sql = <<data['goods'] = $query->raw($sql)->execute()?->fetchAll() ?? []; if (empty($view->data['goods'])) { return $view; } $sql = <<data['footnotes'] = $query->raw($sql)->execute()?->fetchAll() ?? []; return $view; } /** * Backend method to handle basic search request * * @param RequestAbstract $request Request * @param ResponseAbstract $response Response * @param array $data Generic data * * @return RenderableInterface * * @api * * @since 1.0.0 */ public function viewHSCodeDashboard(RequestAbstract $request, ResponseAbstract $response, array $data = []) : RenderableInterface { $view = new View($this->app->l11nManager, $request, $response); $view->setTemplate('/Modules/Customs/Theme/Backend/hscode-dashboard'); if (!$request->hasData('hscode')) { return $view; } $con = new \phpOMS\DataStorage\Database\Connection\SQLiteConnection([ 'db' => 'sqlite', 'database' => __DIR__ . '/../Data/customs.sqlite', ]); $con->connect(); // Search codes that contain the keyword $sql = <<bind(['value' => '%' . $request->getDataString('hscode') . '%'], ':description'); $query->bind(['value' => '%' . $request->getDataString('hscode') . '%'], ':code'); $temp = $query->raw($sql)->execute()?->fetchAll() ?? []; if (($exactCount = \count($temp)) === 0) { return $view; } // Sometimes sub-categories exist that don't contain the keyword but may be better // For this reason we have to also load all the sub-categories // Create code range by finding the last none-0 value and increasing that value by 1 // While that value is a 9 the value is set to 0 and the left number is increased by 1 $codeRanges = []; $exactMatches = []; foreach ($temp as $code) { $exactMatches[] = $code['Goods_code']; if ($exactCount > 50) { continue; } $length = \strlen($code['Goods_code']); $max = \max( \strrpos($code['Goods_code'], '1', -3), \strrpos($code['Goods_code'], '2', -3), \strrpos($code['Goods_code'], '3', -3), \strrpos($code['Goods_code'], '4', -3), \strrpos($code['Goods_code'], '5', -3), \strrpos($code['Goods_code'], '6', -3), \strrpos($code['Goods_code'], '7', -3), \strrpos($code['Goods_code'], '8', -3), \strrpos($code['Goods_code'], '9', -3), ); $maxCode = $code['Goods_code']; $maxCode[$length - 1] = '0'; $maxCode[$length - 2] = '0'; while ($maxCode[$max] === '9') { $maxCode[$max] = '0'; --$max; } $maxCode[$max] = ((int) $code['Goods_code'][$max]) + 1; $codeRanges[] = '(taric_good.Goods_code >= "' . $code['Goods_code'] . '"' . ' AND taric_good.Goods_code < "' . $maxCode . '")'; } $codeRanges = empty($codeRanges) ? '' : ' OR (' . \implode(' OR ', $codeRanges) . ')'; $exactMatches = '"' . \implode('","', $exactMatches) . '"'; $sql = <<data['codes'] = $query->raw($sql)->execute()?->fetchAll() ?? []; $con->close(); return $view; } }