Archive for PHP

User Proof Repeater Images

So lets talk about proper image implementation.

We sometimes run into clients who would like slideshow galleries while uploading 2000-5000px wide images. And it’s important to understand that content managers are not going to KNOW what a proper image size is. So how do you maintain a nice easy consistent image query AND meet your client where they currently stand on knowledge of the web?

The set up for this image query is as follows:

I’ve seen a lot of queries that look like this.

<img src="<?= the_sub_field('image'); ?>" />

You would then set the height and the image in CSS

But lets challenge that. Does that offer the best quality for the end user? Those obviously allow for large images to be loaded and slow down your site, right?

Lets use a different query that will allow for faster loading.

<? $image = get_sub_field('image'); $image = wp_get_attachment_image($image, 'medium'); ?>
   <?php echo $image; print_r($image); ?>

So this should be the proper way to load fast images. You can change the size to whatever size you need.

This way when your site owners decide to load a large sized image, it won’t ruin your design or your load speed.

How Do I Make a Drupal “repeater field” with Field Collections (D7)

Up until now I’ve been mainly working in WordPress, mainly because of my love for ACF and their abilities to have repeating groups of fields. And I finally found a resource that helped me achieve the same user content manageability using Drupal. First off, you’ll need to install the Entity and the Field Collection modules by downlowding the files from the above links and putting the folders in the /sites/all/modules folder. After that dont forget to active them both in the admin at site.com/admin/modules

So now we can start setting ourselves up.

<?php
/**
* This function takes a field collection field and returns an object array that contains all of the field
* collection entity's fields. You can then use it the same way you would a node object. For example:
* $loaded_field_collection =  load_collection($node->your_field_collection);
* print 'check this ' . $loaded_field_collection->your_collected_field['und'][0]['value'] . ' value, sucka!';
*/
function load_collection($entity_uri) {
  $loaded_field_collection = entity_load('field_collection_item', array(0 => $entity_uri));
  foreach ($loaded_field_collection as $loaded_field_collection_object ) {
    return $loaded_field_collection_object;
  }
}
?>

And clear the cache at site.com/admin/config/development/performance
In fact, i just wrote a blog about how many times clearing the cache ended up being my problem.
So now you are ready to tackle the node.tpl.php file.  This works for other any of the other template files too, like node–news.tpl.php

<?php
/**
*
* For this example my content type was configured like this:
*
*  node
*   - top_level_collection
*     - second_level_collection
*        - text_1
*        - image_1
*        - third_level_collection
*         - text_2
*         - image_2
*     - second_level_collection_2
*        - text_3
*        - list_1
*        - image_3
*/
 
