Skip to content

Instantly share code, notes, and snippets.

@garyconstable
Last active December 29, 2016 11:11
Show Gist options
  • Select an option

  • Save garyconstable/0610234468789ed2047d to your computer and use it in GitHub Desktop.

Select an option

Save garyconstable/0610234468789ed2047d to your computer and use it in GitHub Desktop.
Craft CMS Loop through categories and children from within a plugin
<?php
namespace Craft;
class TestPlugin extends BasePlugin
{
function getName()
{
return Craft::t('Test Plugin');
}
function getVersion()
{
return '1.0';
}
function getDeveloper()
{
return 'Gary Constable - Yello Studio';
}
function getDeveloperUrl()
{
return 'http://yellostudio.co.uk';
}
public function getSourceLanguage(){
return 'en';
}
}
<?php
namespace Craft;
class TestVariable
{
public function p($data = array() ){
echo '<pre>'.print_r($data, true).'</pre>';
}
public function d($data = array() ){
echo '<pre>'.print_r($data, true).'</pre>';die();
}
public function test(){
$this->p(' --- BEGIN HERE --- ');
//this returns an element criteria model
$o_criteria = craft()->elements->getCriteria(ElementType::Category);
//set the model params - level 1 order by level limit 20!
$o_criteria->group = 'catParent2';
$o_criteria->order = 'level';
$o_criteria->level = 1;
$o_criteria->limit = 20;
//check we have some matching categories
if( $o_criteria->getDescendants()->total() > 0 ){
//loop through
foreach ($o_criteria as $o_entry)
{
$this->p("Level 1: " . $o_entry->title);
//if we have some children, i.e the next level down
if( $o_entry->getDescendants()->total() > 0 ){
//get the current levels children
$o_children = $o_entry->getChildren();
//loop each child
foreach ($o_children as $d){
$this->p("&nbsp;&nbsp; Level 2: " . $d->title);
}
}
}
}
$this->d(' --- END HERE --- ');
}
}
<?php
namespace Craft;
class TestVariable
{
public function p($data = array() ){
echo '<pre>'.print_r($data, true).'</pre>';
}
public function d($data = array() ){
echo '<pre>'.print_r($data, true).'</pre>';die();
}
protected $preferencesBlocks = array(
'preference'
);
/**
* get the matrix block id's using the hardcoded preference block handle;
* @return type
*/
public function getPreferenceIds(){
$a_id = array();
$this->preferencesBlocks = $this->preferencesBlocks;
foreach( $this->preferencesBlocks as $x){
$q =
" select fields.id as main_id , types.id as block_type_id from craft_fields fields LEFT JOIN craft_matrixblocktypes types ON fields.id = types.fieldId
where lower(fields.type) = 'matrix' and lower(fields.handle) like '%%".$x."%%'
-- AND types.handle = 'contact' ";
$o_db_command = craft()->db->createCommand($q)->queryAll(true);
$a_id[ $x ] = $o_db_command;
}
return $a_id;
}
public function getPreferencesForMatrixBlock( $s_blockname = ''){
//the retunr array should contain the user preferences
$a_return_attributes = array();
//get the user model
$o_user_model = craft()->userSession->getUser();
//see a row exists - actually a user will have a row for each element type so for one user may have 10 rows - crap no?
if( $o_user_model->$s_blockname->count() ) {
//null the block
$block = null;
//itterate through each of the existing blocks
foreach( $o_user_model->$s_blockname->iterator as $o_current_block){
//get the attributes
$a_attributes = $o_current_block->getContent()->getAttributes();
//add to the return array
$a_return_attributes[] = $a_attributes;
}
}
return $a_return_attributes;
}
public function findPreferenceValueInBlock( $a_prefernces_block = array(), $s_findme = '' ){
foreach( $a_prefernces_block as $row ){
foreach( $row as $key => $value ){
if( $key == $s_findme){
return $value;
}
}
}
}
public function getCategories( $group = "" ){
//$this->d($group);
$ret = array();
//this returns an element criteria model
$o_criteria = craft()->elements->getCriteria(ElementType::Category);
//set the model params - level 1 order by level limit 20!
$o_criteria->groupId = str_replace('group:', '', $group);
$o_criteria->order = 'level';
$o_criteria->level = 1;
$o_criteria->limit = 20;
//check we have some matching categories
if( $o_criteria->getDescendants()->total() > 0 ){
//loop through
foreach ($o_criteria as $o_entry)
{
//$this->p("Level 1: " . $o_entry->title);
$ret[] = "Level 1: " . $o_entry->title;
//if we have some children, i.e the next level down
if( $o_entry->getDescendants()->total() > 0 ){
//get the current levels children
$o_children = $o_entry->getChildren();
//loop each child
foreach ($o_children as $d){
//$this->p("&nbsp;&nbsp; Level 2: " . $d->title);
$ret[] = "&nbsp;&nbsp; Level 2: " . $d->title;
}
}
}
}
return $ret;
}
/**
* Get the matrix block columns
* we end up with a multi dimen array that looks like the matrik blocks we setup, top level, 2nd level and then third level
* @param type $a_matrix_block_ids
* @return type
*/
public function getTableColumns( $a_matrix_block_ids = array() ){
//the return array
$a_block_colums = array();
//the current logged in user
$o_user_model = craft()->userSession->getUser();
foreach( $a_matrix_block_ids as $key => $value ){
//the block name i.e contactPreferences
$s_block_name = $key;
//get all of the user prefernces (rows in the table i.e. craft_matrixcontent_contactpreference) for the current block
$a_my_prefernce = $this->getPreferencesForMatrixBlock( $s_block_name );
//temp array to hold the current chunk of chunks!
$a_tmps = array();
foreach( $value as $x ){
//these are the cunks!
$a_tmp = array();
//craft_fields table id 158 = brochures, in the context table we want the matrix block type of 6
$i_matrix_block_id = $x['block_type_id'];
//get the model
$o_matrix_block_type_model = craft()->matrix->getBlockTypeById( $i_matrix_block_id );
//refernce this section by name
$s_section = $o_matrix_block_type_model->name;
//get the fields for the current model
$a_fields = $o_matrix_block_type_model->getFieldLayout()->getFields();
//loop through the fields and grab the required data to be return ed as the chunk in the array
foreach($a_fields as $o_field_layout_field_model) {
//the current field from the layour loop
$o_field = $o_field_layout_field_model->getField();
//create the array chunk
$a_tmp[] = array(
//block name
'blockname' => $s_block_name,
//parent
'matrixBlockId' => $x['main_id'], // 145 - contact preferences
//prefernce
'fieldId' => $x['block_type_id'], // craft_fields table id 158 = brochures, in the context table we want the matrix block type of 6
//others
'type' => $o_field->type,
'handle' => $o_field->handle,
'name' => $o_field->name,
'instructions' => $o_field->instructions,
'placeholder' => isset($o_field->settings['placeholder']) ? $o_field->settings['placeholder'] : null,
'options' => isset($o_field->settings['options']) ? $o_field->settings['options'] : null,
//the preference value
'preference' => $this->findPreferenceValueInBlock( $a_my_prefernce, $o_field->handle )
);
if($o_field->type == 'Categories'){
$cats = $this->getCategories( $o_field->settings['source'] );
$this->d($cats);
}
$this->p($o_field);
}
//add the chunks to the chunk!
$a_tmps[$s_section] = $a_tmp;
}
//add the chunk to the return array
$a_block_colums[$s_block_name] = $a_tmps;
}
//$this->pr( $a_block_colums, true );
return $a_block_colums;
}
/**
* In the front end design, some of the fields are grouped - such as telephone
* this function will lopp through and group matching names in to their own array part
* the front end then notices that there is not a type but and array and deals with it..
* @param type $a_table_columns
* @return type
*/
public function groupforGui( $a_table_columns = array() ){
$a_groups = array(
'telephone'
);
$a_grouped_columns = array();
/**
* contactPreference
* propertyPreference
* etc..
*/
foreach( $a_table_columns as $key => $x){
/**
* Contact
* Direct Mail
* etc..
*/
foreach( $x as $k => $y ){
$a_tmp = array();
$a_tmp_group = array();
/**
* telephoneDaytime
* telephoneEvening
* etc..
*/
foreach($y as $v ){
foreach( $a_groups as $s_current_group){
/**
* telephone - is part of a group so add it to its own array
*/
if( strstr( $v['handle'] , $s_current_group) ){
$a_tmp_group[$s_current_group][] = $v;
}else{
$a_tmp[] = $v;
}
}
}
if(!empty($a_tmp_group)){
if( count($a_tmp_group) > 1){
$a_tmp[] = $a_tmp_group;
}else{
$a_first_element = reset($a_tmp_group);
if( count($a_first_element) > 1){
$a_tmp[] = $a_tmp_group;
}else{
$a_tmp[] = $a_first_element[0];
}
}
}
/**
* add to the return array
*/
$a_grouped_columns[$key][$k] = $a_tmp;
}
}
return $a_grouped_columns;
}
/**
* this is a test case function -
* plug some numbers in and watch the prefernce change in the database
* handy for getting the correct matrix id's
*
* If run this will break the preference page
*/
public function testCase(){
$parent = 145;
$preference = 5;
$value = '07702795435';
$handle = 'sms';
$blockname = 'contactPreference';
craft()->log->removeRoute('WebLogRoute');
craft()->log->removeRoute('ProfileLogRoute');
//clean the values
if($value === true || $value === 'true' ){
$value = 1;
}
if($value === false || $value === 'false' ){
$value = 0;
}
//debug the posted vars
// $this->pr(array(
//
// 'parent' => $parent,
// 'preference' => $preference,
// 'value' => $value,
// 'handle' => $handle,
// 'blockname' => $blockname
//
// ), true);
//get the user model
$o_user_model = craft()->userSession->getUser();
//see a row exists - actually a user will have a row for each element type so for one user may have 10 rows - crap no?
if( $o_user_model->$blockname->count() ) {
//null the block
$block = null;
//itterate through each of the existing blocks
foreach( $o_user_model->$blockname->iterator as $o_current_block){
//get the attributes
$a_attributes = $o_current_block->getContent()->getAttributes();
//if the attrubute exists in the loop block , the global block become a matrix object
if( in_array($handle, array_keys($a_attributes)) ){
$block = $o_current_block;
}
}
//though we had blocks they were the wrong blocks - go figure!
if( is_null($block) ){
//create a new block wit the correct params
$block = new MatrixBlockModel();
$block->fieldId = intval($parent);
$block->ownerId = $o_user_model->id;
$block->typeId = intval($preference); // ID of block type
}
}
//the row did not exist so create a new row
else {
$block = new MatrixBlockModel();
$block->fieldId = intval($parent);
$block->ownerId = $o_user_model->id;
$block->typeId = intval($preference); // ID of block type
}
//now we have a block we can add the content
$block->getContent()->setAttributes(array(
(string)$handle => (string)$value
));
if( craft()->matrix->saveBlock( $block ) ) {
$a_errors = array();
echo json_encode(array(
'success' => 'ok',
'errors' => $a_errors,
'parent' => $parent,
'preference' => $preference,
'value' => $value,
'handle' => $handle,
'blockname' => $blockname,
));
die();
}
else {
$a_errors = $block->getErrors();
echo json_encode(array(
'success' => 'fail',
'errors' => $a_errors,
'parent' => $parent,
'preference' => $preference,
'value' => $value,
'handle' => $handle,
'blockname' => $blockname,
));
die();
}
}
/**
* This function is called within the template to create a preference structure using the methods above
* @return type
*/
public function test(){
$this->p(' --- BEGIN HERE --- ');
$return = array();
//get the block ids
$a_blockids = $this->getPreferenceIds();
//turn the block ids into columns that we can use in the front end
$a_table_columns = $this->getTableColumns($a_blockids);
//group the table columns so we can alter the front end gui
$a_grouped_table_columns = $this->groupforGui($a_table_columns);
//return the structure
$this->p($a_grouped_table_columns);
$this->d(' --- END HERE --- ');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment