Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
D
drupal
Manage
Activity
Members
Labels
Plan
Wiki
Custom issue tracker
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Model registry
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
project
drupal
Commits
7eeb51c6
Commit
7eeb51c6
authored
14 years ago
by
Angie Byron
Browse files
Options
Downloads
Patches
Plain Diff
#556842
by mh86, bangpound, Francewhoa, catch: Fixed taxonomy_get_tree() memory issues.
parent
5ffb666f
No related branches found
No related tags found
2 merge requests
!7452
Issue #1797438. HTML5 validation is preventing form submit and not fully...
,
!789
Issue #3210310: Adjust Database API to remove deprecated Drupal 9 code in Drupal 10
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
modules/taxonomy/taxonomy.module
+78
-26
78 additions, 26 deletions
modules/taxonomy/taxonomy.module
with
78 additions
and
26 deletions
modules/taxonomy/taxonomy.module
+
78
−
26
View file @
7eeb51c6
...
@@ -841,21 +841,23 @@ function taxonomy_get_children($tid, $vid = 0) {
...
@@ -841,21 +841,23 @@ function taxonomy_get_children($tid, $vid = 0) {
* for the entire vocabulary.
* for the entire vocabulary.
* @param $max_depth
* @param $max_depth
* The number of levels of the tree to return. Leave NULL to return all levels.
* The number of levels of the tree to return. Leave NULL to return all levels.
* @param $depth
* @param $load_entities
* Internal use only.
* If TRUE, a full entity load will occur on the term objects. Otherwise they
* are partial objects queried directly from the {taxonomy_term_data} table to
* save execution time and memory consumption when listing large numbers of
* terms. Defaults to FALSE.
*
*
* @return
* @return
* An array of all term objects in the tree. Each term object is extended
* An array of all term objects in the tree. Each term object is extended
* to have "depth" and "parents" attributes in addition to its normal ones.
* to have "depth" and "parents" attributes in addition to its normal ones.
* Results are statically cached.
* Results are statically cached. Term objects will be partial or complete
* depending on the $load_entities parameter.
*/
*/
function
taxonomy_get_tree
(
$vid
,
$parent
=
0
,
$max_depth
=
NULL
,
$
depth
=
-
1
)
{
function
taxonomy_get_tree
(
$vid
,
$parent
=
0
,
$max_depth
=
NULL
,
$
load_entities
=
FALSE
)
{
$children
=
&
drupal_static
(
__FUNCTION__
,
array
());
$children
=
&
drupal_static
(
__FUNCTION__
,
array
());
$parents
=
&
drupal_static
(
__FUNCTION__
.
':parents'
,
array
());
$parents
=
&
drupal_static
(
__FUNCTION__
.
':parents'
,
array
());
$terms
=
&
drupal_static
(
__FUNCTION__
.
':terms'
,
array
());
$terms
=
&
drupal_static
(
__FUNCTION__
.
':terms'
,
array
());
$depth
++
;
// We cache trees, so it's not CPU-intensive to call get_tree() on a term
// We cache trees, so it's not CPU-intensive to call get_tree() on a term
// and its children, too.
// and its children, too.
if
(
!
isset
(
$children
[
$vid
]))
{
if
(
!
isset
(
$children
[
$vid
]))
{
...
@@ -865,31 +867,81 @@ function taxonomy_get_tree($vid, $parent = 0, $max_depth = NULL, $depth = -1) {
...
@@ -865,31 +867,81 @@ function taxonomy_get_tree($vid, $parent = 0, $max_depth = NULL, $depth = -1) {
$query
=
db_select
(
'taxonomy_term_data'
,
't'
);
$query
=
db_select
(
'taxonomy_term_data'
,
't'
);
$query
->
join
(
'taxonomy_term_hierarchy'
,
'h'
,
'h.tid = t.tid'
);
$query
->
join
(
'taxonomy_term_hierarchy'
,
'h'
,
'h.tid = t.tid'
);
$query
->
addField
(
't'
,
'tid'
);
$result
=
$query
$query
->
addField
(
'h'
,
'parent'
);
->
addTag
(
'translatable'
)
$query
->
condition
(
't.vid'
,
$vid
);
->
addTag
(
'term_access'
)
$query
->
addTag
(
'term_access'
);
->
fields
(
't'
)
$query
->
orderBy
(
't.weight'
);
->
fields
(
'h'
,
array
(
'parent'
))
$query
->
orderBy
(
't.name'
);
->
condition
(
't.vid'
,
$vid
)
$tid_parents
=
$query
->
execute
()
->
fetchAllKeyed
();
->
orderBy
(
't.weight'
)
$terms
[
$vid
]
=
taxonomy_term_load_multiple
(
array_keys
(
$tid_parents
));
->
orderBy
(
't.name'
)
->
execute
();
foreach
(
$tid_parents
as
$tid
=>
$parent_tid
)
{
$children
[
$vid
][
$parent_tid
][]
=
$tid
;
foreach
(
$result
as
$term
)
{
$parents
[
$vid
][
$tid
][]
=
$parent_tid
;
$children
[
$vid
][
$term
->
parent
][]
=
$term
->
tid
;
$parents
[
$vid
][
$term
->
tid
][]
=
$term
->
parent
;
$terms
[
$vid
][
$term
->
tid
]
=
$term
;
}
}
}
}
// Load full entities, if necessary. The entity controller statically
// caches the results.
if
(
$load_entities
)
{
$term_entities
=
taxonomy_term_load_multiple
(
array_keys
(
$terms
[
$vid
]));
}
$max_depth
=
(
!
isset
(
$max_depth
))
?
count
(
$children
[
$vid
])
:
$max_depth
;
$max_depth
=
(
!
isset
(
$max_depth
))
?
count
(
$children
[
$vid
])
:
$max_depth
;
$tree
=
array
();
$tree
=
array
();
if
(
$max_depth
>
$depth
&&
!
empty
(
$children
[
$vid
][
$parent
]))
{
foreach
(
$children
[
$vid
][
$parent
]
as
$child
)
{
// Keeps track of the parents we have to process, the last entry is used
$term
=
clone
$terms
[
$vid
][
$child
];
// for the next processing step.
$term
->
depth
=
$depth
;
$process_parents
=
array
();
$term
->
parents
=
$parents
[
$vid
][
$child
];
$process_parents
[]
=
$parent
;
$tree
[]
=
$term
;
if
(
!
empty
(
$children
[
$vid
][
$child
]))
{
// Loops over the parent terms and adds its children to the tree array.
$tree
=
array_merge
(
$tree
,
taxonomy_get_tree
(
$vid
,
$child
,
$max_depth
,
$depth
));
// Uses a loop instead of a recursion, because it's more efficient.
while
(
count
(
$process_parents
))
{
$parent
=
array_pop
(
$process_parents
);
// The number of parents determines the current depth.
$depth
=
count
(
$process_parents
);
if
(
$max_depth
>
$depth
&&
!
empty
(
$children
[
$vid
][
$parent
]))
{
$has_children
=
FALSE
;
$child
=
current
(
$children
[
$vid
][
$parent
]);
do
{
if
(
empty
(
$child
))
{
break
;
}
$term
=
$load_entities
?
$term_entities
[
$child
]
:
$terms
[
$vid
][
$child
];
if
(
count
(
$parents
[
$vid
][
$term
->
tid
])
>
1
)
{
// We have a term with multi parents here. Clone the term,
// so that the depth attribute remains correct.
$term
=
clone
$term
;
}
$term
->
depth
=
$depth
;
unset
(
$term
->
parent
);
$term
->
parents
=
$parents
[
$vid
][
$term
->
tid
];
$tree
[]
=
$term
;
if
(
!
empty
(
$children
[
$vid
][
$term
->
tid
]))
{
$has_children
=
TRUE
;
// We have to continue with this parent later.
$process_parents
[]
=
$parent
;
// Use the current term as parent for the next iteration.
$process_parents
[]
=
$term
->
tid
;
// Reset pointers for child lists because we step in there more often
// with multi parents.
reset
(
$children
[
$vid
][
$term
->
tid
]);
// Move pointer so that we get the correct term the next time.
next
(
$children
[
$vid
][
$parent
]);
break
;
}
}
while
(
$child
=
next
(
$children
[
$vid
][
$parent
]));
if
(
!
$has_children
)
{
// We processed all terms in this hierarchy-level, reset pointer
// so that this function works the next time it gets called.
reset
(
$children
[
$vid
][
$parent
]);
}
}
}
}
}
}
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment