mysite.module

// $Id: mysite.module,v 1.97 2008/04/27 18:47:05 agentken Exp $


/**
 * @defgroup mysite Mysite: Allows users to create custom pages of site content.
 *
 * Before reading the API, you should refer to http://drupal.org/node/119576,
 * which offers a short tutorial on MySite plugins.
 *
 * Please be sure to also read http://drupal.org/node/318 for Drupal coding standards and refer to
 * http://api.drupal.org for core Drupal documentation.
 *
 * The best starting point for this API is probably http://therickards.com/api/group/hooks/MySite.
 * This section shows you the common functions used by MySite plugins.
 *
 * If you find errors in the documentation, please file an issue at http://drupal.org/project/issues/mysite.
 *
 * -- agentrickard
 */


/**
 * @file
 * Core module file for the MySite module.
 *
 * @ingroup mysite
 */


/**
 * Implementation of hook_help().
 */

function mysite_help($section) {
  switch ($section) {
    case 'admin/help#mysite':
      include_once('mysite_help.inc');
      $output = mysite_helptext();
      return $output;
      break;
    case 'admin/settings/mysite':
      $output = t('<p>The MySite module gives users a customized view of site data,
        arranged in the order they prefer.  The behavior and presentation of the MySite
        module can be controlled through the following settings.  For detailed instructions,
        see the README.txt file in your MySite folder.</p>'
);
      return $output;
      break;
  }
}

/**
 * Implementation of hook_menu().
  */

function mysite_menu($may_cache) {
  global $user;
  $items = array();
  // Run access checks once for the entire menu.
  $admin = FALSE;
  $view = user_access('view mysite');
  if (user_access('administer mysite')) {
    $admin = TRUE;
    $owner = TRUE;
    $create = TRUE;
  }
  else {
    $create = user_access('edit mysite');
    $owner = FALSE;
    if ($create && $user->uid == arg(1)) {
      $owner = TRUE;
    }
  }

  // Load the MySite data for the menu, if needed
  $show_pages = FALSE;
  if (arg(0) == 'mysite') {
    $uid = arg(1);
    $mysite = mysite_get($uid);
    $show_pages = TRUE;
    $access = mysite_menu_check($mysite->status, $owner, $view);
    // conditional functions needed by MySite's user interface
    // add the css to override form-item and format icons
    drupal_add_css(drupal_get_path('module', 'mysite') .'/mysite.css');
    // we use the collapse feature in the interface, so make sure it loads.
    if (function_exists('jquery_interface_add') && ($admin || $owner)) {
      drupal_add_js(drupal_get_path('module', 'mysite') .'/mysite.js', 'module');
      // add interface support
      jquery_interface_add();
    }
  }
  if ($may_cache) {
    $items[] = array('path' => 'admin/settings/mysite',
      'title' => t('MySite'),
      'description' => t('Adjust the features and settings for the MySite module.'),
      'callback' => 'mysite_configure',
      'access' => $admin);
    // menu items for default settings
    $items[] = array('path' => 'admin/settings/mysite/edit',
      'title' => t('Default page settings'),
      'description' => t('Edit the default MySite content settings.'),
      'callback' => 'drupal_goto',
      'weight' => -8,
      'type' => MENU_LOCAL_TASK,
      'callback arguments' => array('mysite/0/edit'),
      'access' => $admin);
    $items[] = array('path' => 'admin/settings/mysite/content',
      'title' => t('Default page content'),
      'description' => t('Edit the default MySite content settings.'),
      'weight' => -6,
      'callback' => 'drupal_goto',
      'type' => MENU_LOCAL_TASK,
      'callback arguments' => array('mysite/0/content'),
      'access' => $admin);
    // activate a plugin
    $items[] = array('path' => 'admin/settings/mysite/type/activate',
      'title' => mysite_sitename(),
      'callback' => 'mysite_activate',
      'type' => MENU_CALLBACK,
      'access' => $admin);
    // default page view items
    $items[] = array('path' => 'mysite',
      'title' => mysite_sitename(),
      'callback' => 'mysite_view',
      'access' => $view);
     // admin tasks
    $items[] = array('path' => 'mysite/0/admin',
      'title' => t('Settings'),
      'callback' => 'drupal_goto',
      'type' => MENU_LOCAL_TASK,
      'callback arguments' => array('admin/settings/mysite'),
      'weight' => -5,
      'access' => $admin);
    $items[] = array('path' => 'mysite/0/view',
      'title' => t('Default pages'),
      'callback' => 'mysite_view',
      'type' => MENU_LOCAL_TASK,
      'weight' => -3,
      'access' => $admin);
    $items[] = array('path' => 'mysite/0/edit',
      'title' => t('Default settings'),
      'callback' => 'mysite_edit',
      'type' => MENU_LOCAL_TASK,
      'access' => $admin);
    $items[] = array('path' => 'mysite/0/content',
      'title' => t('Default content'),
      'callback' => 'mysite_content',
      'type' => MENU_LOCAL_TASK,
      'access' => $admin);
    $items[] = array('path' => 'mysite-all',
      'title' => t('View all personal sites'),
      'callback' => 'mysite_view_all',
      'access' => $view);
    $items[] = array('path' => 'mysite-default',
      'title' => mysite_sitename(),
      'callback' => 'mysite_view_default',
      'type' => MENU_CALLBACK,
      'access' => $view);
    $items[] = array('path' => 'autocomplete/mysite',
      'title' => t('MySite autocomplete'),
      'callback' => 'mysite_autocomplete',
      'type' => MENU_CALLBACK,
      'access' => $create);
  }
  else {
    // add a tab to the user page
    if (arg(0) == 'user' && is_numeric(arg(1))) {
      $items[] = array('path' => 'user/'. arg(1) .'/mysite',
        'title' => mysite_sitename(),
        'access' => $owner,
        'callback' => 'mysite_page',
        'callback arguments' => array(arg(1)),
        'type' => MENU_LOCAL_TASK, 'weight' => 10);
    }
    // Ajax handling items
    $items[] = array('path' => 'ajax/mysite/'. arg(2) .'/'. arg(3),
      'title' => t('Ajax MySite'),
      'callback' => 'mysite_ajax',
      'callback arguments' => array(arg(2), arg(3)),
      'type' => MENU_CALLBACK,
      'access' => $create);
    $items[] = array('path' => 'ajax/mysite-sort',
      'title' => t('Ajax MySite'),
      'callback' => 'mysite_ajax_sort',
      'type' => MENU_CALLBACK,
      'access' => $create);
    if (arg(0) == 'mysite' && is_numeric(arg(1))) {
      $items[] = array(
        'title' => $mysite->title,
        'path' => 'mysite/'. arg(1),
        'type' => MENU_NORMAL_ITEM,
        'weight' => -10,
        'callback' => 'mysite_view',
        'callback arguments' => array(arg(1)),
        'access' => $access);
      $items[] = array('path' => 'mysite/'. arg(1) .'/delete',
        'title' => t('Delete'),
        'callback' => 'drupal_get_form',
        'callback arguments' => array('mysite_delete_form', arg(1)),
        'access' => $owner,
        'weight' => 10,
        'type' => MENU_LOCAL_TASK);
      $items[] = array('path' => 'mysite/'. arg(1) .'/reset',
        'title' => t('Reset'),
        'callback' => 'drupal_get_form',
        'callback arguments' => array('mysite_reset_form'),
        'access' => $owner,
        'type' => MENU_CALLBACK);
      if ($show_pages) {
        // Load data for sub-pages.
        $pages = mysite_get_pages($uid);
        // Menu actions to implement
        $actions = array(
          'view' => array('title' => t('View'), 'weight' => -10, 'path' => 'view', 'callback' => 'mysite_page'),
          'edit' => array('title' => t('Settings'), 'weight' => -8, 'path' => 'edit', 'callback' => 'mysite_edit'),
          'content' => array('title' => t('Content'), 'weight' => -6, 'path' => 'content', 'callback' => 'mysite_content')
        );
        // prep the submenu tasks
        $weight = -10;
        $test = arg(2);
        $arg = (empty($test)) ? 'view' : $test;
        $i = arg(3);
        $page = (empty($i)) ? 0 : $i;
        $page = ($page == 'add-page') ? 0 : $page;
        // We can only remove pages if it is not the default page.
        if ($page > 0 && count($pages) > 0) {
          $actions['remove'] = array('title' => t('Remove page'), 'weight' => -4, 'path' => 'remove-page', 'callback' => 'mysite_remove_page');
        }
        if ($arg == 'view') {
          $items[] = array(
            'title' => t('View'),
            'path' => 'mysite/'. arg(1) .'/view',
            'type' => MENU_DEFAULT_LOCAL_TASK,
            'weight' => -10,
            'callback' => 'mysite_view',
            'callback arguments' => array(arg(1)),
            'access' => $access
          );
          if (count($pages) < variable_get('mysite_pages', 5)) {
            $items[] = array(
              'title' => t('Add new page'),
              'path' => 'mysite/'. arg(1) .'/view/add-page',
              'type' => MENU_LOCAL_TASK,
              'weight' => 100,
              'callback' => 'mysite_add_page',
              'callback arguments' => array(arg(1)),
              'access' => $owner
            );
          }
        }
        $content_set = MENU_CALLBACK;
        if ($test == 'settings') {
          $content_set = MENU_LOCAL_TASK;
        }
        $items[] = array('path' => 'mysite/'. arg(1) .'/settings/'. arg(3) .'/'. arg(4),
          'title' => t('Customize'),
          'callback' => 'mysite_content_settings',
          'callback arguments' => array(arg(1), arg(4)),
          'access' => $owner,
          'weight' => 10,
          'type' => $content_set
        );
        foreach ($actions as $action => $settings) {
          if ($action == $arg && !empty($pages)) {
            $items[] = array(
              'title' => $settings['title'],
              'path' => 'mysite/'. arg(1) .'/'. $settings['path'],
              'type' => MENU_LOCAL_TASK,
              'weight' => $settings['weight'],
              'callback' => $settings['callback'],
              'callback arguments' => array(arg(1)),
              'access' => ($arg == 'view') ? $access : $owner
            );
            foreach ($pages as $key => $value) {
              $type = MENU_LOCAL_TASK;
              $page_access = $owner;
              if ($settings['path'] == 'view') {
                $page_access = mysite_menu_check($value['status'], $owner, $view);
                if ($key == 0) {
                  $type = MENU_DEFAULT_LOCAL_TASK;
                }
              }
              $items[] = array(
                'title' => $value['title'],
                'path' => 'mysite/'. arg(1) .'/'. $settings['path'] .'/'. $key,
                'type' => $type,
                'weight' => (-10 + $value['page']),
                'callback' => $settings['callback'],
                'callback arguments' => array(arg(1), arg(3)),
                'access' => $page_access
              );
              $weight++;
            }
          }
          $items[] = array(
            'title' => $settings['title'],
            'path' => 'mysite/'. arg(1) .'/'. $settings['path'] .'/'. $page,
            'type' => MENU_LOCAL_TASK,
            'weight' => $settings['weight'],
            'callback' => $settings['callback'],
            'callback arguments' => array(arg(1), arg(3)),
            'access' => $owner
          );
          if ($arg == 'edit') {
            $_mysite_edit = mysite_edit_menu();
            foreach ($_mysite_edit as $key => $value) {
              foreach ($value as $path => $element) {
                $items[] = array('path' => 'mysite/'. arg(1) .'/edit/'. $key .'/'. $path,
                  'title' => $element['label'],
                  'callback' => 'mysite_edit',
                  'callback arguments' => array(arg(1), arg(3), arg(4)),
                  'access' => $owner,
                  'type' => MENU_LOCAL_TASK
                );
              }
            }
          }
        }
      }
      // theme switching check
      if (arg(0) == 'mysite' && is_numeric(arg(1))) {
        $types = variable_get('mysite_content', NULL);
        $themesvariable_get('mysite_theme_settings', array());
        if (!empty($pages[$page]['theme']) && !empty($types['theme']) && !empty($themes[$mysite->theme])) {
          global $custom_theme;
          $custom_theme = $pages[$page]['theme'];
        }
      }
      $items[] = array('path' => 'mysite/'. arg(1) .'/remove/'. arg(3),
        'title' => t('Remove item'),
        'callback' => 'mysite_content_remove',
        'callback arguments' => array(arg(1), arg(3)),
        'access' => $owner,
        'weight' => 10,
        'type' => MENU_CALLBACK);
      $items[] = array('path' => 'mysite/'. arg(1) .'/promote/'. arg(3) .'/'. arg(4),
        'title' => t('Promote item'),
        'callback' => 'mysite_content_promote',
        'callback arguments' => array(arg(1), arg(3), arg(4)),
        'access' => $owner,
        'weight' => 10,
        'type' => MENU_CALLBACK);
      $items[] = array('path' => 'mysite/'. arg(1) .'/add',
        'title' => t('Add item'),
        'callback' => 'mysite_content_add',
        'callback arguments' => array(arg(1)),
        'access' => $owner,
        'weight' => 10,
        'type' => MENU_CALLBACK);
    }
    if ($admin && arg(0) == 'admin' && arg(2) == 'mysite') {
      $types = mysite_load_includes('types', NULL, $load_all = TRUE);
      $items[] = array('path' => 'admin/settings/mysite/type',
        'title' => t('Settings'),
        'description' => t('Adjust the features and settings for the MySite module.'),
        'type' => MENU_DEFAULT_LOCAL_TASK,
        'access' => $admin,
        'weight' => -10);
      $items[] = array('path' => 'admin/settings/mysite/type/settings',
        'title' => t('MySite'),
        'description' => t('Adjust the features and settings for the MySite module.'),
        'type' => MENU_DEFAULT_LOCAL_TASK,
        'access' => $admin,
        'weight' => -10);
      if (is_array($types)) {
        foreach ($types as $type) {
          $check = module_invoke('mysite_type', $type, FALSE);
          if ((function_exists('mysite_type_'. $type .'_title') || function_exists('mysite_type_'. $type .'_settings')) && is_array($check)) {
            $items[] = array('path' => 'admin/settings/mysite/type/'. $type,
            'title' => t('@type', array('@type' => ucwords($type))),
            'description' => t('Settings for the @type plugin', array('@type' => ucwords($type))),
            'callback' => 'mysite_type_settings',
            'callback arguments' => array($type),
            'type' => MENU_LOCAL_TASK,
            'access' => $admin,
            'weight' => 0);
          }
        }
      }
    }
  }
  return $items;
}

