| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- <?php
- use PHPUnit\Framework\Attributes\Group;
- /**
- * Discussions for the app: every discussion names its category (with the
- * icon the site uses when Studio sets none), and the unit meta sends the
- * reactions element.
- *
- * The test makes its own discussion and image, and restores the category
- * icon row it changes, so it runs on any site with Discussions installed.
- */
- #[Group('integration')]
- class ForumApiTest extends BxDolIntegrationTestCase
- {
- protected $_aGetBackup;
- protected $_aContent;
- protected $_aCategoryRow;
- protected $_iImageId = 0;
- protected function setUp(): void
- {
- parent::setUp();
- $this->_aGetBackup = $_GET;
- if (!BxDolModuleQuery::getInstance()->isEnabledByName('bx_forum'))
- $this->markTestSkipped('Discussions are not installed.');
- $oDb = BxDolDb::getInstance();
- $iCategory = (int)$oDb->getOne("SELECT `Value` FROM `sys_form_pre_values` WHERE `Key` = 'bx_forum_cats' AND `Value` <> '' ORDER BY `Order` LIMIT 1");
- $this->assertGreaterThan(0, $iCategory, 'Discussions install at least one category.');
- $iAuthor = (int)BxDolProfile::getInstanceAccountProfile($this->bxAccount('admin')->id())->id();
- $iNow = time();
- $oDb->query("INSERT INTO `bx_forum_discussions` SET `author` = :author, `added` = :now, `changed` = :now, `lr_timestamp` = :now, `thumb` = 0, `thumb_data` = '', `title` = 'ForumApiTest discussion', `cat` = :cat, `multicat` = '', `text` = '<p>Fixture</p>', `text_comments` = '', `lr_profile_id` = :author, `lr_comment_id` = 0, `labels` = ''", [
- 'author' => $iAuthor,
- 'now' => $iNow,
- 'cat' => $iCategory,
- ]);
- $this->_aContent = $oDb->getRow("SELECT * FROM `bx_forum_discussions` WHERE `id` = :id", ['id' => (int)$oDb->lastId()]);
- // The tests change the category's icon row; keep the original to restore it.
- $this->_aCategoryRow = $oDb->getRow("SELECT * FROM `bx_forum_categories` WHERE `category` = :category", ['category' => $iCategory]);
- }
- protected function tearDown(): void
- {
- $oDb = BxDolDb::getInstance();
- if (!empty($this->_aContent)) {
- $iCategory = (int)$this->_aContent['cat'];
- $oDb->query("DELETE FROM `bx_forum_categories` WHERE `category` = :category", ['category' => $iCategory]);
- if (!empty($this->_aCategoryRow))
- $oDb->query("INSERT INTO `bx_forum_categories` SET `category` = :category, `visible_for_levels` = :levels, `icon` = :icon", [
- 'category' => $iCategory,
- 'levels' => (int)$this->_aCategoryRow['visible_for_levels'],
- 'icon' => $this->_aCategoryRow['icon'],
- ]);
- $oDb->query("DELETE FROM `bx_forum_discussions` WHERE `id` = :id", ['id' => (int)$this->_aContent['id']]);
- }
- if ($this->_iImageId)
- BxDolStorage::getObjectInstance(BX_DOL_STORAGE_OBJ_IMAGES)->deleteFile($this->_iImageId, 0);
- $oDb->cleanMemoryAll();
- $_GET = $this->_aGetBackup ?? [];
- parent::tearDown();
- }
- protected function setCategoryIcon(?string $sIcon): void
- {
- $oDb = BxDolDb::getInstance();
- $iCategory = (int)$this->_aContent['cat'];
- $oDb->query("DELETE FROM `bx_forum_categories` WHERE `category` = :category", ['category' => $iCategory]);
- if ($sIcon !== null)
- $oDb->query("INSERT INTO `bx_forum_categories` SET `category` = :category, `icon` = :icon", ['category' => $iCategory, 'icon' => $sIcon]);
- $oDb->cleanMemoryAll();
- }
- protected function decode(array $aContent): array
- {
- $aResult = BxDolModule::getInstance('bx_forum')->decodeDataApi($aContent);
- $this->assertIsArray($aResult);
- return $aResult;
- }
- public function testCategoryWithoutIconRowFallsBackToFolder(): void
- {
- $this->setCategoryIcon(null);
- $aResult = $this->decode($this->_aContent);
- $this->assertArrayHasKey('category', $aResult);
- $this->assertNotSame('', $aResult['category']['name']);
- $this->assertSame('folder', $aResult['category']['icon']);
- }
- public function testCategoryIconFromStudio(): void
- {
- $this->setCategoryIcon('💬');
- $this->assertSame('💬', $this->decode($this->_aContent)['category']['icon']);
- }
- public function testUploadedIconIsSentAsItsUrl(): void
- {
- // tempnam() creates its own file; the image goes next to it with a .png name.
- $sTmp = tempnam(sys_get_temp_dir(), 'bxforum');
- $sPath = $sTmp . '.png';
- $oStorage = BxDolStorage::getObjectInstance(BX_DOL_STORAGE_OBJ_IMAGES);
- try {
- copy(BX_DIRECTORY_PATH_ROOT . 'template/images/acl-account.png', $sPath);
- $this->_iImageId = (int)$oStorage->storeFileFromPath($sPath, false, 0);
- }
- finally {
- @unlink($sPath);
- @unlink($sTmp);
- }
- if (!$this->_iImageId)
- $this->fail('Store the icon image: ' . $oStorage->getErrorString());
- $this->setCategoryIcon((string)$this->_iImageId);
- $sUrl = $oStorage->getFileUrlById($this->_iImageId);
- $this->assertNotEmpty($sUrl);
- $this->assertSame($sUrl, $this->decode($this->_aContent)['category']['icon']);
- }
- public function testMissingUploadedIconIsNeverTheBareId(): void
- {
- // A storage id with no file behind it: no URL, and never the id.
- $this->setCategoryIcon('2147483000');
- $this->assertSame('', $this->decode($this->_aContent)['category']['icon']);
- }
- public function testNoCategoryNoKey(): void
- {
- $aResult = $this->decode(array_merge($this->_aContent, ['cat' => 0]));
- $this->assertArrayNotHasKey('category', $aResult);
- }
- public function testUnitMetaSendsReactionsElement(): void
- {
- $this->bxLoginAsAdmin();
- $_GET['api'] = 1;
- // Reactions on for this test only (in memory, the site setting is untouched).
- $aSystems = &BxDolVote::getSystems();
- $iIsOn = $aSystems['bx_forum_reactions']['is_on'] ?? null;
- $this->assertNotNull($iIsOn, 'Discussions install the bx_forum_reactions object.');
- $aSystems['bx_forum_reactions']['is_on'] = 1;
- $sVoteKey = 'BxDolVote!bx_forum_reactions' . (int)$this->_aContent['id'];
- unset($GLOBALS['bxDolClasses'][$sVoteKey]);
- $oMenu = BxDolMenu::getObjectInstance('bx_forum_snippet_meta_main');
- $this->assertInstanceOf(BxBaseModGeneralMenuSnippetMeta::class, $oMenu);
- $oIsApi = new ReflectionProperty($oMenu, '_bIsApi');
- $bIsApi = $oIsApi->getValue($oMenu);
- try {
- $oIsApi->setValue($oMenu, true);
- $oMenu->setContentId((int)$this->_aContent['id']);
- $aItem = $this->bxCallProtected($oMenu, '_getMenuItemReactions', ['id' => 1, 'name' => 'reactions']);
- }
- finally {
- // The menu and vote instances are shared: put them back as they were.
- $oIsApi->setValue($oMenu, $bIsApi);
- $aSystems['bx_forum_reactions']['is_on'] = $iIsOn;
- unset($GLOBALS['bxDolClasses'][$sVoteKey]);
- }
- $this->assertIsArray($aItem);
- $this->assertSame('element', $aItem['display_type']);
- $this->assertSame('reactions', $aItem['data']['type']);
- $this->assertSame((int)$this->_aContent['id'], (int)$aItem['data']['object_id']);
- }
- }
|