As far as block creation goes, I thought of a way to create usermade blocks in php code. It's sort of an alternative to hook_block. We could use this to generate the blocks with the module, and then users could go in and modify their contents.

Here is an example of the function:


/**
 * @function create_usermade_block.  Generates blocks where the user can edit the contents.  Alternative to hook_block.
 * $block['title']..............The title of the block as shown to the user.
 * $block['body']...............The content of the block as shown to the user.
 * $block['info']...............A brief description of your block. Used on the block overview page.
 * $block['format'].............Input format. Should probably be PHP. (value = 2)
 **/
 
function create_usermade_block () {

$run_check = $variable_get('gjg_block_check', 1 );
 //we only want to run this code once to create the blocks. User can edit them later.
 if($run_check) {
   $block1 = array('title' => 'GJG BLOCK TITLE #1','body' => 'GJG BLOCK BODY #1','info' => 'GJG BLOCK INFO NAME #1', 'format' => '2');
   $block2 = array('title' => 'GJG BLOCK TITLE #2','body' => 'GJG BLOCK BODY #2','info' => 'GJG BLOCK INFO NAME #2', 'format' => '2');
   $block3 = array('title' => 'GJG BLOCK TITLE #3','body' => 'GJG BLOCK BODY #3','info' => 'GJG BLOCK INFO NAME #3', 'format' => '2');
   $block_array = array($block1, $block2, $block3);
     foreach($block_array as $block) {
       block_box_save($block);
     }
   variable_set('gjg_block_check', 0);
 }


}

Comments

webchick’s picture

Hm. Not sure about this one... I prefer to use the existing infrastructure (e.g. admin/blocks) if possible. Or am I misreading this?

About access control, I don't think there's anyway to hide a block in its entirety in 4.6 from certain roles without it being embedded in the module's hook_block itself. However, we could do something similar to what's listed here:

http://drupal.org/node/13266

and just add a message to the block that says something to the effect of "You must be logged in to view this."

zirafa’s picture

Ah, well this uses exactly the same callback function (block_box_save) that is used when a user creates a block through 'admin/block', so it's already using existing infrastructure. The only difference is I sent in the array directly instead of through a $_POST. It would just save the admin user time in configuration. Also I think the 4.6 access workaround you pointed out would be an adequate solution, I just don't know how ubiquitous these blocks are (i.e. would they be annoying?)

zirafa’s picture

Ok updated versions of the functions. The first is how you create the blocks and the second is how you retrieve them. I still don't know how we should handle a reset or anything. Currently the first function is setup in such a way that it will only run once. We could theoretically have a reset function which deletes all the GJG blocks and then clears the $run_check flag, then runs create_usermade_block again. Let me know what you guys think.

/**
 * function create_usermade_block. Generates blocks where the user can edit the contents. Alternative to hook_block.
 * $block['title']..............The title of the block as shown to the user.
 * $block['body']...............The content of the block as shown to the user.
 * $block['info']...............A brief description of your block. Used on the block overview page.
 * $block['format'].............Input format. Should probably be PHP. (value = 2)
 * For each block we create, we also save a variable in the database with the title of that block.
 * This variable will store the block id (bid) which we can use to print out this block later.
 **/
function create_usermade_block () {
$run_check = $variable_get('gjg_block_check', 1 );
 //we only want to run this code once to create the blocks. User can edit them later.
 if($run_check) {
   $block1 = array('title' => 'GJG BLOCK TITLE #1','body' => 'GJG BLOCK BODY #1','info' => 'GJG BLOCK INFO NAME #1', 'format' => '2');
   $block2 = array('title' => 'GJG BLOCK TITLE #2','body' => 'GJG BLOCK BODY #2','info' => 'GJG BLOCK INFO NAME #2', 'format' => '2');
   $block3 = array('title' => 'GJG BLOCK TITLE #3','body' => 'GJG BLOCK BODY #3','info' => 'GJG BLOCK INFO NAME #3', 'format' => '2');
   $block_array = array($block1, $block2, $block3);
   foreach($block_array as $block) {
     block_box_save($block);
     $box_id = db_result(db_query("SELECT * FROM {boxes} ORDER BY bid DESC LIMIT 1"));
     variable_set($block['title'], $box_id);  //remember the BID of this particular block to pull up later.
     }
   variable_set('gjg_block_check', 0);
 }
}