// check if field collection is not empty. If content exists, do some stuff.
if (!empty($node->top_level_collection['und'])) {
  //Your custom wrapper goes here
  print '<div class="collectin-it">';
 
  foreach ($node->top_level_collection['und'] as $a_top_level_collection) {
    //Use the load_collection() function to load your top level field collection's entity into an object.
    $top_level = load_collection($a_top_level_collection['value']);
    //You can use Devel's dsm() to view this object in the Devel tab of your node. Comment out or delete when everything's working well.
    dsm($top_level);
 
    //if your top_level_collection contains any fields, you can print them here using the $top_level object. Example: print $top_level->your_field['und'][0]['value'];
 
    //Use the load_collection() function to load your second level field collection entity object from the field in the top level field collection's entity object. All notes from the preceeding level apply.
    foreach ($top_level->second_level_collection['und'] as $a_second_level_collection) {
      $second_level = load_collection($a_second_level_collection['value']);
      dsm($second_level);
      foreach ($second_level->text_1['und'] as $a_text_1) {
        print '<p>' . $a_text_1['safe_value'] . '</p>';
      }
      foreach ($second_level->image_1['und'] as $a_image_1) {
        $var = array(
          'item' => $a_image_1,
          'image_style' => 'large',
          'path' => ''
        );
        print theme_image_formatter($var);
      }
 
      //Just like above, you can load the next level from the field in this level's field collection entity object.
      foreach ($second_level->third_level_collection['und'] as $a_third_level_collection) {
        $third_level = load_collection($a_third_level_collection['value']);
        dsm($third_level);
        foreach ($third_level->text_2['und'] as $a_text_2) {
          print '<p>' . $a_text_2['safe_value'] . '</p>';
        }
        foreach ($third_level->image_2['und'] as $a_image_2) {
          $var = array(
            'item' => $a_image_2,
            'image_style' => 'medium',
            'path' => ''
          );
          print theme_image_formatter($var);
        }
      }
    }
    //and finally, for the above mentioned case, you can go back to the $top_level object and load that second level field collection #2.
    foreach ($top_level->second_level_collection_2['und'] as $a_second_level_collection_2) {
      $second_level_2 = load_collection($a_second_level_collection_2['value']);
      dsm($second_level_2);
      foreach ($second_level_2->text_3['und'] as $a_text_3) {
        print '<p>' . $a_text_3['safe_value'] . '</p>';
      }
      foreach ($second_level_2->check_1['und'] as $a_check_1) {
        print '<p>Checklist value is: ' . $a_check_1['value'] . '</p>';
      }
      foreach ($second_level_2->image_3['und'] as $a_image_3) {
        $var = array(
          'item' => $a_image_2,
          'image_style' => 'thumbnail',
          'path' => ''
        );
        print theme_image_formatter($var);
      }
    }
  }
  //close your custom wrapper.
  print '</div>' . "\n";
}
?>

And that’s all you do! Thank you Rob W for all your contributions to Drupal and teaching me the ways of the Field Collections
Source

WordPress Stylesheet Missing in Safari

This is an interesting situation. You might have migrated your blog lately or your hosting provider moved your database somewhere and all the sudden your WordPress blog is no longer showing up in Safari. It may work fine in Chrome and Firefox, but is irritatingly missing from Safari. A check in the code reveals that your stylesheet URL has an extra space added before the relative part of the link. For some reason, this space doesn’t seem to bother the other browsers, but only Safari.

The fix is even more simple than the diagnosis. In order to fix it, you will need to get into the database and change one of the lines of the wordpress options table, where the site URL is given. In my case, there was a hidden return character, but it could have just as easily been a space after the URL. Once this space is removed, you should be well on your way to a working stylesheet, if not already there.

If you don’t have access to the database or you would rather make a more simple fix, edit the wp-header page and instead of the bloginfo() function, type in the direct link (relative link is preferred here) to the stylesheet.

Limit Character Count in ACF Repeater Text Field

Limiting the characters in a given field is a good way to dummyproof your admin dashboard so content writers don’t write novel length entries for a field that should only be a few words. This could have consequences such as ruining the integrity of the design and brand the company wishes to achieve. So limiting the length of the content they can write is a good way to make sure things like that don’t happen.

However, this is not a feature supported by the ACF plugin at the moment. So there is a work around that can get the desired effect until they do. Just put this code in your functions.php file:

<?php function my_head_input() { ?>
<script type="text/javascript">
jQuery(function(){
    jQuery('.repeater textarea').css("min-height","5px");
    jQuery('.repeater textarea').on('keyup', function(){
    var characters = 30;
    if( jQuery(this).val().length > characters ){
      jQuery(this).val(jQuery(this).val().substr(0, characters));
      return false;
    }
  });
});
</script>
<?php }
add_action('acf/input/admin_head' , 'my_head_input' );
?>

this solution was tailored to the textarea fields of all repeater fields. You can play with the jQuery selector to affect the fields you desire
Source

Can’t Update in WordPress – Missing Archive File

Working on a lot of WordPress sites, I’ve never encountered this till this point. The first clue was that I couldn’t just install plugins from the plugin library, i had to install them manually. However, updating had the same problem. Noted, this was the first wordpress site we had installed on a windows server, so that probably messed with how plugins in WordPress work. Anyways, manually doing things is a bit time consuming so I looked into the error…

