Просмотр исходного кода

Fix product info for locally installed modules (#5706)

Fall back to downloaded module metadata only when the Market returns an empty result, while preserving transport and response errors.
Michael Newton 1 неделя назад
Родитель
Сommit
19f3d3b1d8

+ 9 - 0
studio/classes/BxDolStudioStore.php

@@ -412,6 +412,15 @@ class BxDolStudioStore extends BxTemplStudioWidget
         ));
     }
 
+    protected function loadLocalProduct($sModuleName)
+    {
+        $aModules = BxDolStudioInstallerUtils::getInstance()->getModules(false);
+
+        return isset($aModules[$sModuleName]) && is_array($aModules[$sModuleName])
+            ? $aModules[$sModuleName]
+            : array();
+    }
+
     /*
      * Load package (module, update) using OAuth authorization.
      */

+ 36 - 1
studio/template/scripts/BxBaseStudioStore.php

@@ -608,8 +608,15 @@ class BxBaseStudioStore extends BxDolStudioStore
         $oTemplate = BxDolStudioTemplate::getInstance();
 
         $aProduct = $this->loadProduct($sModuleName);
-        if(empty($aProduct) || !is_array($aProduct))
+        if(empty($aProduct) || !is_array($aProduct)) {
+            $aLocalProduct = array();
+            if(is_array($aProduct))
+                $aLocalProduct = $this->loadLocalProduct($sModuleName);
+            if(!empty($aLocalProduct) && is_array($aLocalProduct))
+                return $this->getLocalProduct($aLocalProduct);
+
             return array('code' => BX_DOL_STUDIO_IU_RC_FAILED, 'message' => (!empty($aProduct) ? $aProduct : _t('_adm_str_err_no_product_info')));
+        }
 
 		$aDownloaded = $this->getDownloadedModules(false);
 
@@ -760,6 +767,34 @@ class BxBaseStudioStore extends BxDolStudioStore
         ];
     }
 
+    protected function getLocalProduct(array $aProduct)
+    {
+        $oTemplate = BxDolStudioTemplate::getInstance();
+        $sContent = $oTemplate->parseHtmlByName('str_product_view_local.html', array(
+            'title' => $aProduct['title'],
+            'vendor' => bx_process_output($aProduct['vendor']),
+            'version' => bx_process_output($aProduct['version']),
+            'bx_if:show_note' => array(
+                'condition' => !empty($aProduct['note']),
+                'content' => array(
+                    'note' => $aProduct['note'],
+                ),
+            ),
+        ));
+
+        return array(
+            'code' => BX_DOL_STUDIO_IU_RC_SUCCESS,
+            'message' => '',
+            'popup' => BxTemplStudioFunctions::getInstance()->popupBox(
+                'bx-std-str-popup-product',
+                $aProduct['title'],
+                $sContent,
+                true
+            ),
+            'screenshots' => 0,
+        );
+    }
+
     protected function getFile($iFileId)
     {
         $mixedResult = $this->loadFile($iFileId);

+ 29 - 0
studio/template/str_product_view_local.html

@@ -0,0 +1,29 @@
+<div class="bx-std-product-view pt-4">
+    <div class="bx-std-pv-line">
+        <span class="bx-std-pv-cpt bx-def-font-grayed">
+            <bx_text:_adm_str_txt_pv_title />:
+        </span> __title__
+    </div>
+    <div class="bx-std-pv-line">
+        <span class="bx-std-pv-cpt bx-def-font-grayed">
+            <bx_text:_adm_str_txt_pv_vendor />:
+        </span> __vendor__
+    </div>
+    <div class="bx-std-pv-line">
+        <span class="bx-std-pv-cpt bx-def-font-grayed">
+            <bx_text:_adm_str_txt_pv_version />:
+        </span> __version__
+    </div>
+    <bx_if:show_note>
+        <div class="bx-std-pv-line">
+            <span class="bx-std-pv-cpt bx-def-font-grayed">
+                <bx_text:_adm_str_txt_pv_description />:
+            </span> __note__
+        </div>
+    </bx_if:show_note>
+    <div class="bx-std-pv-actions bx-def-margin-top">
+        <button type="button" class="bx-btn bx-def-margin-right" onclick="javascript:$('.bx-popup-applied:visible').dolPopupHide();">
+            <bx_text:_adm_btn_cancel_submit />
+        </button>
+    </div>
+</div>

+ 80 - 0
tests/units/studio/BxDolStudioStoreTest.php

@@ -0,0 +1,80 @@
+<?php
+
+class BxDolStudioStoreTestProxy extends BxTemplStudioStore
+{
+    private $aRemoteProduct;
+    private $aLocalProduct;
+
+    public function __construct($mixedRemoteProduct, array $aLocalProduct)
+    {
+        $this->aRemoteProduct = $mixedRemoteProduct;
+        $this->aLocalProduct = $aLocalProduct;
+    }
+
+    public function getProductResult($sModuleName)
+    {
+        return $this->getProduct($sModuleName);
+    }
+
+    protected function loadProduct($sModuleName)
+    {
+        return $this->aRemoteProduct;
+    }
+
+    protected function loadLocalProduct($sModuleName)
+    {
+        return $this->aLocalProduct;
+    }
+}
+
+class BxDolStudioStoreTest extends BxDolTestCase
+{
+    public function testDownloadedModuleMetadataBacksProductPopupWhenMarketLookupFails()
+    {
+        $oStore = new BxDolStudioStoreTestProxy(array(), array(
+            'name' => 'my_una_module_doctor',
+            'title' => 'My UNA Module Doctor',
+            'vendor' => 'My UNA World',
+            'version' => '0.1.1',
+            'note' => 'Studio-only compatibility and repair tooling.',
+        ));
+
+        $aResult = $oStore->getProductResult('my_una_module_doctor');
+
+        $this->assertSame(BX_DOL_STUDIO_IU_RC_SUCCESS, $aResult['code']);
+        $this->assertSame(0, $aResult['screenshots']);
+        $this->assertStringContainsString('My UNA Module Doctor', $aResult['popup']);
+        $this->assertStringContainsString('My UNA World', $aResult['popup']);
+        $this->assertStringContainsString('0.1.1', $aResult['popup']);
+        $this->assertStringContainsString(
+            'Studio-only compatibility and repair tooling.',
+            $aResult['popup']
+        );
+    }
+
+    public function testMarketTransportFailureIsNotHiddenByLocalMetadata()
+    {
+        $oStore = new BxDolStudioStoreTestProxy(false, array(
+            'name' => 'my_una_module_doctor',
+            'title' => 'My UNA Module Doctor',
+            'vendor' => 'My UNA World',
+            'version' => '0.1.1',
+            'note' => 'Studio-only compatibility and repair tooling.',
+        ));
+
+        $aResult = $oStore->getProductResult('my_una_module_doctor');
+
+        $this->assertSame(BX_DOL_STUDIO_IU_RC_FAILED, $aResult['code']);
+        $this->assertArrayNotHasKey('popup', $aResult);
+    }
+
+    public function testMissingMarketAndLocalMetadataKeepsNoProductError()
+    {
+        $oStore = new BxDolStudioStoreTestProxy(array(), array());
+
+        $aResult = $oStore->getProductResult('missing_module');
+
+        $this->assertSame(BX_DOL_STUDIO_IU_RC_FAILED, $aResult['code']);
+        $this->assertArrayNotHasKey('popup', $aResult);
+    }
+}