/**
 * This little function takes in the name of the GJG block you want to display and returns a simple array.
 * The input title is the title of the GJG block created using  create_usermade_block (i.e. GJG BLOCK TITLE #1).
 * The returning array $block contains:
 * $block['subject']..............................................................The subject or title of the block.
 * $block['content']..............................................................The body of the block.
 * 
 **/
function gjg_block_display($title) {
$bid = variable_get($title, 0);
$block = module_invoke('block', 'block', 'view', $bid);
return $block;
}

zirafa’s picture

Added a drupal_set_message to create_usermade_block. Usage of these functions would be to put them both in gjg.module, and then to call create_usermade_block by hook_settings. The second function would be called by the theme.

Now all we need is the actual list of blocks to generate using this thing...

/**
 * function create_usermade_block. Generates blocks where the user can edit the contents. Alternative to hook_block.
 * $block['title']..............The title of the block as shown to the user.
 * $block['body']...............The content of the block as shown to the user.
 * $block['info']...............A brief description of your block. Used on the block overview page.
 * $block['format'].............Input format. Should probably be PHP. (value = 2)
 * For each block we create, we also save a variable in the database with the title of that block.
 * This variable will store the block id (bid) which we can use to print out this block later.
 **/
function create_usermade_block () {
$run_check = $variable_get('gjg_block_check', 1 );
 //we only want to run this code once to create the blocks. User can edit them later.
 if($run_check) {
   $block1 = array('title' => 'GJG BLOCK TITLE #1','body' => 'GJG BLOCK BODY #1','info' => 'GJG BLOCK INFO NAME #1', 'format' => '2');
   $block2 = array('title' => 'GJG BLOCK TITLE #2','body' => 'GJG BLOCK BODY #2','info' => 'GJG BLOCK INFO NAME #2', 'format' => '2');
   $block3 = array('title' => 'GJG BLOCK TITLE #3','body' => 'GJG BLOCK BODY #3','info' => 'GJG BLOCK INFO NAME #3', 'format' => '2');
   $block_array = array($block1, $block2, $block3);
   foreach($block_array as $block) {
     block_box_save($block);
     $box_id = db_result(db_query("SELECT * FROM {boxes} ORDER BY bid DESC LIMIT 1"));
     variable_set($block['title'], $box_id); //remember the BID of this particular block to pull up later.
     }
   variable_set('gjg_block_check', 0);
   drupal_set_message("The GoJoinGo blocks have been created. They will only be created once. You can edit their contents in administer >> blocks.");
 }
}

<?php
/**
 * This little function takes in the name of the GJG block you want to display and returns a simple array.
 * The input title is the title of the GJG block created using create_usermade_block (i.e. GJG BLOCK TITLE #1).
 * The returning array $block contains:
 * $block['subject']..............................................................The subject or title of the block.
 * $block['content']..............................................................The body of the block.
 *
 **/
function gjg_block_display($title) {
$bid = variable_get($title, 0);
$block = module_invoke('block', 'block', 'view', $bid);
return $block;
}

?>

zirafa’s picture

Are these the only blocks that need to be generated?

  • Group profile block
  • Personal content block
  • Group details
  • User block
webchick’s picture

Yep, those are them, plus one more:

"Recommendations"

This is just a simple hand-done block, containing the following:

<?php
	global $user;
	  $items = array(l(t('Groups in your Area'), 'gsearch/og'), 
            l(t('Events in your area'), 'gsearch/gjg_event'),
	    l(t('People in your area'), 'gsearch/user'),
 	    l(t('Popular Groups'), 'og/popular'),
	    l(t('New Groups'), 'og/new'));
	    return theme('gjg_menu',$items);
