diff options
| author | Lester Caine <lester@lsces.co.uk> | 2026-05-26 14:51:08 +0100 |
|---|---|---|
| committer | Lester Caine <lester@lsces.co.uk> | 2026-05-26 14:51:08 +0100 |
| commit | c4c48710f929286d4b799bcb6fb02bc8c04383a4 (patch) | |
| tree | 54c70fb97bc8faaa4c5621dadb262b05f79d5350 /includes | |
| parent | 2866cb7d576ae8c59137d0c7dbb8e9baf0e6e3f1 (diff) | |
| download | liberty-c4c48710f929286d4b799bcb6fb02bc8c04383a4.tar.gz liberty-c4c48710f929286d4b799bcb6fb02bc8c04383a4.tar.bz2 liberty-c4c48710f929286d4b799bcb6fb02bc8c04383a4.zip | |
Add liberty_xref subsystem: package-agnostic typed cross-references
Replaces per-package xref tables with three shared liberty tables:
liberty_xref_group (tab groups), liberty_xref_item (source definitions),
liberty_xref (records). Column names: group→x_group (Firebird reserved word),
source→item, multi→multiple throughout PHP classes and templates.
- 5.0.1 upgrade creates the three tables + sequence + indexes for existing installs
- schema_inc.php updated so fresh installs also get the tables
- Admin UI: admin_xref_groups and admin_xref_sources pages with package filter
- LibertyContent::loadXrefList / getXrefGroupList / getXrefTypeList updated
- LibertyMime: skip attachment rendering during BIT_INSTALL
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'includes')
| -rwxr-xr-x | includes/classes/LibertyContent.php | 54 | ||||
| -rwxr-xr-x | includes/classes/LibertyMime.php | 5 | ||||
| -rw-r--r-- | includes/classes/LibertyXref.php | 28 | ||||
| -rw-r--r-- | includes/classes/LibertyXrefType.php | 22 |
4 files changed, 57 insertions, 52 deletions
diff --git a/includes/classes/LibertyContent.php b/includes/classes/LibertyContent.php index 6965788..f823236 100755 --- a/includes/classes/LibertyContent.php +++ b/includes/classes/LibertyContent.php @@ -3732,7 +3732,7 @@ class LibertyContent extends LibertyBase implements BitCacheable { // ========================================================================= // Xref methods — generic for any LibertyContent subclass. // Queries scope to $this->mContentTypeGuid so each package sees only its - // own liberty_xref_type / liberty_xref_source / liberty_xref rows. + // own liberty_xref_group / liberty_xref_item / liberty_xref rows. // ========================================================================= /** @@ -3743,7 +3743,7 @@ class LibertyContent extends LibertyBase implements BitCacheable { global $gBitUser; $roles = array_keys( $gBitUser->mRoles ); $bindVars = array_merge( $roles, [ $gBitUser->mUserId ] ); - $query = "SELECT g.*, g.`xref_type` AS source FROM `".BIT_DB_PREFIX."liberty_xref_type` g + $query = "SELECT g.*, g.`x_group` AS source FROM `".BIT_DB_PREFIX."liberty_xref_group` g LEFT OUTER JOIN `".BIT_DB_PREFIX."users_roles_map` purm ON ( purm.`user_id`=".$gBitUser->mUserId." ) AND ( purm.`role_id`=g.`role_id` ) WHERE g.`content_type_guid` = '".$this->mContentTypeGuid."' AND g.`sort_order` > 0 AND (g.`role_id` IN(". implode(',', array_fill(0, count($roles), '?')) ." ) OR purm.`user_id`=?) ORDER BY g.`sort_order`"; @@ -3762,16 +3762,16 @@ class LibertyContent extends LibertyBase implements BitCacheable { global $gBitUser; $roles = array_keys( $gBitUser->mRoles ); $bindVars = array_merge( $roles, [ $gBitUser->mUserId ] ); - $query = "SELECT g.`cross_ref_title` AS `type_name`, g.`source` FROM `".BIT_DB_PREFIX."liberty_xref_source` g - JOIN `".BIT_DB_PREFIX."liberty_xref_type` t ON t.`xref_type` = g.`xref_type` AND t.`content_type_guid` = '".$this->mContentTypeGuid."' + $query = "SELECT g.`cross_ref_title` AS `type_name`, g.`item` FROM `".BIT_DB_PREFIX."liberty_xref_item` g + JOIN `".BIT_DB_PREFIX."liberty_xref_group` t ON t.`x_group` = g.`x_group` AND t.`content_type_guid` = '".$this->mContentTypeGuid."' LEFT OUTER JOIN `".BIT_DB_PREFIX."users_roles_map` purm ON ( purm.`user_id`=".$gBitUser->mUserId." ) AND ( purm.`role_id`=g.`role_id` ) WHERE g.`content_type_guid` = '".$this->mContentTypeGuid."' AND t.`sort_order` = 0 AND (g.`role_id` IN(". implode(',', array_fill(0, count($roles), '?')) ." ) OR purm.`user_id`=?) - ORDER BY g.`source`"; + ORDER BY g.`item`"; $result = $this->mDb->query( $query, $bindVars ); $ret = []; $cnt = 0; while ( $res = $result->fetchRow() ) { - $ret[$cnt]['source'] = $res['source']; + $ret[$cnt]['item'] = $res['item']; $ret[$cnt++]['name'] = trim( $res['type_name'] ); } return $ret; @@ -3783,29 +3783,29 @@ class LibertyContent extends LibertyBase implements BitCacheable { */ public function getXrefTypeList( $xrefGroup = 0, $xrefTemplate = NULL ): array { if ( $xrefTemplate ) { - $query = "SELECT s.`cross_ref_title` AS `type_name`, s.`source`, s.`template` FROM `".BIT_DB_PREFIX."liberty_xref_source` s + $query = "SELECT s.`cross_ref_title` AS `type_name`, s.`item`, s.`template` FROM `".BIT_DB_PREFIX."liberty_xref_item` s WHERE s.`content_type_guid` = '".$this->mContentTypeGuid."' AND s.`template` = '$xrefTemplate' ORDER BY s.`cross_ref_title`"; $result = $this->mDb->query( $query, [] ); } elseif ( $xrefGroup > -1 ) { - $query = "SELECT s.`cross_ref_title` AS `type_name`, s.`source`, s.`template` FROM `".BIT_DB_PREFIX."liberty_xref_source` s - JOIN `".BIT_DB_PREFIX."liberty_xref_type` t ON t.`xref_type` = s.`xref_type` AND t.`content_type_guid` = '".$this->mContentTypeGuid."' - LEFT JOIN `".BIT_DB_PREFIX."liberty_xref` x ON x.`source` = s.`source` AND x.`content_id` = ? AND ( x.`end_date` IS NULL OR x.`end_date` > CURRENT_TIMESTAMP ) + $query = "SELECT s.`cross_ref_title` AS `type_name`, s.`item`, s.`template` FROM `".BIT_DB_PREFIX."liberty_xref_item` s + JOIN `".BIT_DB_PREFIX."liberty_xref_group` t ON t.`x_group` = s.`x_group` AND t.`content_type_guid` = '".$this->mContentTypeGuid."' + LEFT JOIN `".BIT_DB_PREFIX."liberty_xref` x ON x.`item` = s.`item` AND x.`content_id` = ? AND ( x.`end_date` IS NULL OR x.`end_date` > CURRENT_TIMESTAMP ) WHERE s.`content_type_guid` = '".$this->mContentTypeGuid."' AND t.`sort_order` = ? AND ( x.`xref_id` IS NULL OR x.`xorder` > 0 ) ORDER BY s.`cross_ref_title`"; $result = $this->mDb->query( $query, [ $this->mContentId, $xrefGroup ] ); } else { - $query = "SELECT s.`cross_ref_title` AS `type_name`, s.`source`, s.`template` FROM `".BIT_DB_PREFIX."liberty_xref_source` s - JOIN `".BIT_DB_PREFIX."liberty_xref_type` t ON t.`xref_type` = s.`xref_type` AND t.`content_type_guid` = '".$this->mContentTypeGuid."' - LEFT JOIN `".BIT_DB_PREFIX."liberty_xref` x ON x.`source` = s.`source` AND x.`content_id` = ? AND ( x.`end_date` IS NULL OR x.`end_date` > CURRENT_TIMESTAMP ) + $query = "SELECT s.`cross_ref_title` AS `type_name`, s.`item`, s.`template` FROM `".BIT_DB_PREFIX."liberty_xref_item` s + JOIN `".BIT_DB_PREFIX."liberty_xref_group` t ON t.`x_group` = s.`x_group` AND t.`content_type_guid` = '".$this->mContentTypeGuid."' + LEFT JOIN `".BIT_DB_PREFIX."liberty_xref` x ON x.`item` = s.`item` AND x.`content_id` = ? AND ( x.`end_date` IS NULL OR x.`end_date` > CURRENT_TIMESTAMP ) WHERE s.`content_type_guid` = '".$this->mContentTypeGuid."' AND t.`sort_order` > 0 AND ( x.`xref_id` IS NULL OR x.`xorder` > 0 ) ORDER BY s.`cross_ref_title`"; $result = $this->mDb->query( $query, [ $this->mContentId ] ); } $ret = []; while ( $res = $result->fetchRow() ) { - $ret['list'][$res['source']] = trim( $res['type_name'] ); - $ret['type'][$res['source']] = trim( $res['template'] ) !== '' ? trim( $res['template'] ) : 'generic'; + $ret['list'][$res['item']] = trim( $res['type_name'] ); + $ret['type'][$res['item']] = trim( $res['template'] ) !== '' ? trim( $res['template'] ) : 'generic'; } return $ret; } @@ -3817,7 +3817,7 @@ class LibertyContent extends LibertyBase implements BitCacheable { global $gBitUser; $roles = array_keys( $gBitUser->mRoles ); $bindVars = array_merge( $roles, [ $gBitUser->mUserId ] ); - $query = "SELECT DISTINCT g.`template` FROM `".BIT_DB_PREFIX."liberty_xref_source` g + $query = "SELECT DISTINCT g.`template` FROM `".BIT_DB_PREFIX."liberty_xref_item` g LEFT OUTER JOIN `".BIT_DB_PREFIX."users_roles_map` purm ON ( purm.`user_id`=".$gBitUser->mUserId." ) AND ( purm.`role_id`=g.`role_id` ) WHERE g.`content_type_guid` = '".$this->mContentTypeGuid."' AND (g.`role_id` IN(". implode(',', array_fill(0, count($roles), '?')) ." ) OR purm.`user_id`=?) ORDER BY g.`template`"; @@ -3839,13 +3839,13 @@ class LibertyContent extends LibertyBase implements BitCacheable { global $gBitUser; $roles = array_keys( $gBitUser->mRoles ); $bindVars = array_merge( [ $this->mContentId ], $roles, [ $gBitUser->mUserId ] ); - $sql = "SELECT r.`source`, r.`cross_ref_title`, d.`content_id` - FROM `".BIT_DB_PREFIX."liberty_xref_source` r - JOIN `".BIT_DB_PREFIX."liberty_xref_type` t ON t.`xref_type` = r.`xref_type` AND t.`content_type_guid` = '".$this->mContentTypeGuid."' - LEFT JOIN `".BIT_DB_PREFIX."liberty_xref` d ON d.`content_id` = ? AND d.`source` = r.`source` + $sql = "SELECT r.`item`, r.`cross_ref_title`, d.`content_id` + FROM `".BIT_DB_PREFIX."liberty_xref_item` r + JOIN `".BIT_DB_PREFIX."liberty_xref_group` t ON t.`x_group` = r.`x_group` AND t.`content_type_guid` = '".$this->mContentTypeGuid."' + LEFT JOIN `".BIT_DB_PREFIX."liberty_xref` d ON d.`content_id` = ? AND d.`item` = r.`item` LEFT OUTER JOIN `".BIT_DB_PREFIX."users_roles_map` purm ON ( purm.`user_id`=".$gBitUser->mUserId." ) AND ( purm.`role_id`=r.`role_id` ) WHERE r.`content_type_guid` = '".$this->mContentTypeGuid."' AND t.`sort_order` = 0 AND (r.`role_id` IN(". implode(',', array_fill(0, count($roles), '?')) ." ) OR purm.`user_id`=?) - ORDER BY r.`source`"; + ORDER BY r.`item`"; $result = $this->mDb->query( $sql, $bindVars ); while ( $res = $result->fetchRow() ) { $this->mInfo[$this->mXrefTypeKey][] = $res; @@ -3855,17 +3855,17 @@ class LibertyContent extends LibertyBase implements BitCacheable { /** * Loads all xref records for this content item into mInfo keyed by type_source - * (the liberty_xref_type.xref_type text key, or 'history' for expired records). + * (the liberty_xref_group.xref_type text key, or 'history' for expired records). */ public function loadXrefList(): void { if ( $this->isValid() && empty( $this->mInfo['xref'] ) ) { global $gBitUser; $roles = array_keys( $gBitUser->mRoles ); $bindVars = array_merge( [ $this->mDb->NOW(), $this->mContentId ], $roles, [ $gBitUser->mUserId ] ); - $sql = "SELECT s.`xref_type`, x.`xref_id`, x.`last_update_date`, x.`source`, t.`title` AS type_title, + $sql = "SELECT s.`x_group`, x.`xref_id`, x.`last_update_date`, x.`item`, t.`title` AS type_title, CASE WHEN x.`end_date` < ? THEN 'history' - ELSE t.`xref_type` END AS type_source, + ELSE t.`x_group` END AS type_source, CASE WHEN x.`xorder` = 0 THEN s.`cross_ref_title` ELSE s.`cross_ref_title` || '-' || x.`xorder` END @@ -3874,12 +3874,12 @@ class LibertyContent extends LibertyBase implements BitCacheable { x.`start_date`, x.`end_date`, s.`template`, pc.`add1` || ',' || pc.`add2` || ',' || pc.`add4` || ',' || pc.`town` AS address FROM `".BIT_DB_PREFIX."liberty_xref` x - JOIN `".BIT_DB_PREFIX."liberty_xref_source` s ON s.`source` = x.`source` AND s.`content_type_guid` = '".$this->mContentTypeGuid."' + JOIN `".BIT_DB_PREFIX."liberty_xref_item` s ON s.`item` = x.`item` AND s.`content_type_guid` = '".$this->mContentTypeGuid."' LEFT JOIN `".BIT_DB_PREFIX."address_postcode` pc ON pc.`postcode` = x.`xkey` - JOIN `".BIT_DB_PREFIX."liberty_xref_type` t ON t.`xref_type` = s.`xref_type` AND t.`content_type_guid` = '".$this->mContentTypeGuid."' + JOIN `".BIT_DB_PREFIX."liberty_xref_group` t ON t.`x_group` = s.`x_group` AND t.`content_type_guid` = '".$this->mContentTypeGuid."' LEFT OUTER JOIN `".BIT_DB_PREFIX."users_roles_map` purm ON ( purm.`user_id`=".$gBitUser->mUserId." ) AND ( purm.`role_id`=s.`role_id` ) WHERE x.`content_id` = ? AND (s.`role_id` IN(". implode(',', array_fill(0, count($roles), '?')) ." ) OR purm.`user_id`=?) - ORDER BY x.`source`, x.`xorder`"; + ORDER BY x.`item`, x.`xorder`"; $result = $this->mDb->query( $sql, $bindVars ); if ( $result ) { while ( $res = $result->fetchRow() ) { diff --git a/includes/classes/LibertyMime.php b/includes/classes/LibertyMime.php index 7dce907..eaff998 100755 --- a/includes/classes/LibertyMime.php +++ b/includes/classes/LibertyMime.php @@ -48,6 +48,11 @@ class LibertyMime extends LibertyContent { $this->loadAttachmentPreferences(); } + // mime plugins aren't loaded during BIT_INSTALL (active plugin list can't be read from DB), skip attachment rendering + if( defined( 'BIT_INSTALL' ) ) { + return true; + } + $query = "SELECT * FROM `".BIT_DB_PREFIX."liberty_attachments` la WHERE la.`content_id`=? ORDER BY la.`pos` ASC, la.`attachment_id` ASC"; if( $result = $this->mDb->query( $query,[ $this->mContentId ])) { $this->mStorage = []; diff --git a/includes/classes/LibertyXref.php b/includes/classes/LibertyXref.php index 44e874c..1cd17f7 100644 --- a/includes/classes/LibertyXref.php +++ b/includes/classes/LibertyXref.php @@ -11,7 +11,7 @@ use Bitweaver\BitDate; class LibertyXref extends LibertyBase { public $mType; - public $mSource; + public $mItem; public $mXrefId; public $mContentId; public $mDate; @@ -19,7 +19,7 @@ class LibertyXref extends LibertyBase { public function __construct( $iXrefId = NULL ) { $this->mXrefId = NULL; - $this->mSource = NULL; + $this->mItem = NULL; parent::__construct(); if( $iXrefId ) { $this->load( $iXrefId ); @@ -40,20 +40,20 @@ class LibertyXref extends LibertyBase { $sql = "SELECT x.*, CASE WHEN x.`xorder` = 0 THEN s.`cross_ref_title` ELSE s.`cross_ref_title` || '-' || x.`xorder` END - AS source_title, s.`source`, s.`xref_type`, + AS source_title, s.`item`, s.`x_group`, CASE WHEN x.`start_date` IS NULL THEN 'y' ELSE 'n' END AS `ignore_start_date`, CASE WHEN x.`end_date` IS NULL THEN 'y' ELSE 'n' END AS `ignore_end_date`, s.`cross_ref_title` AS `template_title`, s.`template` FROM `".BIT_DB_PREFIX."liberty_xref` x - JOIN `".BIT_DB_PREFIX."liberty_xref_source` s ON s.`source` = x.`source` $guidFilter + JOIN `".BIT_DB_PREFIX."liberty_xref_item` s ON s.`item` = x.`item` $guidFilter WHERE x.`xref_id` = ? ORDER BY x.`xorder`"; $result = $this->mDb->getRow( $sql, $bindVars ); if( $result['content_id'] ) { $this->mXrefId = $pXrefId; $this->mContentId = $result['content_id']; - $this->mType = $result['xref_type']; - $this->mSource = $result['source']; + $this->mType = $result["x_group"]; + $this->mItem = $result['item']; $this->mInfo['title'] = $result['source_title']; $this->mInfo['format_guid'] = 'text'; unset( $result['source_title'] ); @@ -68,28 +68,28 @@ class LibertyXref extends LibertyBase { if( isset( $pParamHash['content_id'] ) ) { $pParamHash['xref_store']['content_id'] = $pParamHash['content_id']; } - if( isset( $pParamHash['source'] ) ) { - $pParamHash['xref_store']['source'] = $pParamHash['source']; + if( isset( $pParamHash['item'] ) ) { + $pParamHash['xref_store']['item'] = $pParamHash['item']; } $pParamHash['xref_store']['xorder'] = 0; if( isset( $pParamHash['fAddXref'] ) ) { - $pParamHash['xref_store']['source'] = isset( $pParamHash['Array_xref_type_list'] ) ? $pParamHash['Array_xref_type_list']['Array.source'] : $pParamHash['source']; + $pParamHash['xref_store']['item'] = isset( $pParamHash['Array_xref_type_list'] ) ? $pParamHash['Array_xref_type_list']['Array.item'] : $pParamHash['item']; $pParamHash['xref_store']['content_id'] = $pParamHash['content_id']; $guidWhere = !empty( $this->mContentTypeGuid ) ? "AND x.`content_type_guid` = ?" : ''; - $guidBind = !empty( $this->mContentTypeGuid ) ? [ $pParamHash['xref_store']['source'], $this->mContentTypeGuid ] : [ $pParamHash['xref_store']['source'] ]; - $sql = "SELECT x.`multi` FROM `".BIT_DB_PREFIX."liberty_xref_source` x WHERE x.`source` = ? $guidWhere"; + $guidBind = !empty( $this->mContentTypeGuid ) ? [ $pParamHash['xref_store']['item'], $this->mContentTypeGuid ] : [ $pParamHash['xref_store']['item'] ]; + $sql = "SELECT x.`multiple` FROM `".BIT_DB_PREFIX."liberty_xref_item` x WHERE x.`item` = ? $guidWhere"; $next = $this->mDb->getOne( $sql, $guidBind ); if( $next > 0 ) { - $sql = "SELECT COALESCE( MAX(x.`xorder`) + 1, 1 ) FROM `".BIT_DB_PREFIX."liberty_xref` x WHERE x.`content_id` = ? AND x.`source` = ?"; - $next = $this->mDb->getOne( $sql, [ $pParamHash['xref_store']['content_id'], $pParamHash['xref_store']['source'] ] ); + $sql = "SELECT COALESCE( MAX(x.`xorder`) + 1, 1 ) FROM `".BIT_DB_PREFIX."liberty_xref` x WHERE x.`content_id` = ? AND x.`item` = ?"; + $next = $this->mDb->getOne( $sql, [ $pParamHash['xref_store']['content_id'], $pParamHash['xref_store']['item'] ] ); } $pParamHash['xref_store']['xorder'] = $next; } if( isset( $pParamHash['fStepXref'] ) ) { - $pParamHash['xref_store']['source'] = $this->mSource; + $pParamHash['xref_store']['item'] = $this->mItem; $pParamHash['xref_store']['xorder'] = $this->mInfo['data']['xorder'] + 1; $pParamHash['xref_store']['content_id'] = $this->mContentId; $pParamHash['start_date'] = $this->mDb->NOW(); diff --git a/includes/classes/LibertyXrefType.php b/includes/classes/LibertyXrefType.php index 00f2cb2..2d64366 100644 --- a/includes/classes/LibertyXrefType.php +++ b/includes/classes/LibertyXrefType.php @@ -28,14 +28,14 @@ class LibertyXrefType extends LibertyBase { $where = " WHERE cxs.`role_id` = ? "; $bindVars[] = $pOptionHash['active_role']; } - if( !empty( $pOptionHash['source'] ) ) { - $where = " WHERE cxs.`source` = ? "; - $bindVars[] = $pOptionHash['source']; + if( !empty( $pOptionHash['item'] ) ) { + $where = " WHERE cxs.`item` = ? "; + $bindVars[] = $pOptionHash['item']; } $query = "SELECT cxs.* - FROM `".BIT_DB_PREFIX."liberty_xref_source` cxs - $where ORDER BY cxs.`xref_type`, cxs.`source`"; + FROM `".BIT_DB_PREFIX."liberty_xref_item` cxs + $where ORDER BY cxs.`x_group`, cxs.`item`"; $result = $gBitSystem->mDb->query( $query, $bindVars ); @@ -52,12 +52,12 @@ class LibertyXrefType extends LibertyBase { } /** - * Returns the distinct content_type_guid values present in liberty_xref_type. + * Returns the distinct content_type_guid values present in liberty_xref_group. */ public static function getContentTypeGuids(): array { global $gBitSystem; $result = $gBitSystem->mDb->query( - "SELECT DISTINCT `content_type_guid` FROM `".BIT_DB_PREFIX."liberty_xref_type` ORDER BY `content_type_guid`", + "SELECT DISTINCT `content_type_guid` FROM `".BIT_DB_PREFIX."liberty_xref_group` ORDER BY `content_type_guid`", [] ); $ret = []; @@ -68,7 +68,7 @@ class LibertyXrefType extends LibertyBase { } /** - * Returns liberty_xref_type rows, optionally filtered by content_type_guid. + * Returns liberty_xref_group rows, optionally filtered by content_type_guid. * Each row includes num_sources: count of sources defined for that group. */ public static function getGroupList( $pOptionHash = NULL ): array { @@ -79,14 +79,14 @@ class LibertyXrefType extends LibertyBase { $where = " WHERE cxt.`content_type_guid` = ?"; $bindVars[] = $pOptionHash['content_type_guid']; } - $query = "SELECT cxt.* FROM `".BIT_DB_PREFIX."liberty_xref_type` cxt + $query = "SELECT cxt.* FROM `".BIT_DB_PREFIX."liberty_xref_group` cxt $where ORDER BY cxt.`content_type_guid`, cxt.`sort_order`"; $result = $gBitSystem->mDb->query( $query, $bindVars ); $ret = []; while ( $res = $result->fetchRow() ) { $res['num_sources'] = $gBitSystem->mDb->getOne( - "SELECT COUNT(*) FROM `".BIT_DB_PREFIX."liberty_xref_source` WHERE `xref_type` = ? AND `content_type_guid` = ?", - [ $res['xref_type'], $res['content_type_guid'] ] + "SELECT COUNT(*) FROM `".BIT_DB_PREFIX."liberty_xref_item` WHERE `x_group` = ? AND `content_type_guid` = ?", + [ $res["x_group"], $res['content_type_guid'] ] ); $ret[] = $res; } |