(-4) : Missing archive file ‘C:\Windows\TEMP/formidable-1.tmp’

The solution turned out to be pretty simple

  1. You need to ftp your server. Inside the wp content folder, create a new directory/folder called TEMP.
  2. open the wp-config.php in the root directory and enter the following code at the bottom (remember the semicolon ^_^)
define('WP_TEMP_DIR', ABSPATH . 'wp-content/TEMP');

That’s it! You can install and update plugins with no problems
[Source]

Events Lists in WordPress.

So you want to make an events list in WordPress? There is a lot to do! First off lets define how this should work. Since I’m writing this blog I’ll tell you how mine works and then you decide if it’s how you want YOURS to work.

  1. It’s going to be a dynamic list.
  2. It’s going to pull events from an Event content type.
  3. It’s going to order them by date, newest on top.
  4. It’s going to display all the info for other people.

Ok so what do we need to set this up?

First find a way to create content types. I use the Custom Post Type UI plugin. This is a very good easy to use plugin that will do all that you need it to do.

Secondly, we need to be able to add specific fields into the post type. I strongly recommend using Advanced Custom Fields plugin. The main reason for this is that you are going to want to Repeater Fields and inside those store all your info, including a “date” input type.

Ok so create your custom field types inside your posts. Set a date as an Advanced Custom Field and remember where you put it.

Once you have a good list in the database it’s as simple as Querying.

 

<? if ( get_query_var('events') ) $paged = get_query_var('events');
$query = new WP_Query( array( 'post_type' => 'Events', 'paged' => $paged, 'orderby' => 'meta_value','meta_key' => 'date', 'order' => 'ASC', 'posts_per_page' => -1 ) );
$now = date("Ymd");
?>

Ok so you will notice a few things about this code.

  1. I use an orderby metavalue command.
    This is so that we can order by date. Advanced Custom Fields will have all it’s fields available as metadata so you can orderby          different things. In our case it’s a date.
  2.  I created a “date” variable called “now”.
    This is so I can filter out events that already happened from appearing to the user. It’s incredibly important to have the format be YMD so that you can do straight data comparisons.

So now that we have the query set up we are all but ready to start incorporating it into our theme. All we need to know is what to print from what is being queried.

 

<?php while ( $query->have_posts() ) : $query->the_post(); ?>
 
