99use Magento \Catalog \Api \CategoryRepositoryInterface ;
1010use Magento \Catalog \Block \Product \ProductList \Toolbar ;
1111use Magento \Catalog \Model \Category ;
12+ use Magento \Catalog \Model \Config ;
13+ use Magento \Catalog \Model \Layer ;
14+ use Magento \Catalog \Model \Layer \Resolver ;
1215use Magento \Catalog \Model \Product ;
1316use Magento \Catalog \Model \ResourceModel \Product \Collection ;
17+ use Magento \Catalog \Pricing \Price \FinalPrice ;
1418use Magento \Eav \Model \Entity \Collection \AbstractCollection ;
19+ use Magento \Framework \App \ActionInterface ;
20+ use Magento \Framework \App \Config \Element ;
21+ use Magento \Framework \Data \Helper \PostHelper ;
1522use Magento \Framework \DataObject \IdentityInterface ;
1623use Magento \Framework \Exception \NoSuchEntityException ;
24+ use Magento \Framework \Pricing \Render ;
25+ use Magento \Framework \Url \Helper \Data ;
1726
1827/**
1928 * Product list
@@ -40,17 +49,17 @@ class ListProduct extends AbstractProduct implements IdentityInterface
4049 /**
4150 * Catalog layer
4251 *
43- * @var \Magento\Catalog\Model\ Layer
52+ * @var Layer
4453 */
4554 protected $ _catalogLayer ;
4655
4756 /**
48- * @var \Magento\Framework\Data\Helper\ PostHelper
57+ * @var PostHelper
4958 */
5059 protected $ _postDataHelper ;
5160
5261 /**
53- * @var \Magento\Framework\Url\Helper\ Data
62+ * @var Data
5463 */
5564 protected $ urlHelper ;
5665
@@ -61,18 +70,18 @@ class ListProduct extends AbstractProduct implements IdentityInterface
6170
6271 /**
6372 * @param Context $context
64- * @param \Magento\Framework\Data\Helper\ PostHelper $postDataHelper
65- * @param \Magento\Catalog\Model\Layer\ Resolver $layerResolver
73+ * @param PostHelper $postDataHelper
74+ * @param Resolver $layerResolver
6675 * @param CategoryRepositoryInterface $categoryRepository
67- * @param \Magento\Framework\Url\Helper\ Data $urlHelper
76+ * @param Data $urlHelper
6877 * @param array $data
6978 */
7079 public function __construct (
71- \ Magento \ Catalog \ Block \ Product \ Context $ context ,
72- \ Magento \ Framework \ Data \ Helper \ PostHelper $ postDataHelper ,
73- \ Magento \ Catalog \ Model \ Layer \ Resolver $ layerResolver ,
80+ Context $ context ,
81+ PostHelper $ postDataHelper ,
82+ Resolver $ layerResolver ,
7483 CategoryRepositoryInterface $ categoryRepository ,
75- \ Magento \ Framework \ Url \ Helper \ Data $ urlHelper ,
84+ Data $ urlHelper ,
7685 array $ data = []
7786 ) {
7887 $ this ->_catalogLayer = $ layerResolver ->get ();
@@ -113,7 +122,7 @@ protected function _getProductCollection()
113122 /**
114123 * Get catalog layer model
115124 *
116- * @return \Magento\Catalog\Model\ Layer
125+ * @return Layer
117126 */
118127 public function getLayer ()
119128 {
@@ -137,7 +146,35 @@ public function getLoadedProductCollection()
137146 */
138147 public function getMode ()
139148 {
140- return $ this ->getChildBlock ('toolbar ' )->getCurrentMode ();
149+ if ($ this ->getChildBlock ('toolbar ' )) {
150+ return $ this ->getChildBlock ('toolbar ' )->getCurrentMode ();
151+ }
152+
153+ return $ this ->getDefaultListingMode ();
154+ }
155+
156+ /**
157+ * Get listing mode for products if toolbar is removed from layout.
158+ * Use the general configuration for product list mode from config path catalog/frontend/list_mode as default value
159+ * or mode data from block declaration from layout.
160+ *
161+ * @return string
162+ */
163+ private function getDefaultListingMode ()
164+ {
165+ // default Toolbar when the toolbar layout is not used
166+ $ defaultToolbar = $ this ->getToolbarBlock ();
167+ $ availableModes = $ defaultToolbar ->getModes ();
168+
169+ // layout config mode
170+ $ mode = $ this ->getData ('mode ' );
171+
172+ if (!$ mode || !isset ($ availableModes [$ mode ])) {
173+ // default config mode
174+ $ mode = $ defaultToolbar ->getCurrentMode ();
175+ }
176+
177+ return $ mode ;
141178 }
142179
143180 /**
@@ -148,28 +185,60 @@ public function getMode()
148185 protected function _beforeToHtml ()
149186 {
150187 $ collection = $ this ->_getProductCollection ();
151- $ this ->configureToolbar ($ this ->getToolbarBlock (), $ collection );
188+
189+ $ this ->addToolbarBlock ($ collection );
190+
152191 $ collection ->load ();
153192
154193 return parent ::_beforeToHtml ();
155194 }
156195
157196 /**
158- * Retrieve Toolbar block
197+ * Add toolbar block from product listing layout
198+ *
199+ * @param Collection $collection
200+ */
201+ private function addToolbarBlock (Collection $ collection )
202+ {
203+ $ toolbarLayout = $ this ->getToolbarFromLayout ();
204+
205+ if ($ toolbarLayout ) {
206+ $ this ->configureToolbar ($ toolbarLayout , $ collection );
207+ }
208+ }
209+
210+ /**
211+ * Retrieve Toolbar block from layout or a default Toolbar
159212 *
160213 * @return Toolbar
161214 */
162215 public function getToolbarBlock ()
216+ {
217+ $ block = $ this ->getToolbarFromLayout ();
218+
219+ if (!$ block ) {
220+ $ block = $ this ->getLayout ()->createBlock ($ this ->_defaultToolbarBlock , uniqid (microtime ()));
221+ }
222+
223+ return $ block ;
224+ }
225+
226+ /**
227+ * Get toolbar block from layout
228+ *
229+ * @return bool|Toolbar
230+ */
231+ private function getToolbarFromLayout ()
163232 {
164233 $ blockName = $ this ->getToolbarBlockName ();
234+
235+ $ toolbarLayout = false ;
236+
165237 if ($ blockName ) {
166- $ block = $ this ->getLayout ()->getBlock ($ blockName );
167- if ($ block ) {
168- return $ block ;
169- }
238+ $ toolbarLayout = $ this ->getLayout ()->getBlock ($ blockName );
170239 }
171- $ block = $ this -> getLayout ()-> createBlock ( $ this -> _defaultToolbarBlock , uniqid ( microtime ()));
172- return $ block ;
240+
241+ return $ toolbarLayout ;
173242 }
174243
175244 /**
@@ -203,7 +272,7 @@ public function setCollection($collection)
203272 }
204273
205274 /**
206- * @param array|string|integer|\Magento\Framework\App\Config\ Element $code
275+ * @param array|string|integer| Element $code
207276 * @return $this
208277 */
209278 public function addAttribute ($ code )
@@ -223,7 +292,7 @@ public function getPriceBlockTemplate()
223292 /**
224293 * Retrieve Catalog Config object
225294 *
226- * @return \Magento\Catalog\Model\ Config
295+ * @return Config
227296 */
228297 protected function _getConfig ()
229298 {
@@ -233,8 +302,8 @@ protected function _getConfig()
233302 /**
234303 * Prepare Sort By fields from Category Data
235304 *
236- * @param \Magento\Catalog\Model\ Category $category
237- * @return \Magento\Catalog\Block\Product\ListProduct
305+ * @param Category $category
306+ * @return $this
238307 */
239308 public function prepareSortableFieldsByCategory ($ category )
240309 {
@@ -278,38 +347,38 @@ public function getIdentities()
278347 /**
279348 * Get post parameters
280349 *
281- * @param \Magento\Catalog\Model\ Product $product
350+ * @param Product $product
282351 * @return string
283352 */
284- public function getAddToCartPostParams (\ Magento \ Catalog \ Model \ Product $ product )
353+ public function getAddToCartPostParams (Product $ product )
285354 {
286355 $ url = $ this ->getAddToCartUrl ($ product );
287356 return [
288357 'action ' => $ url ,
289358 'data ' => [
290359 'product ' => $ product ->getEntityId (),
291- \ Magento \ Framework \ App \ ActionInterface::PARAM_NAME_URL_ENCODED => $ this ->urlHelper ->getEncodedUrl ($ url ),
360+ ActionInterface::PARAM_NAME_URL_ENCODED => $ this ->urlHelper ->getEncodedUrl ($ url ),
292361 ]
293362 ];
294363 }
295364
296365 /**
297- * @param \Magento\Catalog\Model\ Product $product
366+ * @param Product $product
298367 * @return string
299368 */
300- public function getProductPrice (\ Magento \ Catalog \ Model \ Product $ product )
369+ public function getProductPrice (Product $ product )
301370 {
302371 $ priceRender = $ this ->getPriceRender ();
303372
304373 $ price = '' ;
305374 if ($ priceRender ) {
306375 $ price = $ priceRender ->render (
307- \ Magento \ Catalog \ Pricing \ Price \ FinalPrice::PRICE_CODE ,
376+ FinalPrice::PRICE_CODE ,
308377 $ product ,
309378 [
310379 'include_container ' => true ,
311380 'display_minimal_price ' => true ,
312- 'zone ' => \ Magento \ Framework \ Pricing \ Render::ZONE_ITEM_LIST ,
381+ 'zone ' => Render::ZONE_ITEM_LIST ,
313382 'list_category_page ' => true
314383 ]
315384 );
@@ -322,7 +391,7 @@ public function getProductPrice(\Magento\Catalog\Model\Product $product)
322391 * Specifies that price rendering should be done for the list of products
323392 * i.e. rendering happens in the scope of product list, but not single product
324393 *
325- * @return \Magento\Framework\Pricing\ Render
394+ * @return Render
326395 */
327396 protected function getPriceRender ()
328397 {
@@ -348,7 +417,7 @@ protected function getPriceRender()
348417 private function initializeProductCollection ()
349418 {
350419 $ layer = $ this ->getLayer ();
351- /* @var $layer \Magento\Catalog\Model\ Layer */
420+ /* @var $layer Layer */
352421 if ($ this ->getShowRootCategory ()) {
353422 $ this ->setCategoryId ($ this ->_storeManager ->getStore ()->getRootCategoryId ());
354423 }
@@ -386,9 +455,8 @@ private function initializeProductCollection()
386455 if ($ origCategory ) {
387456 $ layer ->setCurrentCategory ($ origCategory );
388457 }
389-
390- $ toolbar = $ this ->getToolbarBlock ();
391- $ this ->configureToolbar ($ toolbar , $ collection );
458+
459+ $ this ->addToolbarBlock ($ collection );
392460
393461 $ this ->_eventManager ->dispatch (
394462 'catalog_block_product_list_collection ' ,
0 commit comments