/**
 * Installer function that sets MySite pages to show on all domains.
 *
  */

function mysite_enable() {
  $pages = variable_get('domain_grant_all', "user/*/track");
  if (strpos($pages, 'mysite/*') == 0) {
    $pages .= "\r\nmysite/*";
    variable_set('domain_grant_all', $pages);
  }
}

/**
 * Implementation of hook_perm().
  */

function mysite_perm() {
  $array = array('administer mysite', 'edit mysite', 'view mysite');
  // if using aggregator, we have an additional permission
  if (module_exists('aggregator')) {
    $array[] = 'add mysite feeds';
  }
  return $array;
}

/**
 * Implementation of hook_user().
  */

function mysite_user($type, &$edit, &$user) {
  if ($type == 'view' && user_access('edit mysite', $user)) {
    $mysite = mysite_get($user->uid);
    if ($mysite->uid > 0 && user_access('administer mysite') || $mysite->status == 1) {
      $items['mysite'] = array('title' => mysite_sitename(),
        'value' => l($mysite->title, "mysite/$user->uid/view", array('title' => t("Read @username's personal page.", array('@username' => $user->name)))),
        'class' => 'mysite',
      );
      return array(t('History') => $items);
    }
  }
}

/**
 * Implementation of hook_block().  Calls mysite_type_hook_block().
 *
 * @param $nid
 *   We invoke this hook from mysite_link as well, so this variable lets us
 *   make minor changes to the output call, as needed.  Passing the node id
 *   gives us both the data and the logic necessary to invoke the MySite hooks.
  */

function mysite_block($op = 'list', $delta = 0, $nid = NULL) {
  global $user;
  if ($op == 'list') {
    $blocks[0]['info'] = t('MySite');
    return $blocks;
  }
  else if ($op == 'view' && user_access('edit mysite')) {
    // Each of the type includes must check the path. No point in calling arg() more than once.
    for ($i = 0; $i < 5; $i++) {
      $arg[$i] = arg($i);
    }
    $content = '';
    // if the user has a mysite, generate a link to it.
    $mysite = mysite_get($user->uid);
    if ($mysite->uid > 0) {
      $content .= '<ul>';
      $content .= '<li>'. l($mysite->title, 'mysite/'. $mysite->uid .'/view') .'</li>';
      if (user_access('view all mysites') && empty($nid)) {
        $content .= '<li>'. l(t('View custom sites'), 'mysite-all') .'</li>';
      }
      $content .= '</ul>';
    }
    // if not, help them create a mysite.
    else {
      $content = theme_mysite_block_help();
    }
    // load the type includes and check for block content. See the README for more.
    if (user_access('edit mysite')) {
      static $result, $pages, $page_count, $page, $check = FALSE;
      if (!isset($page)) {
        $page = mysite_find_empty_page($user->uid);
      }
      if ($page >= 0) {
        $types = mysite_load_includes('types');
        foreach ($types as $key => $value) {
          $content .= module_invoke('mysite_type', $value .'_block', $arg, $op);
        }
        // universal handler for nodes, where $nid may be passed from mysite_link()
        // or inferred from the path when viewing a node
        if (!empty($nid) || ($arg[0] == 'node' && is_numeric($arg[1]))) {
          if (!$nid) {
            $nid = $arg[1];
          }
          $query = db_fetch_object(db_query("SELECT n.type, n.nid FROM {node} n WHERE n.nid = %d", $nid));
          if ($query->nid > 0) {
            foreach ($types as $key => $value) {
              $content .= module_invoke('mysite_type', $value .'_block_node', $query->nid, $query->type);
            }
          }
        }
      }
      else {
        if (count($pages) < variable_get('mysite_pages', 5)) {
          $content .= l(t('Create new personal page'), 'mysite/'. $user->uid .'view/add-page');
        }
        else {
          $content .= t('Your personal page is currently full. Go to <a href="@url">add or remove content</a> to delete an item.', array('@url' => url("mysite/$user->uid/content")));
        }
      }
    }
  }
  // if we returned $content, then print the block.
  if (!empty($content)) {
    $block['subject'] = mysite_sitename();
    $block['content'] = $content;
  }
  return $block;
}

