<?php

// Search for a page, by selecting by its path.
// Useful in transform hooks (e.g. Autolinks) where
// a link to a page can be generated by knowing some part
// of its path.
// path: the path of the page, in the form [/][path-part/ ...][page]
// dd_flag: indicates whether DD data is needed for the final page.
// returns: the page data (without DD) or NULL if no matching page found

// e.g. for a real page '/home/about/the-org', this function will
// return the page 'the-org' against the following paths:
//  /home/about/the-org
//  home/about/the-org
//  about/the-org
//  the-org
// In addition, if 'about' is a module alias, the following will match:
//  /about/the-org
// It is also possible to include fragments and URLs in the path:
//  /about/the-org?param=value#fragment
// This does not affect the matched page, but the 'url' element returned
// will contain these elements (ie parameters and fragment).

function xarpages_userapi_getpagebypath($args)
{
    extract($args);

    if (!isset($path)) {
        return;
    }

    // If any extra parameters or fragments have been passed then, then
    // strip them off now for adding again later.
    // e.g. page/name?p1=v1#fragment
    if (preg_match('/#/', $path)) {
        // A fragment was included. This will be on the end of the URL
        $fragment = preg_replace('/.*#/', '', $path);
        $path = preg_replace('/#.*/', '', $path);
    } else {
        $fragment = NULL;
    }

    if (preg_match('/\?/', $path)) {
        // Parameters have been supplied. This will be on the end of the URL
        $params = preg_replace('/.*\?/', '', $path);
        $path = preg_replace('/\?.*/', '', $path);

        // Expand the params into an array we can merge in later.
        $params = explode('&', $params);
        $params2 = array();
        foreach($params as $param) {
            list($p, $v) = explode('=', $param);
            if (!empty($p) && isset($v)) {
                $params2[$p] = $v;
            }
        }
        $params = $params2;
    } else {
        $params = array();
    }


    // The page is the top part.
    $pagename = basename($path);

    // Path could be absolute or relative (i.e. we may or may not know the root page).
    if (strpos($path, '/') === 0) {
        $absolute = true;

        // However, if the top level also happens to be a
        // module alias, then make it relative (since nothing
        // below that alias matters in their URL).
        $explode = explode('/', $path);
        if (count($explode) > 2 && xarModGetAlias($explode[1]) == 'xarpages') {
            $absolute = false;
        }
    } else {
        $absolute = false;
    }

    // Now fetch pages that match the page name, along with their ancestors.
    // TODO: if there is no path (i.e. just a page name), then we don't have
    // to worry about ancestors.
    $pages = xarModAPIfunc(
        'xarpages', 'user', 'getpages',
        array(
            'tree_contains_name' => $pagename,
            'tree_ancestors' => true,
            'dd_flag' => false,
            'key' => 'pid'
        )
    );

    // Scan the pages so we have arrays of ancestors we can scan.
    // Create expanded string paths from the pages, and match strings.
    $all_paths = array();

    $depthstack = array();
    $pathstack = array();
    foreach($pages as $pid => $page) {
        // 
        if (!empty($depthstack)) {
            while (!empty($depthstack) && end($depthstack) < $page['right']) {
                array_pop($depthstack);
                array_pop($pathstack);
            }
        }
        $depthstack[] = $page['right'];
        $pathstack[] = $page['name'];

        if ($page['name'] == $pagename) {
            $all_paths[$pid] = '/' . implode('/', $pathstack);
        }
    }

    // We now have a set of paths that match the page name.
    // Hopefully there will be just one path, but there could
    // be more since uniqueness is not enforced on page names.

    // Scan the paths and see if the path we have been given matches.
    $page_id = 0;
    foreach($all_paths as $pid => $this_path) {
        $pages[$pid]['path'] = $this_path;
        if ($absolute && $this_path == $path) {
            // Found an exact match on an absolute path.
            $page_id = $pid;
            break;
        }
        if (!$absolute && substr($this_path, -strlen($path)) == $path) {
            // Found a right-hand match on a relative path.
            $page_id = $pid;
            break;
        }
    }

    if ($page_id > 0) {
        $page =& $pages[$page_id];
        // A page was found.
        // If DD data is needed for the matched page, then fetch it.
        if (!empty($dd_flag)) {
            $dd_data = xarModAPIfunc('xarpages', 'user', 'getpagedd', array('pages' => array($page_id => $page)));
            $page['dd'] = $dd_data[$page_id];
        }

        // Create the URL for this page.
        // XML encoding is left at its default setting.
        $params['pid'] = $page_id;
        $page['url'] = xarModURL('xarpages', 'user', 'display', $params, NULL, $fragment);

        return $pages[$page_id];
    } else {
        // No matching page was found.
        return;
    }
}

?>