src/Resource.php
public static function getXmlFileWithPath($xmlObj)
    {
        if (isset(self::$_xmlFileList[$xmlObj])) {
            return self::$_xmlFileList[$xmlObj];
        }
        $xmlFile = $xmlObj;
        if (strpos($xmlObj, ".xml") > 0) {  // remove .xml suffix if any
            $xmlFile = substr($xmlObj, 0, strlen($xmlObj) - 4);
        }

        // replace "." with "/"
        $xmlFile = str_replace(".", "/", $xmlFile);
        // check the leading char '@'
        $checkExtModule = true;
        if (strpos($xmlFile, '@') === 0) {
            $xmlFile = substr($xmlFile, 1);
            $checkExtModule = false;
        }
        $xmlFile .= ".xml";
        $xmlFile = "/" . $xmlFile;

        // find device path first
        if (defined('OPENBIZ_CLIENT_DEVICE')) {
            $path = dirname($xmlFile);
            if (strpos($path, 'view') > 0 || strpos($path, 'form') > 0 || strpos($path, 'widget') > 0) {
                $fname = basename($xmlFile);
                $xmlFileList[] = OPENBIZ_APP_MODULE_PATH . "/$path/" . OPENBIZ_CLIENT_DEVICE . "/$fname";
            }
        }

        // search in modules directory first
        $xmlFileList[] = OPENBIZ_APP_MODULE_PATH . $xmlFile;
        $xmlFileList[] = OPENBIZ_APP_PATH . $xmlFile;
        $xmlFileList[] = OPENBIZ_META . $xmlFile;
        if ($checkExtModule && defined('MODULE_EX_PATH')) {
            array_unshift($xmlFileList, MODULE_EX_PATH . $xmlFile);
        }

        foreach ($xmlFileList as $xmlFileItem) {
            if (file_exists($xmlFileItem)) {
                self::$_xmlFileList[$xmlObj] = $xmlFileItem;
                return $xmlFileItem;
            }
        }
        self::$_xmlFileList[$xmlObj] = null;
        return null;
    }
public static function getXmlFileWithPath($xmlObj)
    {
        if (isset(self::$_xmlFileList[$xmlObj])) {
            return self::$_xmlFileList[$xmlObj];
        }
        $xmlFile = $xmlObj;
        if (strpos($xmlObj, ".xml") > 0) {  // remove .xml suffix if any
            $xmlFile = substr($xmlObj, 0, strlen($xmlObj) - 4);
        }

        // replace "." with "/"
        $xmlFile = str_replace(".", "/", $xmlFile);
        // check the leading char '@'
        $checkExtModule = true;
        if (strpos($xmlFile, '@') === 0) {
            $xmlFile = substr($xmlFile, 1);
            $checkExtModule = false;
        }
        $xmlFile .= ".xml";
        $xmlFile = "/" . $xmlFile;

        // find device path first
        if (defined('OPENBIZ_CLIENT_DEVICE')) {
            $path = dirname($xmlFile);
            if (strpos($path, 'view') > 0 || strpos($path, 'form') > 0 || strpos($path, 'widget') > 0) {
                $fname = basename($xmlFile);
                $xmlFileList[] = OPENBIZ_APP_MODULE_PATH . "/$path/" . OPENBIZ_CLIENT_DEVICE . "/$fname";
            }
        }

        // search in modules directory first
        $xmlFileList[] = OPENBIZ_APP_MODULE_PATH . $xmlFile;
        $xmlFileList[] = OPENBIZ_APP_PATH . $xmlFile;
        $xmlFileList[] = OPENBIZ_META . $xmlFile;
        if ($checkExtModule && defined('MODULE_EX_PATH')) {
            array_unshift($xmlFileList, MODULE_EX_PATH . $xmlFile);
        }

        foreach ($xmlFileList as $xmlFileItem) {
            if (file_exists($xmlFileItem)) {
                self::$_xmlFileList[$xmlObj] = $xmlFileItem;
                return $xmlFileItem;
            }
        }
        self::$_xmlFileList[$xmlObj] = null;
        return null;
    }
Get Xml file with path

Search the object metedata file as objname+.xml in metedata directories
name convension: demo.BOEvent points to metadata/demo/BOEvent.xml
new in 2.2.3, demo.BOEvent can point to modules/demo/BOEvent.xml

@param string $xmlObj xml object name
@return string xml config file path