/**
 * Implementation of hook_link()
 */

function mysite_link($type, $node = NULL, $teaser = FALSE) {
  if ($type == 'node' && $node->nid) {
    $show = variable_get('mysite_links', 1);
    // 0 == no; 1 == always, 2 == page view only
    if ($show == 1 || ($show == 2 && !$teaser)) {
      global $user;
      if ($user->uid > 0 && user_access('edit mysite')) {
        $link = l(mysite_sitename(), 'mysite/'. $user->uid .'/view', array('class' => 'mysite-anchor'));
        drupal_add_js(drupal_get_path('module', 'mysite') .'/mysite_links.js', 'module');
        drupal_add_css(drupal_get_path('module', 'mysite') .'/mysite_links.css');
        $links = array();
        // we already prepare the links in hook_block, so get them and theme them.
        $data = mysite_block('view', 0, $node->nid);
        $string = str_replace('<ul>', '', $data['content']);
        $content = str_replace('</ul>', '', $string);
        $links['mysite'] = array(
            'title' => theme('mysite_links', $link, $content),
            'html' => TRUE
        );
        return $links;
      }
    }
  }
}

/**
 * Menu callback; presents general configuration options.
 */

function mysite_configure() {
  // run the cron hook if cron isn't configured properly.
  mysite_cron();
  // set the interface variable
  if (!function_exists('jquery_interface_add') && !$_POST) {
    drupal_set_message(t('To enable drag-and-drop sorting of content, you must install and enable the <a href="!jq">jQuery Update</a> and <a href="!ji">jQuery Interface</a> modules.', array('!jq' => 'http://drupal.org/project/jquery_update', '!ji' => 'http://drupal.org/project/jquery_interface')));
  }
  return drupal_get_form('mysite_configure_form');
}

