<?php 
 
/** 
 * Implements hook_shadow_node_edit. 
 * 
 * @param Environment $env 
 *   The current Environment. 
 * @param $vars 
 *   An array of variables. 
 */ 
function access_shadow_node_form($env, $vars) { 
  /** @var Shadow $shadow */ 
  $shadow = &$vars['shadow']; 
  $shadow->addTab('manage permissions', file_get_contents($env->getModulePath('access') . '/tpl/permissions_form.html'), 5); 
} 
 
/** 
 * Implements hook_node_presave(). 
 * 
 * @param Environment $env 
 *   The current Environment. 
 * @param $vars 
 *   An array of variables. 
 */ 
function access_node_presave($env, $vars) { 
  $node_permissions = array( 
    'node_add', 
    'node_edit', 
    'node_delete', 
    'node_view', 
  ); 
  /** @var Node $node */ 
  $node = &$vars['node']; 
  // TODO: review this process. 
  if (!isset($node->json->permissions)) { 
    $node->json->permissions = new StdClass(); 
  } 
  // Set all the node's permissions. 
  foreach ($node_permissions as $permission) { 
    if (isset($vars['data'][$permission])) { 
      $node->json->permissions->{$permission} = $vars['data'][$permission]; 
    } 
  } 
} 
 
/** 
 * Implements hook_node_open(). 
 * 
 * @param Environment $env 
 *   The Environment. 
 * @param $vars 
 *   An array of variables. 
 */ 
function access_node_open($env, $vars) { 
  /** @var Node $node */ 
  $node = &$vars['node']; 
 
  // Check if the user can access the node. 
  if (!empty($node) && $node->exists) { 
    $has_access = NodeAccess::check($env, NODE_ACTION_VIEW, array('node' => $node)); 
    if (!$has_access) { 
      $node = NodeFactory::buildForbiddenNode($env); 
    } 
  } 
} 
 
/** 
 * Check if a qtag is filtered via the filter attribute. 
 * 
 * TODO: make it open for all node attributes 
 * 
 * @param Environment $env 
 *   The Environment. 
 * @param $vars 
 *   An array of variables. 
 */ 
function access_qtag_preload($env, $vars) { 
  $node = NodeFactory::current($env); 
  $user = UserFactory::current($env); 
 
  // The user has selected to show the tag only if a certain criteria is matched. 
  if (!empty($vars['attributes']['filter'])) { 
  $filter_match = _access_filter($env, $vars['attributes']['filter'], $node, $user); 
    // If there is an active tag filter, and it doesn't match, empty the tag. 
    if (!$filter_match) { 
      $vars['access'] = FALSE; 
    } 
  } 
} 
 
/** 
 * Check access as defined by a qtag filter attribute. 
 * 
 * @param Environment $env 
 *   The Environment. 
 * @param string $criteria 
 *   The criteria to use for filtering check. 
 * @param Node $node 
 *   The node to use for filtering check. 
 * @param User $user 
 *   The user to use for filtering check. 
 * @return bool 
 *   Returns true if the access check was positive. 
 */ 
function _access_filter($env, $criteria, $node, $user = NULL) { 
 
 
  // Explode the criteria values. 
  $filter = explode(',', $criteria); 
 
  // Make matching false by default. 
  $filter_match = FALSE; 
 
  if ($user == NULL) { 
    $user = UserFactory::load($env, $node->getName()); 
  } 
 
  // Check all filters. 
  foreach ($filter as $filter_item) { 
    $exp = explode('@', $filter_item); 
    $filter_type = $exp[0]; 
    if (substr($filter_type, 0, 12) == 'current_user') { 
      $filter_type = str_replace('current_user', 'user', $filter_type); 
      $user = UserFactory::current($env); 
    } 
    if (substr($filter_type, 0, 12) == 'node_author') { 
      $filter_type = str_replace('node_author', 'user', $filter_type); 
      $user = new User($env, $node->getAuthor()); 
    } 
    $filter_values = explode(';', $exp[1]); 
 
    $filter_match = FALSE; 
    $break = FALSE; 
    $one_match = FALSE; 
 
    switch ($filter_type) { 
      // Filter by HTTP referer. 
      case 'referer': 
        $explode = explode('/', $_SERVER['HTTP_REFERER']); 
        $filter_check = $explode; 
        break; 
      // Filter by current node path. 
      case 'path': 
        $filter_check = array($node->getName()); 
        break; 
      // Filter by current node's father node. 
      case 'father': 
        $filter_check = array($node->getFather()->getName()); 
        break; 
      // Filter by current user's name. 
      case 'user_name': 
        $filter_check = array($user->getName()); 
        break; 
      // Filter by current user's role. 
      case 'user_role': 
        $filter_check = $user->getRoles(); 
        break; 
      // Filter by node's lineage (father, grandfather, and all ancestors!). 
      case 'lineage': 
        $one_match = TRUE; 
        $filter_check = array(); 
        $lineage = $node->getLineage(); 
        foreach ($lineage as $lineage_node) { 
          /** @var Node $lineage_node */ 
          $filter_check[] = $lineage_node->getName(); 
        } 
        break; 
 
      case 'context': 
        $filter_check[] = $env->getContext(); 
        break; 
 
      case 'category': 
        $filter_check = array(); 
        $categories = $node->getCategories(); 
        foreach ($categories as $category_node) { 
          /** @var Node $category_node */ 
          $filter_check[] = $category_node->getName(); 
        } 
        break; 
 
      case 'status': 
        $filter_check = array($node->getStatus()); 
        break; 
 
      default: 
 
        break; 
    } 
 
    if (!empty($filter_check)) { 
 
      // Check if the filtered item corresponds to the user input. 
      foreach ($filter_check as $check) { 
 
        foreach ($filter_values as $filter_value) { 
 
          if (substr($filter_value, 0, 1) == '!') { 
            $negate = TRUE; 
            $filter_value = str_replace('!', '', $filter_value); 
          } 
 
          $filter_match = ($check == $filter_value); 
 
          if ($filter_match && !isset($negate)) { 
            unset($one_match); 
            $break = TRUE; 
          } 
 
          if (isset($negate)) { 
            $filter_match = !$filter_match; 
            unset($negate); 
 
            if (!$filter_match) { 
              $break = TRUE; 
            } 
          } 
 
          if ($break) { 
            break; 
          } 
        } 
 
        // For multiple fields such as lineage one match is enough to validate. 
        if ($break) { 
          break; 
        } 
      } 
 
      //TODO: handle invalid / unknown filters. 
      //TODO: use hook for custom filters. 
 
      if (!$filter_match) { 
        break; 
      } 
    } 
    else { 
      $filter_match = TRUE; 
    } 
 
  } 
  return $filter_match; 
} 
 
 |