Page Menu
Home
In-Portal Phabricator
Search
Configure Global Search
Log In
Files
F1052175
cache_updater.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Fri, Jul 4, 9:28 AM
Size
14 KB
Mime Type
text/x-php
Expires
Sun, Jul 6, 9:28 AM (2 h, 11 m)
Engine
blob
Format
Raw Data
Handle
679468
Attached To
rINP In-Portal
cache_updater.php
View Options
<?php
/**
* @version $Id: cache_updater.php 12231 2009-08-08 18:38:05Z alex $
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.net/license/ for copyright notices and details.
*/
class
clsRecursionStack
{
var
$Stack
;
function
clsRecursionStack
()
{
$this
->
Stack
=
Array
();
}
function
Push
(
$values
)
{
array_push
(
$this
->
Stack
,
$values
);
}
function
Pop
()
{
if
(
$this
->
Count
()
>
0
)
{
return
array_pop
(
$this
->
Stack
);
}
else
{
return
false
;
}
}
function
Get
()
{
if
(
$this
->
Count
()
>
0
)
{
// return end($this->Stack);
return
$this
->
Stack
[
count
(
$this
->
Stack
)-
1
];
}
else
{
return
false
;
}
}
function
Update
(
$values
)
{
$this
->
Stack
[
count
(
$this
->
Stack
)-
1
]
=
$values
;
}
function
Count
()
{
return
count
(
$this
->
Stack
);
}
}
class
clsCachedPermissions
{
var
$Allow
=
Array
();
var
$Deny
=
Array
();
var
$CatId
;
/**
* Table name used for inserting permissions
*
* @var string
*/
var
$table
=
''
;
function
clsCachedPermissions
(
$CatId
,
$table_name
)
{
$this
->
CatId
=
$CatId
;
$this
->
table
=
$table_name
;
}
function
SetCatId
(
$CatId
)
{
$this
->
CatId
=
$CatId
;
}
function
CheckPermArray
(
$Perm
)
{
if
(!
isset
(
$this
->
Allow
[
$Perm
]))
{
$this
->
Allow
[
$Perm
]
=
array
();
$this
->
Deny
[
$Perm
]
=
array
();
}
}
function
AddAllow
(
$Perm
,
$GroupId
)
{
$this
->
CheckPermArray
(
$Perm
);
if
(!
in_array
(
$GroupId
,
$this
->
Allow
[
$Perm
]))
{
array_push
(
$this
->
Allow
[
$Perm
],
$GroupId
);
$this
->
RemoveDeny
(
$Perm
,
$GroupId
);
}
}
function
AddDeny
(
$Perm
,
$GroupId
)
{
$this
->
CheckPermArray
(
$Perm
);
if
(!
in_array
(
$GroupId
,
$this
->
Deny
[
$Perm
]))
{
array_push
(
$this
->
Deny
[
$Perm
],
$GroupId
);
$this
->
RemoveAllow
(
$Perm
,
$GroupId
);
}
}
function
RemoveDeny
(
$Perm
,
$GroupId
)
{
if
(
in_array
(
$GroupId
,
$this
->
Deny
[
$Perm
]))
{
array_splice
(
$this
->
Deny
[
$Perm
],
array_search
(
$GroupId
,
$this
->
Deny
[
$Perm
]),
1
);
}
}
function
RemoveAllow
(
$Perm
,
$GroupId
)
{
if
(
in_array
(
$GroupId
,
$this
->
Allow
[
$Perm
]))
{
array_splice
(
$this
->
Allow
[
$Perm
],
array_search
(
$GroupId
,
$this
->
Allow
[
$Perm
]),
1
);
}
}
function
GetInsertSQL
()
{
$values
=
array
();
foreach
(
$this
->
Allow
as
$perm
=>
$groups
)
{
if
(
count
(
$groups
)
>
0
)
{
$values
[]
=
'('
.
$this
->
CatId
.
', '
.
$perm
.
', "'
.
join
(
','
,
$groups
).
'")'
;
}
}
if
(!
$values
)
return
''
;
$sql
=
'INSERT INTO '
.
$this
->
table
.
' (CategoryId, PermId, ACL) VALUES '
.
join
(
','
,
$values
);
return
$sql
;
}
}
class
kPermCacheUpdater
extends
kHelper
{
/**
* Holds Stack
*
* @var clsRecursionStack
*/
var
$Stack
;
/**
* Rebuild process iteration
*
* @var int
*/
var
$iteration
;
/**
* Categories count to process
*
* @var unknown_type
*/
var
$totalCats
=
0
;
/**
* Processed categories count
*
* @var int
*/
var
$doneCats
=
0
;
/**
* Temporary table name used for storing cache building progress
*
* @var string
*/
var
$progressTable
=
''
;
/**
* Temporary table name used for storing not fully built permissions cache
* 1. preserves previous cache while new cache is building
* 2. when rebuild process fails allows previous cache (in live table) is used
*
* @var string
*/
var
$permCacheTable
=
''
;
var
$primaryLanguageId
=
0
;
var
$languageCount
=
0
;
var
$root_prefixes
=
Array
();
/**
* Update cache only for requested categories and it's parent categories
*
* @var bool
*/
var
$StrictPath
=
false
;
function
Init
(
$prefix
,
$special
,
$event_params
=
null
)
{
parent
::
Init
(
$prefix
,
$special
,
$event_params
);
$continuing
=
isset
(
$event_params
[
'continue'
])
?
$event_params
[
'continue'
]
:
1
;
$this
->
StrictPath
=
isset
(
$event_params
[
'strict_path'
])
?
$event_params
[
'strict_path'
]
:
false
;
if
(
$this
->
StrictPath
&&
!
is_array
(
$this
->
StrictPath
))
{
$this
->
StrictPath
=
explode
(
'|'
,
trim
(
$this
->
StrictPath
,
'|'
));
}
// cache widely used values to speed up process: begin
$ml_helper
=&
$this
->
Application
->
recallObject
(
'kMultiLanguageHelper'
);
/* @var $ml_helper kMultiLanguageHelper */
$this
->
languageCount
=
$ml_helper
->
getLanguageCount
();
$this
->
primaryLanguageId
=
$this
->
Application
->
GetDefaultLanguageId
();
// cache widely used values to speed up process: end
foreach
(
$this
->
Application
->
ModuleInfo
as
$module_name
=>
$module_info
)
{
$this
->
root_prefixes
[
$module_info
[
'RootCat'
]
]
=
$module_info
[
'Var'
];
}
$this
->
iteration
=
0
;
$this
->
progressTable
=
$this
->
Application
->
GetTempName
(
'permCacheUpdate'
);
$this
->
permCacheTable
=
$this
->
Application
->
GetTempName
(
TABLE_PREFIX
.
'PermCache'
);
if
(
$continuing
==
1
)
{
$this
->
InitUpdater
();
}
elseif
(
$continuing
==
2
)
{
$this
->
getData
();
}
}
/**
* Checks if language with specified id is created
*
* @param int $language_id
* @return bool
*/
function
LanguageFound
(
$language_id
)
{
static
$language_ids
=
null
;
if
(!
isset
(
$language_ids
))
{
$ml_helper
=&
$this
->
Application
->
recallObject
(
'kMultiLanguageHelper'
);
/* @var $ml_helper kMultiLanguageHelper */
$language_ids
=
$ml_helper
->
languagesIDs
;
}
return
in_array
(
$language_id
,
$language_ids
)
||
$language_id
<=
5
;
}
function
InitUpdater
()
{
$this
->
Stack
=
new
clsRecursionStack
();
$this
->
initData
();
}
function
getDonePercent
()
{
if
(!
$this
->
totalCats
)
{
return
0
;
}
return
min
(
100
,
intval
(
floor
(
$this
->
doneCats
/
$this
->
totalCats
*
100
)
));
}
function
getData
()
{
$tmp
=
$this
->
Conn
->
GetOne
(
'SELECT data FROM '
.
$this
->
progressTable
);
if
(
$tmp
)
$tmp
=
unserialize
(
$tmp
);
$this
->
totalCats
=
isset
(
$tmp
[
'totalCats'
])
?
$tmp
[
'totalCats'
]
:
0
;
$this
->
doneCats
=
isset
(
$tmp
[
'doneCats'
])
?
$tmp
[
'doneCats'
]
:
0
;
if
(
isset
(
$tmp
[
'stack'
]))
{
$this
->
Stack
=
$tmp
[
'stack'
];
}
else
{
$this
->
Stack
=
new
clsRecursionStack
();
}
}
function
setData
()
{
$tmp
=
Array
(
'totalCats'
=>
$this
->
totalCats
,
'doneCats'
=>
$this
->
doneCats
,
'stack'
=>
$this
->
Stack
,
);
$this
->
Conn
->
Query
(
'DELETE FROM '
.
$this
->
progressTable
);
$fields_hash
=
Array
(
'data'
=>
serialize
(
$tmp
));
$this
->
Conn
->
doInsert
(
$fields_hash
,
$this
->
progressTable
);
}
function
initData
()
{
$this
->
clearData
();
// drop table before starting anyway
// 1. create table for rebuilding permissions cache
$this
->
Conn
->
Query
(
'CREATE TABLE '
.
$this
->
permCacheTable
.
' LIKE '
.
TABLE_PREFIX
.
'PermCache'
);
if
(
$this
->
StrictPath
)
{
// when using strict path leave all other cache intact
$sql
=
'INSERT INTO '
.
$this
->
permCacheTable
.
'
SELECT *
FROM '
.
TABLE_PREFIX
.
'PermCache'
;
$this
->
Conn
->
Query
(
$sql
);
// delete only cache related to categories in path
$sql
=
'DELETE FROM '
.
$this
->
permCacheTable
.
'
WHERE CategoryId IN ('
.
implode
(
','
,
$this
->
StrictPath
).
')'
;
$this
->
Conn
->
Query
(
$sql
);
}
$add_charset
=
defined
(
SQL_CHARSET
)?
' CHARACTER SET '
.
SQL_CHARSET
.
' '
:
''
;
$add_collation
=
defined
(
SQL_COLLATION
)?
' COLLATE '
.
SQL_COLLATION
.
' '
:
''
;
$this
->
Conn
->
Query
(
'CREATE TABLE '
.
$this
->
progressTable
.
'(data LONGTEXT'
.
$add_charset
.
$add_collation
.
') '
.
$add_charset
.
$add_collation
);
$this
->
totalCats
=
(
int
)
$this
->
Conn
->
GetOne
(
'SELECT COUNT(*) FROM '
.
TABLE_PREFIX
.
'Category'
);
$this
->
doneCats
=
0
;
}
function
clearData
()
{
$this
->
Conn
->
Query
(
'DROP TABLE IF EXISTS '
.
$this
->
progressTable
);
$this
->
Conn
->
Query
(
'DROP TABLE IF EXISTS '
.
$this
->
permCacheTable
);
$this
->
Conn
->
Query
(
'DELETE FROM '
.
TABLE_PREFIX
.
'Cache WHERE VarName =
\'
ForcePermCacheUpdate
\'
'
);
$this
->
Conn
->
Query
(
'UPDATE '
.
TABLE_PREFIX
.
'ConfigurationValues SET VariableValue = VariableValue+1 WHERE VariableName =
\'
CategoriesRebuildSerial
\'
'
);
}
function
SaveData
()
{
// copy data from temp permission cache table back to live
$this
->
Conn
->
Query
(
'TRUNCATE '
.
TABLE_PREFIX
.
'PermCache'
);
$sql
=
'INSERT INTO '
.
TABLE_PREFIX
.
'PermCache
SELECT *
FROM '
.
$this
->
permCacheTable
;
$this
->
Conn
->
Query
(
$sql
);
$this
->
clearData
();
}
function
DoTheJob
()
{
$data
=
$this
->
Stack
->
Get
();
if
(
$data
===
false
)
{
//If Stack is empty
$data
[
'current_id'
]
=
0
;
$data
[
'titles'
]
=
Array
();
$data
[
'parent_path'
]
=
Array
();
$data
[
'named_path'
]
=
Array
();
$data
[
'file_name'
]
=
''
;
$data
[
'template'
]
=
''
;
// design
$data
[
'item_template'
]
=
''
;
$data
[
'children_count'
]
=
0
;
$data
[
'left'
]
=
0
;
$data
[
'right'
]
=
2
;
$data
[
'debug_title'
]
=
'ROOT'
;
$this
->
Stack
->
Push
(
$data
);
}
if
(!
isset
(
$data
[
'queried'
]))
{
$this
->
QueryTitle
(
$data
);
$this
->
QueryChildren
(
$data
);
$data
[
'children_count'
]
=
count
(
$data
[
'children'
]);
$this
->
QueryPermissions
(
$data
);
$data
[
'queried'
]
=
1
;
$data
[
'right'
]
=
$data
[
'left'
]+
1
;
if
(
$sql
=
$data
[
'perms'
]->
GetInsertSQL
())
{
$this
->
Conn
->
Query
(
$sql
);
// $this->doneCats++; // moved to the place where it pops out of the stack by Kostja
}
$this
->
iteration
++;
}
// start with first child if we haven't started yet
if
(!
isset
(
$data
[
'current_child'
]))
$data
[
'current_child'
]
=
0
;
// if we have more children on CURRENT LEVEL
if
(
isset
(
$data
[
'children'
][
$data
[
'current_child'
]]))
{
if
(
$this
->
StrictPath
)
{
while
(
isset
(
$data
[
'children'
][
$data
[
'current_child'
]
])
&&
!
in_array
(
$data
[
'children'
][
$data
[
'current_child'
]
],
$this
->
StrictPath
)
)
{
$data
[
'current_child'
]++;
continue
;
}
if
(!
isset
(
$data
[
'children'
][
$data
[
'current_child'
]
]))
return
false
;
//error
}
$next_data
=
Array
();
$next_data
[
'titles'
]
=
$data
[
'titles'
];
$next_data
[
'parent_path'
]
=
$data
[
'parent_path'
];
$next_data
[
'named_path'
]
=
$data
[
'named_path'
];
$next_data
[
'template'
]
=
$data
[
'template'
];
$next_data
[
'item_template'
]
=
$data
[
'item_template'
];
$next_data
[
'current_id'
]
=
$data
[
'children'
][
$data
[
'current_child'
]
];
//next iteration should process child
$next_data
[
'perms'
]
=
$data
[
'perms'
];
//we should copy our permissions to child - inheritance
$next_data
[
'perms'
]->
SetCatId
(
$next_data
[
'current_id'
]);
$next_data
[
'left'
]
=
$data
[
'right'
];
$data
[
'current_child'
]++;
$this
->
Stack
->
Update
(
$data
);
//we need to update ourself for the iteration after the next (or further) return to next child
$this
->
Stack
->
Push
(
$next_data
);
//next iteration should process this child
return
true
;
}
else
{
$this
->
Stack
->
Update
(
$data
);
$prev_data
=
$this
->
Stack
->
Pop
();
//remove ourself from stack if we have finished all the childs (or there are none)
$data
[
'right'
]
=
$prev_data
[
'right'
];
$this
->
UpdateCachedPath
(
$data
);
// we are getting here if we finished with current level, so check if it's first level - then bail out.
$this
->
doneCats
++;
// moved by Kostja from above, seems to fix the prob
$has_more
=
$this
->
Stack
->
Count
()
>
0
;
if
(
$has_more
)
{
$next_data
=
$this
->
Stack
->
Get
();
$next_data
[
'right'
]
=
$data
[
'right'
]+
1
;
$next_data
[
'children_count'
]
+=
$data
[
'children_count'
];
$this
->
Stack
->
Update
(
$next_data
);
}
return
$has_more
;
}
}
function
UpdateCachedPath
(&
$data
)
{
$fields_hash
=
Array
(
'ParentPath'
=>
'|'
.
implode
(
'|'
,
$data
[
'parent_path'
]).
'|'
,
// allow old fashion system templates to work
'NamedParentPath'
=>
strpos
(
$data
[
'file_name'
],
'/'
)
!==
false
?
$data
[
'file_name'
]
:
implode
(
'/'
,
$data
[
'named_path'
]
),
'CachedTemplate'
=>
$data
[
'template'
],
'CachedDescendantCatsQty'
=>
$data
[
'children_count'
],
'TreeLeft'
=>
$data
[
'left'
],
'TreeRight'
=>
$data
[
'right'
],
);
$i
=
1
;
while
(
$i
<=
$this
->
languageCount
)
{
if
(!
$this
->
LanguageFound
(
$i
))
{
continue
;
}
$fields_hash
[
'l'
.
$i
.
'_CachedNavbar'
]
=
implode
(
'&|&'
,
$data
[
'titles'
][
$i
]);
$i
++;
}
$this
->
Conn
->
doUpdate
(
$fields_hash
,
TABLE_PREFIX
.
'Category'
,
'CategoryId = '
.
$data
[
'current_id'
]);
}
function
QueryTitle
(&
$data
)
{
$category_id
=
$data
[
'current_id'
];
$sql
=
'SELECT *
FROM '
.
TABLE_PREFIX
.
'Category
WHERE CategoryId = '
.
$category_id
;
$record
=
$this
->
Conn
->
GetRow
(
$sql
);
if
(
$record
)
{
$i
=
1
;
while
(
$i
<=
$this
->
languageCount
)
{
$data
[
'titles'
][
$i
][]
=
$record
[
'l'
.
$i
.
'_Name'
]
?
$record
[
'l'
.
$i
.
'_Name'
]
:
$record
[
'l'
.
$this
->
primaryLanguageId
.
'_Name'
];
$i
++;
}
$data
[
'debug_title'
]
=
$record
[
'l1_Name'
];
$data
[
'parent_path'
][]
=
$category_id
;
$data
[
'named_path'
][]
=
preg_replace
(
'/^Content
\\
//'
,
''
,
$record
[
'Filename'
]);
$data
[
'file_name'
]
=
$record
[
'Filename'
];
// it is one of the modules root category
/*$root_prefix = isset($this->root_prefixes[$category_id]) ? $this->root_prefixes[$category_id] : false;
if ($root_prefix) {
$fields_hash = Array();
if (!$record['Template']) {
$record['Template'] = $this->Application->ConfigValue($root_prefix.'_CategoryTemplate');
$fields_hash['Template'] = $record['Template'];
}
$this->Conn->doUpdate($fields_hash, TABLE_PREFIX.'Category', 'CategoryId = '.$category_id);
}*/
// if explicitly set, then use it; use parent template otherwise
if
(
$record
[
'Template'
]
&&
(
$record
[
'Template'
]
!=
CATEGORY_TEMPLATE_INHERIT
))
{
$data
[
'template'
]
=
$record
[
'Template'
];
}
}
}
function
QueryChildren
(&
$data
)
{
$sql
=
'SELECT CategoryId
FROM '
.
TABLE_PREFIX
.
'Category
WHERE ParentId = '
.
$data
[
'current_id'
];
$data
[
'children'
]
=
$this
->
Conn
->
GetCol
(
$sql
);
}
function
QueryPermissions
(&
$data
)
{
// don't search for section "view" permissions here :)
$sql
=
'SELECT ipc.PermissionConfigId, ip.GroupId, ip.PermissionValue
FROM '
.
TABLE_PREFIX
.
'Permissions AS ip
LEFT JOIN '
.
TABLE_PREFIX
.
'PermissionConfig AS ipc ON ipc.PermissionName = ip.Permission
WHERE (CatId = '
.
$data
[
'current_id'
].
') AND (Permission LIKE "%.VIEW") AND (ip.Type = 0)'
;
$records
=
$this
->
Conn
->
Query
(
$sql
);
//create permissions array only if we don't have it yet (set by parent)
if
(!
isset
(
$data
[
'perms'
]))
{
$data
[
'perms'
]
=
new
clsCachedPermissions
(
$data
[
'current_id'
],
$this
->
permCacheTable
);
}
foreach
(
$records
as
$record
)
{
if
(
$record
[
'PermissionValue'
]
==
1
)
{
$data
[
'perms'
]->
AddAllow
(
$record
[
'PermissionConfigId'
],
$record
[
'GroupId'
]);
}
else
{
$data
[
'perms'
]->
AddDeny
(
$record
[
'PermissionConfigId'
],
$record
[
'GroupId'
]);
}
}
}
/**
* Rebuild all cache in one step
*
*/
function
OneStepRun
(
$path
=
''
)
{
$this
->
InitUpdater
();
$needs_more
=
true
;
while
(
$needs_more
)
{
// until proceeeded in this step category count exceeds category per step limit
$needs_more
=
$this
->
DoTheJob
();
}
$this
->
SaveData
();
}
}
?>
Event Timeline
Log In to Comment