/**
 * Cron hook for cleaning out bad data
 * We use this routine to remove MySite references
 * to deleted content containers.
  */

function mysite_cron() {
  // run this once per day, if cron is disabled, it runs from the settings page
  $cron= variable_get('mysite_cron', '0');
  $date = date("Ymd", time() - (3600 * 24)); // get yesterday's date
  if ($date != $cron) {
    variable_set('mysite_cron', $date);
    $types = mysite_load_includes('types');
    foreach ($types as $type) {
      $data[$type] = module_invoke('mysite_type', $type .'_clear', $type);
    }
    // iterate through the returns and set user messages
    if (!empty($data)) {
      foreach ($data as $key => $value) {
        if (is_array($value) && !empty($value)) {
          foreach ($value as $item) {
            $sql = "DELETE FROM {mysite_data} WHERE mid = %d";
            db_query($sql, $item['mid']);
            $sql = "SELECT message FROM {mysite} WHERE uid = %d";
            $obj = db_fetch_object(db_query($sql, $uid));
            $message = $obj->message;
            $message .= t('<p>@title content is no longer available and has been removed from your personal page.</p>', array('@title' => $item['title']));
            $sql = "UPDATE {mysite} SET message = '%s' WHERE uid = %d";
            db_query($sql, $message, $item['uid']);
          }
        }
      }
    }
  }
}

/**** PAGE VIEW FUNCTIONS  ****/

/**
 * Take user to the correct MySite page, based on mysite_configure().
 */

function mysite_view($uid = NULL) {
  global $user;
  if (is_null($uid)) {
    $list = variable_get('mysite_list', 0);
    if ($list) {
      drupal_goto('mysite-all');
    }
    $uid = arg(1);
  }
  $mysite = mysite_get($uid);
  if ($mysite->uid > 0 && user_access('view mysite')) {
    drupal_goto('mysite/'. $mysite->uid .'/view');
  }
  else if ($user->uid > 0) {
    return theme('mysite_create_help', $user);
  }
  else {
    return theme('mysite_anonymous_help');
  }
}

/**
 * View all active MySite users
 */

function mysite_view_all() {
  $output = '';
  $header = array(
    array('data' => t('Name'), 'field' => 'name'),
    array('data' => t('Collection Title'), 'field' => 'title'),
    array('data' => t('Updated'), 'field' => 'updated')
    );
  $sql = 'SELECT m.uid, m.title, m.created, m.updated, u.name, u.picture FROM {mysite} m INNER JOIN {users} u ON m.uid = u.uid WHERE u.status = 1 AND m.status = 1'. tablesort_sql($header);
  if (user_access('administer mysite')) {
    $sql = 'SELECT m.uid, m.title, m.created, m.updated, u.name, u.picture FROM {mysite} m INNER JOIN {users} u ON m.uid = u.uid WHERE u.status = 1'. tablesort_sql($header);
  }
  $result = pager_query($sql, 25);
  $rows = array();
  while ($owner = db_fetch_object($result)) {
    $updated = $owner->created;
    if (!empty($owner->updated)) {
      $updated = $owner->updated;
    }
    $rows[] = array('data' => array($owner->name, l($owner->title, 'mysite/'. $owner->uid .'/view'), format_date($updated, $type = 'medium', $format = '', $timezone = NULL)));
    if ($owner->uid == $user->uid) {
      $nopage = FALSE;
    }
  }
  // no users found
  if (!empty($rows)) {
    $output .= theme_table($header, $rows);
    $output .= theme('pager', NULL, 25, 0);
  }
  else {
    $top_output .= l(t('There are no publicly viewable personal collections.'), "mysite/". $user->uid);
  }
  // can this user create a mysite?
  $mysite = mysite_get($user->uid);
  if (user_access('edit mysite') && empty($mysite)) {
    $top_output .= l(t('Create your own personal collection.'), "mysite/". $user->uid .'/edit');
  }
  $output = $top_output . $output;
  return $output;
}