<? $date = DateTime::createFromFormat('Ymd', get_field('date')); ?>
<? if($now > $date->format("Ymd")) {  }else{ ?>

Ok so now you notice how we make the custom field “date” into an object named date and we check to see if “now” is greater than “date” who is also formatted as YMD.

This is going to call all events that are happening anytime farther that right at this very millisecond.

After this build your content any way you wish and watch the magic happen!

How to Write a Recursive Function with PHP

For the uninitiated, the recursive function can be a mind-bender. The concept, however, is not as difficult as it may seem at first glance. The difficulty of a recursive function is that it must have a definite way to exit the loop. Otherwise, you will have an eternal loop.

function loop_infinitely() {
 loop_infinitely();
}
loop_infinitely();

This function will never exit, because the function is called within itself. Common means of exiting a recursive function include a counter, looping over an object or array of items, or a timer.

Hierarchy is a good example of a more complex form of recursion. If you are building a hierarchy tree and need it to be dynamic to account for different numbers and levels of users, you will need to either write nested loops to an insane depth, or write a recursive function. The latter is preferable.

To start, write the function that encapsulates the actions needing to be done on each level. For example

<?
function write_a_list() {
// Any output will very probably go outside the conditional, since it is being executed 
// after having called the function from within the function. If necessary, you can pass 
// a variable from within the function back to the function to check for grandchildren of 
// the parent elements. 
  echo "<li>This is the list for the current row.</li>";
}
 
function on_this_level() {
 // This is where the action happens. 
 if(levels_below()) {
  // Call this function as long as there are still levels to go. The function is not 
  // written here, but it would check whatever conditions would be true of your result 
  // which would specify a child element. In this case, the levels_below() would need to 
  // contain the conditions which would prevent an infinite loop. 
 
  // Start a list, because the elements below must go inside of it.
  echo "<ul>"; 
  write_a_list();
  on_this_level(); 
 } 
 else { 
   // end the list when there are no more levels below to traverse. 
  echo "</ul>"; 
 } 
} 
// The function just needs to be called once outside the function so that it triggers. 
// I have chosen to loop over a list to show a little bit of added complexity. 
foreach ($items as $item) { 
  on_this_level(); 
} 
?>

And that is how you write a recursive function.

Flexible ajax using jQuery

We recently had to send a delete request to a javascript confirm.

We were using bootstrap so instead of the standard confirm(); command we wanted to display our own module.

We also wanted a universal command that would execute any of the actions that are forwarded by the buttons.

So with all things, you guys get the benefit of our work.

First define the action you want and set it in a send to a javascript function.

For this case we will delete anything by linking to a specific path. user or organization/delete/ userID or organizationID is the basic set up. The dynamic variables are whether it’s a user or organization, and the specific ID.

So we are left with y/delete/x

You want to define that in the first object that the user clicks, before the confirm.

<a onclick="confirmation('/user/delete/<?=$emp->id; ?>');">

This is displayed to obviously delete a certain user based on their ID, you can substitute user with organization and call your organization the same way.
Next we want to make the module, we made ours using twitter bootstrap

<div id="confirm" class="modal hide fade">
<div class="modal-header"><h3>OH WAIT!</h3></div>
Are you sure you want to delete this?
 
<div class="confirmInputWrapper">
 
<a class="confirmConfirm btn" value="Delete" data-toggle="modal">Delete</a>
<a class="confirmCancel btn" onClick="javascript: $('#confirm').modal('hide'); $('.modal-backdrop')">Cancel</a>
<div class="clear"></div>
</div>

and lastly we want to make the confirmation button. The link between the object clicked and the actual send to the path.

function confirmation(action)
{
	$(".confirmSubmit").attr("href", ""+action+"");
	$("#confirm").modal('show');
}

This function grabs the delete path, as action, and ads it to the confirm button that is classed as confirmSubmit. It then does a twitter bootstrap call to show the modal before deleting the user.

After this all the user really has to do is click confirm.

How Can I Make a Php Alphabet Loop?

A useful feature of many coding languages is the “for loop”. A basic loop in php has for following structure:

for (init; condition; increment)
  {
  code to be executed;
  }

Parameters:

init: Mostly used to set a counter (but can be any code to be executed once at the beginning of the loop)
condition: Evaluated for each loop iteration. If it evaluates to TRUE, the loop continues. If it evaluates to FALSE, loop ends.
increment: Mostly used to increment a counter (but can be any code to be executed at the end of the iteration)

So basically, all I used this for was to go over a set of numbers, with i=0, and i++ everytime if went through the loop until i was less than ‘x’.  I didn’t realize php can also loop over the alphabet (using foreach).

foreach(range('a','z') as $i) {
    echo $i;
}

Knowledge shared.

How do I remove a domain from a string in PHP?

This doesn’t feel like it should be that hard, and luckily it’s not! However, some of the more common ways I found had been commented on being rather unreliable.  Most people recommend an easy str_replace, removing the specified domain and replacing it with an empty string.  But what if you don’t know your domain yet, what if your still in development? No one wants to go back and change that…

So here’s a rather brilliant little combo of exploding and replacing that will work regardless of what the domain is. Done and done.

$fileurl = get_field('pdf');
$fileurlexplode = explode('.com/', $fileurl);
$removedomain = $fileurlexplode [0].'.com/';
$fileurl = str_replace($removedomain , "",$fileurl); ?>