?>
zirafa’s picture

ok these are up and working, with a reset function. all that's needed now is to integrate into gjg.module and delete the hook_block style ones (but keep the user_block one and load the code from here).

/**
 * function gjg_create_usermade_blocks. Generates blocks where the user can edit the contents. Alternative to hook_block.
 * $block['title']..............The title of the block as shown to the user.
 * $block['body']...............The content of the block as shown to the user.
 * $block['info']...............A brief description of your block. Used on the block overview page.
 * $block['format'].............Input format. Should probably be PHP. (value = 2)
 * For each block we create, we also save a variable in the database with the title of that block.
 * This variable will store the block id (bid) which we can use to print out this block later.
 **/
function gjg_create_usermade_blocks() {
$run_check = variable_get('gjg_block_check', 1 );
 //we only want to run this code once to create the blocks. User can edit them later.
 if($run_check) {
   $block1 = array('title' => 'Group profile','body' => gjg_block_snippets('group_profile'),'info' => 'GJG: Group profile', 'format' => '2');
   $block2 = array('title' => 'Group actions','body' => gjg_block_snippets('group_actions'),'info' => 'GJG: Group actions', 'format' => '2');
   $block3 = array('title' => 'My friends','body' => gjg_block_snippets('my_friends'),'info' => 'GJG: My friends', 'format' => '2');
   $block4 = array('title' => 'Recommendations','body' => gjg_block_snippets('recommendations'),'info' => 'GJG: Recommendations', 'format' => '2');
   $block5 = array('title' => 'User block *CODE ONLY*','body' => gjg_block_snippets('user_block'),'info' => 'GJG: User block *CODE ONLY*', 'format' => '2');
   $block6 = array('title' => 'Personal content','body' => gjg_block_snippets('personal_content'),'info' => 'GJG: Personal content', 'format' => '2');
   $block_array = array($block1, $block2, $block3, $block4, $block5, $block6);
   foreach($block_array as $block) {
     block_box_save($block);
     $box_id = db_result(db_query("SELECT * FROM {boxes} ORDER BY bid DESC LIMIT 1"));
     variable_set($block['info'], $box_id); //remember the BID of this particular block to pull up later.
     }
   variable_set('gjg_block_check', 0);
   drupal_set_message("The GoJoinGo blocks have been created.  They will only be created once, unless you decide to reset them.  You can edit their contents in administer >> blocks.");
 }
}


