dolibarr/test/phpunit/DAVLibTest.php

252 lines
7.2 KiB
PHP
Raw Normal View History

FIX: CDavLib getSqlCalEvents broken after actioncomm_cdav table removal, Add CalDav tests (#39322) * # FIX: CDavLib getSqlCalEvents broken after actioncomm_cdav table removal # FIX: CDavLib getSqlCalEvents broken after actioncomm_cdav table removal, Add CalDav tests Add CalDav tests, which resulted in detecting Issue. ## Issue The `CDavLib::getSqlCalEvents()` method in `htdocs/dav/dav.class.php` has been generating broken SQL queries, causing the new `CDavLibTest::testGetFullCalendarObjects` test to fail. ## Root Cause The issue stems from the removal of the `actioncomm_cdav` table. The original code referenced: - `ac.sourceuid` field (from a non-existent `ac` alias) - `ac.uuidext` field (from the removed `actioncomm_cdav` table) - Used incorrect phone field names (`sp.phone`, `sp.phone_perso`, `sp.phone_mobile`) - Used incorrect country field `sp.fk_pays` instead of `sp.fk_country` - Missing JOIN for the `user` table (`sp` alias) ## Fixes Applied ### 1. SQL String Concatenation Upgraded to the use of `$this->db->prefix()` instead of `.MAIN_DB_PREFIX.` literal strings. ### 2. Phone Field Names Updated phone field names to match current Dolibarr schema: - `sp.phone` → `sp.office_phone as phone` - `sp.phone_perso` → `sp.personal_mobile as phone_perso` - `sp.phone_mobile` → `sp.user_mobile as phone_mobile` ### 3. Country Field Fixed the country JOIN to use the correct field: - `sp.fk_pays` → `sp.fk_country` - `s.fk_pays` remains unchanged (correct for societe table) ### 4. Removed Non-Existent Fields Removed `ac.sourceuid` and `a.sourceuid` from the SELECT clause as these fields do not exist in the `actioncomm` table. These were likely from the removed `actioncomm_cdav` table. ### 5. Added Missing JOINs Added proper JOIN for the user table: ```php LEFT JOIN ' . $this->db->prefix() . 'user as sp ON sp.rowid = a.fk_user_action ``` ### 6. OURI Parameter Handling Fixed the `$ouri` parameter handling to use `a.recurid` instead of the non-existent `ac.uuidext`: ```php // When both OID and OURI are provided $sql .= ' AND (a.id = ' . ((int) $oid) . ' OR a.recurid = \''. $this->db->escape($ouri) . '\')'; // When only OURI is provided } elseif ($ouri !== false) { $sql .= ' AND a.recurid = \''. $this->db->escape($ouri) . '\''; } ``` ## Test Cases Added Added test cases to `test/phpunit/CDavLibTest.php` to verify: 1. OID and OURI parameters together produce SQL with both `a.id =` and `a.recurid =` conditions 2. OURI parameter alone produces SQL with only `a.recurid =` condition (no `a.id =`) ## Regression Origin This regression dates back to when the `actioncomm_cdav` table was removed from Dolibarr. The code was not properly updated to handle the removal, leaving broken references to fields and tables that no longer exist. ## Files Modified - `htdocs/dav/dav.class.php` - Method `getSqlCalEvents()` (lines 69-111) - `test/phpunit/CDavLibTest.php` - Method `testGetSqlCalEvents()` (lines 123-138) ## Verification All CDavLibTest tests pass: - testCdavLibConstruct - testGetSqlCalEvents - testToVCalendar - testGetFullCalendarObjects * FIX: Phan type warnings and PHPUnit 7.x compatibility - Fix Phan type warnings in dav.class.php by casting $ouri to string before escape() - Add PHPUnit compatibility helper in CommonClassTest for assertMatchesRegularExpression which was introduced in PHPUnit 8.0, providing backward compatibility with PHPUnit 7.x Fixes: - PhanTypeMismatchArgument warnings for $ouri parameter - assertMatchesRegularExpression undefined method error in CI with PHPUnit < 8.0
2026-07-30 15:09:34 +00:00
<?php
/* Copyright (C) 2018 Destailleur Laurent <eldy@users.sourceforge.net>
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
* or see https://www.gnu.org/
*/
/**
* \file test/phpunit/DAVLibTest.php
* \ingroup test
* \brief PHPUnit test for DAV library functions
* \remarks To run this script as CLI: phpunit filename.php
*/
global $conf,$user,$langs,$db;
require_once dirname(__FILE__).'/../../htdocs/master.inc.php';
// Define HTTP_HOST before loading dav.lib.php to avoid warning
if (!isset($_SERVER['HTTP_HOST'])) {
$_SERVER['HTTP_HOST'] = 'localhost';
}
require_once dirname(__FILE__).'/../../htdocs/dav/dav.lib.php';
require_once dirname(__FILE__).'/CommonClassTest.class.php';
// Ensure constants are defined for tests
if (!defined('CDAV_URI_KEY')) {
define('CDAV_URI_KEY', substr(md5($_SERVER['HTTP_HOST'] ?? 'localhost'), 0, 8));
}
if (!defined('CDAV_CONTACT_TAG')) {
define('CDAV_CONTACT_TAG', '');
}
if (empty($user->id)) {
print "Load permissions for admin user nb 1\n";
$user->fetch(1);
$user->loadRights();
}
$conf->global->MAIN_DISABLE_ALL_MAILS = 1;
/**
* Class for PHPUnit tests of DAV library functions
*
* @backupGlobals disabled
* @backupStaticAttributes enabled
* @remarks backupGlobals must be disabled to have db,conf,user and lang not erased.
*/
class DAVLibTest extends CommonClassTest
{
/**
* testDavAdminPrepareHead
*
* @return void
*/
public function testDavAdminPrepareHead()
{
global $conf,$user,$langs,$db;
$conf = $this->savconf;
$user = $this->savuser;
$langs = $this->savlangs;
$db = $this->savdb;
// Call the function
$head = dav_admin_prepare_head();
// Check that the result is an array
$this->assertIsArray($head);
// Check that the array is not empty
$this->assertNotEmpty($head);
// Check that the first element has the expected structure
// The first tab should be the WebDAV admin page
$this->assertArrayHasKey(0, $head);
$this->assertIsArray($head[0]);
// Check that the first tab has the expected keys (0=url, 1=title, 2=picto)
$this->assertArrayHasKey(0, $head[0]); // URL
$this->assertArrayHasKey(1, $head[0]); // Title
$this->assertArrayHasKey(2, $head[0]); // Picto
// Check that the URL contains 'dav.php'
$this->assertStringContainsString('dav.php', $head[0][0]);
// Check that the title is 'WebDAV' (translated)
$this->assertSame('WebDAV', $head[0][1]);
// Check that the picto is 'webdav'
$this->assertSame('webdav', $head[0][2]);
print __METHOD__." OK\n";
}
/**
* testCdavConstants
*
* @return void
*/
public function testCdavConstants()
{
global $conf,$user,$langs,$db;
$conf = $this->savconf;
$user = $this->savuser;
$langs = $this->savlangs;
$db = $this->savdb;
// Ensure the constants are defined by including the lib file
// (already included at the top of this file)
// Check that CDAV_CONTACT_TAG is defined
$this->assertTrue(defined('CDAV_CONTACT_TAG'));
// Check that CDAV_URI_KEY is defined
$this->assertTrue(defined('CDAV_URI_KEY'));
// If CDAV_URI_KEY was not set in config, it should have a default value
if (empty(getDolGlobalString('CDAV_URI_KEY'))) {
// It should be generated from HTTP_HOST
$this->assertNotEmpty(CDAV_URI_KEY);
$this->assertSame(8, strlen(CDAV_URI_KEY)); // Should be 8 characters
}
print __METHOD__." OK\n";
}
/**
* testCdavUriKeyGeneration
* Test that CDAV_URI_KEY is generated correctly from different HTTP_HOST values
*
* @return void
*/
public function testCdavUriKeyGeneration()
{
global $conf,$user,$langs,$db;
$conf = $this->savconf;
$user = $this->savuser;
$langs = $this->savlangs;
$db = $this->savdb;
// Test with different HTTP_HOST values
$testHosts = array(
'localhost',
'example.com',
'dolibarr.example.org',
'192.168.1.1'
);
foreach ($testHosts as $host) {
// Simulate different HTTP_HOST
$_SERVER['HTTP_HOST'] = $host;
// Reload the constants by including the lib file again
// Note: We can't easily redefine constants, so we'll just verify the logic
$expectedKey = substr(md5($host), 0, 8);
// Check that the generated key has the correct length
$this->assertSame(8, strlen($expectedKey), "CDAV_URI_KEY for host '$host' should be 8 characters");
// Check that the generated key is alphanumeric (hex)
$this->assertMatchesRegularExpression('/^[0-9a-f]{8}$/', $expectedKey, "CDAV_URI_KEY for host '$host' should be hex");
}
print __METHOD__." OK\n";
}
/**
* testCdavContactTag
* Test CDAV_CONTACT_TAG constant values
*
* @return void
*/
public function testCdavContactTag()
{
global $conf,$user,$langs,$db;
$conf = $this->savconf;
$user = $this->savuser;
$langs = $this->savlangs;
$db = $this->savdb;
// CDAV_CONTACT_TAG should be defined
$this->assertTrue(defined('CDAV_CONTACT_TAG'));
// If not configured, it should default to empty string
if (empty(getDolGlobalString('CDAV_CONTACT_TAG'))) {
$this->assertSame('', CDAV_CONTACT_TAG);
}
// CDAV_CONTACT_TAG should be a string
$this->assertIsString(CDAV_CONTACT_TAG);
print __METHOD__." OK\n";
}
/**
* testDavAdminPrepareHeadStructure
* Test the structure of dav_admin_prepare_head return value in detail
*
* @return void
*/
public function testDavAdminPrepareHeadStructure()
{
global $conf,$user,$langs,$db;
$conf = $this->savconf;
$user = $this->savuser;
$langs = $this->savlangs;
$db = $this->savdb;
$head = dav_admin_prepare_head();
// Check that head is an array of arrays
foreach ($head as $index => $tab) {
$this->assertIsArray($tab, "Tab $index should be an array");
// Each tab should have at least 3 elements: URL, title, picto
$this->assertArrayHasKey(0, $tab, "Tab $index should have URL at index 0");
$this->assertArrayHasKey(1, $tab, "Tab $index should have title at index 1");
$this->assertArrayHasKey(2, $tab, "Tab $index should have picto at index 2");
// URL should be a non-empty string
$this->assertIsString($tab[0], "Tab $index URL should be a string");
$this->assertNotEmpty($tab[0], "Tab $index URL should not be empty");
// Title should be a non-empty string
$this->assertIsString($tab[1], "Tab $index title should be a string");
$this->assertNotEmpty($tab[1], "Tab $index title should not be empty");
// Picto should be a string
$this->assertIsString($tab[2], "Tab $index picto should be a string");
}
// The first tab should be the main DAV admin page
$firstTab = $head[0];
$this->assertStringContainsString('admin/dav.php', $firstTab[0]);
$this->assertSame('WebDAV', $firstTab[1]);
$this->assertSame('webdav', $firstTab[2]);
print __METHOD__." OK\n";
}
}