/**
 * Show the default user page
 */

function mysite_view_default() {
  // show the default mysite
  $default = (int) variable_get('mysite_default_user', 0);
  drupal_goto('mysite/'. $default .'/view');
}

/**
 * The default MySite page view.
 *
 * @param $uid
 * The user id of the owner of the mysite.
 * @param $page
 * The current page of the mysite collection.
 * @param $pageview
 *  Boolean flag that indicates the data will be viewed using theme_page.
 *  If you want to access this data externally, set $pageview = FALSE.
 * @return
 *  $content array.
 *  If $pageview = FALSE, the function will return a $content array with three elements.
 *    $content['owner'] = the $user object of the MySite page's owner.
 *    $content['mysite'] = MySite data for the page's owner.
 *    $content['data'] = MySite data as defined by mysite_type_{name}_data().
 *  If the user does not have a MySite page, $content will return an empty array().
 */

function mysite_page($uid = NULL, $page = 0, $pageview = TRUE) {
  global $user;

  // get the $owner of this mysite, use as a $user surrogate
  if (is_null($uid)) {
    $uid = arg(1);
  }
  if (is_numeric($uid)) {
    $owner = user_load(array('uid' => $uid));
  }
  if (!isset($owner->uid)) {
    $owner = $user;
  }
  // Load the settings for this page.
  $mysite = mysite_load_page($owner->uid, $page);

  // access control set by the user 'status' flag
  $show = FALSE;
  // if the user is looking at the MySite data
  if ($user->uid == $owner->uid) {
    $show = TRUE;
    if ($pageview) {
      // get any system messages waiting for this user
      mysite_message($owner->uid);

      // this user has no page, give them help making one
      if (user_access('edit mysite')) {
        if (!isset($mysite->uid)) {
          $output = theme('mysite_create_help', $owner);
          return $output;
        }
      }
      else {
        return drupal_access_denied();
      }
    }
  }
  // access checks: can this user view this data?
  // these checks are here for external use of this function
  else if (user_access('administer mysite') || $mysite->uid == 0 || $mysite->status == 1) {
    $show = TRUE;
  }
  // show the page or return the data
  if ($show) {
    mysite_load($mysite, $pageview);
    // the cache wrapper
    $content = NULL;
    $cache_set = variable_get('mysite_cache', 0);
    if ($cache_set > 0) {
      $expire = db_result(db_query("SELECT expire FROM {cache} WHERE cid = '%s'", 'mysite:'. $mysite->uid .':'. $mysite->page));
      if (time() < $expire) {
        $data = cache_get('mysite:'. $mysite->uid .':'. $mysite->page, 'cache');
        $content = unserialize($data->data);
      }
      if (isset($content['owner']) && empty($content['data'])) {
        // This page is blank in the cache, so just render the approprate message.
        return mysite_output($owner, $mysite, $content = array(), $pageview);
      }
    }
    if (empty($content)) {
      $data = array();
      /* get the data for this user
          for each type of content listed in the user's mysite_data set
          run the appropriate include / theme function
          append the themed data to the $data array
          using the order value as the key
      */

      $sql = 'SELECT mid, uid, page, title, type, type_id, sort, position, format, settings, locked FROM {mysite_data} WHERE (uid = %d OR (uid = 0 AND locked = 1)) AND page = %d ORDER BY position ASC, sort ASC';
      $result = db_query($sql, $owner->uid, $page);
      $i = 0;
      $allowed = variable_get('mysite_content',