function gjg_block_snippets($block_name) {
  switch($block_name) {
   	case 'group_profile':
	  $code_block = '
	      <?php
	      global $user;
		  if ($gid = $_SESSION[\'og_last\']->nid) {
		    $node = node_load(array(\'nid\' => $gid));
		    $result = db_query(og_list_users_sql(0), $node->nid);
		    $cntall = db_num_rows($result);
			if (!empty($node->files) && is_array($node->files)) {
		      foreach ($node->files as $file) {
			    if ($file->filename == \'thumbnail\') {
				  $node->og_picture = file_create_path($file->filepath);
				}
		      }
		    }
			$picture = theme(\'image\', $node->og_picture);
			$default = theme(\'image\', \'files/images/user_image_not_found.png\');
			$content = $picture ? $picture : $default;
			$content .= \'<div class="group-group">\';
			$content .= \'<div class="group-title">\'. t(\'Description\') .\'</div>\';
			$content .= \'<div class="group-item">\'. check_plain($node->og_description) .\'</div>\';
			$content .= \'</div>\';
			$content .= \'<div class="group-group">\';
			$content .= \'<div class="group-title">\'. t(\'Organizer\') .\'</div>\';
			$content .= \'<div class="group-item">\'. check_plain($node->firstname .\' \'. $group->lastname) .\'</div>\';
			$content .= \'</div>\';
			$content .= \'<div class="group-group">\';
			$content .= \'<div class="group-title">\'. t(\'Location\') .\'</div>\';
			$content .= \'<div class="group-item">\'. check_plain($node->address) .\'</div>\';
			$content .= \'</div>\';
			$content .= \'<div class="group-group">\';
			$content .= \'<div class="group-title">\'. t(\'Members\') .\'</div>\';
			$content .= \'<div class="group-item">\'. format_plural($cntall-$cntpending, \'1 member\', \'%count members\') .\'</div>\';
			$content .= \'</div>\';    
			print $content;
		  }
          

'; //end of the code_block;
return $code_block; //return the above php snippet.

case 'group_actions':
$code_block = '

		  global $user;
		
		  if ($gid = $_SESSION[\'og_last\']->nid) {
			$node = node_load(array(\'nid\' => $gid));
			$result = db_query(og_list_users_sql(0), $node->nid);
			$cntall = db_num_rows($result);
			$cntpending = 0;
			while ($row = db_fetch_object($result)) {
			  if ($row->grant_view == 0) {
				$cntpending++;
			  }
			  if ($row->uid == $user->uid) {
				if ($row->grant_view) {
				  $subscription = \'active\';
				}
				else {
				  $subscription = \'requested\';
				}
			  }
			}
			$links = array();
			if ($subscription == \'active\') {
			  $links = og_create_links($node);
			  $links[] = l(t(\'my subscription\'), "og/manage/$node->nid");
			  if ($node->og_selective == OG_OPEN || db_result(db_query("SELECT grant_update FROM {node_access} WHERE realm = \'og_uid\' AND gid = %d AND nid = %d", $user->uid, $node->nid))) {
				$links[] = l(t(\'invite friend\'), \'og/invite/\'. $node->nid, array(), drupal_get_destination());
			  }
			}
			elseif ($subscription == \'requested\') {
			  $links[] = t(\'Your subscription request awaits approval.\');
			  $links[] = l(t(\'delete request\'), "og/unsubscribe/$node->nid", array(), \'destination=og\');
			}
			elseif ($user->uid && $node->og_selective < OG_INVITE_ONLY) {
			  if ($node->og_selective == OG_MODERATED) {
				$txt = t(\'request subscription\');
			  }
			  elseif ($node->og_selective == OG_OPEN) {
				$txt = t(\'subscribe\');
			  }
			  $links[] = l($txt, "og/subscribe/$node->nid", array(), "destination=node/$node->nid");
			}
			$content .= theme(\'item_list\', $links);
		
			print $content;
		  }
		

';
return $code_block; //return the above php snippet
case 'my_friends':
$code_block = '

	      // Show My Friends block only for authenticated users
          if (!$uid = $user->uid) {
            return;
          }
          $result = db_query_range("
            SELECT u.uid
            FROM {gjg_user_user} f
            INNER JOIN {users} u ON ((f.uid1 = %d AND u.uid = f.uid2) OR (f.uid2 = %d AND u.uid = f.uid1))
            WHERE f.status = \'f\'
            ORDER BY f.status DESC, u.name", $uid, $uid, 0, 4);
          $accounts = array();
          while ($account = db_fetch_object($result)) {
            $accounts[] = user_load(array(\'uid\' => $account->uid));
          }
          $block[\'subject\'] = t(\'My friends\');

          // Check if friends exist
          if (count($accounts) > 0) {
            $block[\'content\'] = theme(\'list_users\', $accounts);
          }
          else {
            $block[\'content\'] = t(\'You do not have any friends yet.\');
          }
          print $block;
          

'; //end php snippet
return $code_block; //return the above php snippet
case 'personal_content':
$code_block = '

			<div class="menu">
			<ul>
			<li><a href="?q=my/groups">My Groups</a></li>
			<li><a href="?q=my/events">My Events</a></li>
			<li><a href="?q=my/friends">My Friends</a></li>
			<li><a href="?q=my/bookmarks">My Bookmarks</a></li>
			<li><a href="?q=tracker/\'. $GLOBALS[\'user\']->uid .\'">My Posts</a></li>
			<li><a href="?q=my/stats">My Stats</a></li>
			</ul>
			</div>
		

'; //end of php snippet
return $code_block; //return above snippet
case 'user_block':
$code_block = '

			  global $user;
			  $account = $user;
			  $unread = (int)_privatemsg_get_new_messages($user->uid);   
			  // Hide for anonymous users
				if (!$user->uid) {
					return;
				}
				  $picture = theme(\'user_picture\', $account);
				  $default = theme(\'image\', \'files/images/user_image_not_found.png\');
				  $content .= $picture ? $picture : l($default, "user/$account->uid/edit/personal", array(), NULL, NULL, FALSE, TRUE);
				  $title = t(\'My Inbox\');
				  $items = array(
					l(t(\'View Messages\'), \'privatemsg\') . \'<div class="count">[\'. $unread .\']</div>\',
					l(t(\'Invite a Friend\'), \'create/invite\')
				  );
				 $content .= theme(\'user_block_item_group\', $title, $items);
				 $title = t(\'My Account\');
				 $items = array(
				   l(t(\'View Profile\'), "user/$account->uid"),
				   l(t(\'Update Account\'), "user/$account->uid/edit"),
				   l(t(\'Log out\'), \'logout\')
				 );
				 $content .= theme(\'user_block_item_group\', $title, $items);
				 print $content;
		   

'; //end of php snippet
return $code_block; //return above php snippet
case 'recommendations':
$code_block = '

			  global $user;
				$items = array(l(t(\'Groups in your Area\'), \'gsearch/og\'),
							   l(t(\'Events in your area\'), \'gsearch/gjg_event\'),
							   l(t(\'People in your area\'), \'gsearch/user\'),
							   l(t(\'Popular Groups\'), \'og/popular\'),
							   l(t(\'New Groups\'), \'og/new\'));
			   $output = theme(\'gjg_menu\',$items);
			   print $output;
		   

'; //end of php snippet
return $code_block; //return the above code snippet
}

}

function gjg_reset_blocks() {
$run_check = variable_get('gjg_block_check', 0 );
if(!$run_check){
$blocks = array('GJG: Group profile','GJG: Group actions','GJG: My friends','GJG: Recommendations','GJG: User block *CODE ONLY*','GJG: Personal content');
//delete the current blocks
foreach($blocks as $block_info) {
$bid = variable_get($block_info, 0);
if($bid) {
$box = block_box_get($bid);
$info = $box['info'] ? $box['info'] : $box['title'];
db_query('DELETE FROM {boxes} WHERE bid = %d', $bid);
}
}
cache_clear_all();
//recreate the default blocks
variable_set('gjg_block_check', 1 );
gjg_create_usermade_blocks();
drupal_set_message(t('The previous GJG blocks have successfully been deleted and re-created.'));
}

}

?>

zirafa’s picture

StatusFileSize
new9.84 KB

Patch to replace GJG blocks with user_editable blocks.

gjg_settings() will install the blocks only once if not installed. the reset checkbox on the settings page will overwrite the previous blocks with new ones.

hook_block is still used to create 'GJG: User block' although it's contents can be edited in GJG: User block *CODE ONLY*.

It is up and running on the dev site. The only thing left is to modify block.tpl.php and coordinate with trae to get these blocks themed properly, which will probably happen tomorrow (today?) morning.

Farsheed

zirafa’s picture

StatusFileSize
new11.2 KB

This file needs to be added to the path gjg/block_generation.inc. Don't know if the patch contained this.

zirafa’s picture

additionally, group_block.module is no longer used.

webchick’s picture

Priority: Normal » Critical

Upgrading this to 'critical', however I'm going to wait until very near the end to integrate this since the block spec is still in flux.