Collection.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Directory\Model\ResourceModel\Country;
  7. use Magento\Directory\Model\AllowedCountries;
  8. use Magento\Framework\App\ObjectManager;
  9. use Magento\Store\Model\ScopeInterface;
  10. /**
  11. * Country Resource Collection
  12. *
  13. * @api
  14. *
  15. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  16. * @since 100.0.2
  17. */
  18. class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
  19. {
  20. /**
  21. * Locale model
  22. *
  23. * @var \Magento\Framework\Locale\ListsInterface
  24. */
  25. protected $_localeLists;
  26. /**
  27. * Core store config
  28. *
  29. * @var \Magento\Framework\App\Config\ScopeConfigInterface
  30. */
  31. protected $_scopeConfig;
  32. /**
  33. * @var \Magento\Directory\Model\ResourceModel\CountryFactory
  34. */
  35. protected $_countryFactory;
  36. /**
  37. * Array utils object
  38. *
  39. * @var \Magento\Framework\Stdlib\ArrayUtils
  40. */
  41. protected $_arrayUtils;
  42. /**
  43. * @var \Magento\Framework\Locale\ResolverInterface
  44. */
  45. protected $_localeResolver;
  46. /**
  47. * @var \Magento\Directory\Helper\Data
  48. */
  49. protected $helperData;
  50. /**
  51. * @var AllowedCountries
  52. */
  53. private $allowedCountriesReader;
  54. /**
  55. * @var string[]
  56. * @since 100.1.0
  57. */
  58. protected $countriesWithNotRequiredStates;
  59. /**
  60. * @var \Magento\Store\Model\StoreManagerInterface
  61. */
  62. private $storeManager;
  63. /**
  64. * Initialize dependencies.
  65. *
  66. * @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory
  67. * @param \Psr\Log\LoggerInterface $logger
  68. * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
  69. * @param \Magento\Framework\Event\ManagerInterface $eventManager
  70. * @param \Magento\Framework\Locale\ListsInterface $localeLists
  71. * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
  72. * @param \Magento\Directory\Model\ResourceModel\CountryFactory $countryFactory
  73. * @param \Magento\Framework\Stdlib\ArrayUtils $arrayUtils
  74. * @param \Magento\Framework\Locale\ResolverInterface $localeResolver
  75. * @param \Magento\Framework\App\Helper\AbstractHelper $helperData
  76. * @param array $countriesWithNotRequiredStates
  77. * @param mixed $connection
  78. * @param \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource
  79. * @param \Magento\Store\Model\StoreManagerInterface|null $storeManager
  80. * @SuppressWarnings(PHPMD.ExcessiveParameterList)
  81. */
  82. public function __construct(
  83. \Magento\Framework\Data\Collection\EntityFactory $entityFactory,
  84. \Psr\Log\LoggerInterface $logger,
  85. \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
  86. \Magento\Framework\Event\ManagerInterface $eventManager,
  87. \Magento\Framework\Locale\ListsInterface $localeLists,
  88. \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
  89. \Magento\Directory\Model\ResourceModel\CountryFactory $countryFactory,
  90. \Magento\Framework\Stdlib\ArrayUtils $arrayUtils,
  91. \Magento\Framework\Locale\ResolverInterface $localeResolver,
  92. \Magento\Framework\App\Helper\AbstractHelper $helperData,
  93. array $countriesWithNotRequiredStates = [],
  94. \Magento\Framework\DB\Adapter\AdapterInterface $connection = null,
  95. \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource = null,
  96. \Magento\Store\Model\StoreManagerInterface $storeManager = null
  97. ) {
  98. parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $connection, $resource);
  99. $this->_scopeConfig = $scopeConfig;
  100. $this->_localeLists = $localeLists;
  101. $this->_localeResolver = $localeResolver;
  102. $this->_countryFactory = $countryFactory;
  103. $this->_arrayUtils = $arrayUtils;
  104. $this->helperData = $helperData;
  105. $this->countriesWithNotRequiredStates = $countriesWithNotRequiredStates;
  106. $this->storeManager = $storeManager ?: ObjectManager::getInstance()->get(
  107. \Magento\Store\Model\StoreManagerInterface::class
  108. );
  109. }
  110. /**
  111. * Foreground countries
  112. *
  113. * @var array
  114. */
  115. protected $_foregroundCountries = [];
  116. /**
  117. * Add top destinition countries to head of option array
  118. *
  119. * @param string $emptyLabel
  120. * @param array $options
  121. * @return array
  122. */
  123. private function addForegroundCountriesToOptionArray($emptyLabel, $options)
  124. {
  125. if ($emptyLabel !== false && count($this->_foregroundCountries) !== 0 &&
  126. count($options) === count($this->_foregroundCountries)
  127. ) {
  128. $options[] = ['value' => '', 'label' => $emptyLabel];
  129. return $options;
  130. }
  131. return $options;
  132. }
  133. /**
  134. * Define main table
  135. *
  136. * @return void
  137. */
  138. protected function _construct()
  139. {
  140. $this->_init(\Magento\Directory\Model\Country::class, \Magento\Directory\Model\ResourceModel\Country::class);
  141. }
  142. /**
  143. * Return Allowed Countries reader
  144. *
  145. * @deprecated 100.1.2
  146. * @return \Magento\Directory\Model\AllowedCountries
  147. */
  148. private function getAllowedCountriesReader()
  149. {
  150. if (!$this->allowedCountriesReader) {
  151. $this->allowedCountriesReader = ObjectManager::getInstance()->get(AllowedCountries::class);
  152. }
  153. return $this->allowedCountriesReader;
  154. }
  155. /**
  156. * Load allowed countries for current store
  157. *
  158. * @param null|int|string|\Magento\Store\Model\Store $store
  159. * @return \Magento\Directory\Model\ResourceModel\Country\Collection
  160. */
  161. public function loadByStore($store = null)
  162. {
  163. $allowedCountries = $this->getAllowedCountriesReader()
  164. ->getAllowedCountries(ScopeInterface::SCOPE_STORE, $store);
  165. if (!empty($allowedCountries)) {
  166. $this->addFieldToFilter("country_id", ['in' => $allowedCountries]);
  167. }
  168. return $this;
  169. }
  170. /**
  171. * Loads Item By Id
  172. *
  173. * @param string $countryId
  174. * @return \Magento\Directory\Model\ResourceModel\Country|null
  175. */
  176. public function getItemById($countryId)
  177. {
  178. foreach ($this->_items as $country) {
  179. if ($country->getCountryId() == $countryId) {
  180. return $country;
  181. }
  182. }
  183. return null;
  184. }
  185. /**
  186. * Add filter by country code to collection.
  187. *
  188. * $countryCode can be either array of country codes or string representing one country code.
  189. * $iso can be either array containing 'iso2', 'iso3' values or string with containing one of that values directly.
  190. * The collection will contain countries where at least one of country $iso fields matches $countryCode.
  191. *
  192. * @param string|string[] $countryCode
  193. * @param string|string[] $iso
  194. * @return $this
  195. */
  196. public function addCountryCodeFilter($countryCode, $iso = ['iso3', 'iso2'])
  197. {
  198. if (!empty($countryCode)) {
  199. if (is_array($countryCode)) {
  200. if (is_array($iso)) {
  201. $whereOr = [];
  202. foreach ($iso as $iso_curr) {
  203. $whereOr[] .= $this->_getConditionSql("{$iso_curr}_code", ['in' => $countryCode]);
  204. }
  205. $this->_select->where('(' . implode(') OR (', $whereOr) . ')');
  206. } else {
  207. $this->addFieldToFilter("{$iso}_code", ['in' => $countryCode]);
  208. }
  209. } else {
  210. if (is_array($iso)) {
  211. $whereOr = [];
  212. foreach ($iso as $iso_curr) {
  213. $whereOr[] .= $this->_getConditionSql("{$iso_curr}_code", $countryCode);
  214. }
  215. $this->_select->where('(' . implode(') OR (', $whereOr) . ')');
  216. } else {
  217. $this->addFieldToFilter("{$iso}_code", $countryCode);
  218. }
  219. }
  220. }
  221. return $this;
  222. }
  223. /**
  224. * Add filter by country code(s) to collection
  225. *
  226. * @param string|string[] $countryId
  227. * @return $this
  228. */
  229. public function addCountryIdFilter($countryId)
  230. {
  231. if (!empty($countryId)) {
  232. if (is_array($countryId)) {
  233. $this->addFieldToFilter("country_id", ['in' => $countryId]);
  234. } else {
  235. $this->addFieldToFilter("country_id", $countryId);
  236. }
  237. }
  238. return $this;
  239. }
  240. /**
  241. * Convert collection items to select options array
  242. *
  243. * @param string|boolean $emptyLabel
  244. * @return array
  245. */
  246. public function toOptionArray($emptyLabel = ' ')
  247. {
  248. $options = $this->_toOptionArray('country_id', 'name', ['title' => 'iso2_code']);
  249. $sort = [];
  250. foreach ($options as $data) {
  251. $name = (string)$this->_localeLists->getCountryTranslation($data['value']);
  252. if (!empty($name)) {
  253. $sort[$name] = $data['value'];
  254. }
  255. }
  256. $this->_arrayUtils->ksortMultibyte($sort, $this->_localeResolver->getLocale());
  257. foreach (array_reverse($this->_foregroundCountries) as $foregroundCountry) {
  258. $name = array_search($foregroundCountry, $sort);
  259. unset($sort[$name]);
  260. $sort = [$name => $foregroundCountry] + $sort;
  261. }
  262. $isRegionVisible = (bool)$this->helperData->isShowNonRequiredState();
  263. $options = [];
  264. foreach ($sort as $label => $value) {
  265. $options = $this->addForegroundCountriesToOptionArray($emptyLabel, $options);
  266. $option = ['value' => $value, 'label' => $label];
  267. if ($this->helperData->isRegionRequired($value)) {
  268. $option['is_region_required'] = true;
  269. } else {
  270. $option['is_region_visible'] = $isRegionVisible;
  271. }
  272. if ($this->helperData->isZipCodeOptional($value)) {
  273. $option['is_zipcode_optional'] = true;
  274. }
  275. $options[] = $option;
  276. }
  277. if ($emptyLabel !== false && count($options) > 1) {
  278. array_unshift($options, ['value' => '', 'label' => $emptyLabel]);
  279. }
  280. $this->addDefaultCountryToOptions($options);
  281. return $options;
  282. }
  283. /**
  284. * Adds default country to options
  285. *
  286. * @param array $options
  287. * @return void
  288. */
  289. private function addDefaultCountryToOptions(array &$options)
  290. {
  291. $defaultCountry = [];
  292. foreach ($this->storeManager->getWebsites() as $website) {
  293. $defaultCountryConfig = $this->_scopeConfig->getValue(
  294. \Magento\Directory\Helper\Data::XML_PATH_DEFAULT_COUNTRY,
  295. ScopeInterface::SCOPE_WEBSITES,
  296. $website
  297. );
  298. $defaultCountry[$defaultCountryConfig][] = $website->getId();
  299. }
  300. foreach ($options as $key => $option) {
  301. if (isset($defaultCountry[$option['value']])) {
  302. $options[$key]['is_default'] = !empty($defaultCountry[$option['value']]);
  303. }
  304. }
  305. }
  306. /**
  307. * Set foreground countries array
  308. *
  309. * @param string|array $foregroundCountries
  310. * @return $this
  311. */
  312. public function setForegroundCountries($foregroundCountries)
  313. {
  314. if (empty($foregroundCountries)) {
  315. return $this;
  316. }
  317. $this->_foregroundCountries = (array)$foregroundCountries;
  318. return $this;
  319. }
  320. /**
  321. * Get list of countries with required states
  322. *
  323. * @return \Magento\Directory\Model\Country[]
  324. * @since 100.1.0
  325. */
  326. public function getCountriesWithRequiredStates()
  327. {
  328. $countries = [];
  329. foreach ($this->getItems() as $country) {
  330. /** @var \Magento\Directory\Model\Country $country */
  331. if ($country->getRegionCollection()->getSize() > 0
  332. && !in_array($country->getId(), $this->countriesWithNotRequiredStates)
  333. ) {
  334. $countries[$country->getId()] = $country;
  335. }
  336. }
  337. return $countries;
  338. }
  339. }