'. t('View Origo Home.') .'

'; return $o; } } /** * Implementation of hook_perm(). * Define the permissions this module uses. */ function origo_home_perm() { return array( 'access content', 'origo admin access', 'origo project settings', 'origo create project', 'origo request application key', 'origo create release', 'origo delete release' ); } /** * Implementation of hook_theme(). */ function origo_home_theme() { return array( 'origo_home_project_settings_navigation_form' => array( 'arguments' => array('form' => NULL) ), 'origo_home_settings_subscriptions_form' => array( 'arguments' => array('form' => NULL) ), 'origo_home_settings_user_icon_form' => array( 'arguments' => array('form' => NULL) ), 'origo_home_settings_personal_information_form' => array( 'arguments' => array('form' => NULL) ), 'origo_home_settings_contact_information_form' => array( 'arguments' => array('form' => NULL) ), 'origo_home_additional_settings_form' => array( 'arguments' => array('form' => NULL) ), 'origo_home_create_release_form' => array( 'arguments' => array('form' => NULL) ), 'origo_home_project_information_form' => array( 'arguments' => array('form' => NULL) ), 'origo_home_project_settings_members_page' => array( 'arguments' => array('values' => NULL) ), 'dashboard_workitems_tabs' => array( 'arguments' => array('tabs' => NULL) ), 'dashboard_workitems_read_link' => array( 'arguments' => array('project_name' => NULL, 'unread_only' => NULL) ), 'dashboard_workitems_mark_read_and_feed_link' => array( 'arguments' => array('project' => NULL, 'feed_url' => NULL) ), 'dashboard_settings' => array( 'arguments' => array('itmes' => NULL) ), 'origo_home_menu' => array( 'arguments' => array('menu' => NULL) ), 'origo_home_repository_links' => array( 'arguments' => array('content' => NULL) ), 'origo_home_access_matrix' => array( 'arguments' => array('$headers' => NULL, 'data' => NULL) ), ); } // -------------------------------------------------------------------------------------- /** * Title callback for menu paths to "/dashboard". * Displays the project name of the currently selected project. * @param $title The project name passed in the URL. * @return String The appropriate title string. */ function dashboard_workitems_title_callback($project_name) { if (!isset($project_name) || $project_name == '') { $project_name = variable_get('origo_project_name', 'Error retrieving project name'); } return "Work Items for Project ". $project_name; } /** * Access callback for links that only existing users may access. * @return Boolean denoting if $user is a registered user. */ function origo_home_existing_user_access() { global $user; // Note: anonymous users have uid 0. return $user->uid > 0; } /** * Access callback for menu paths into a user's profile. * Existing user may access pages, while anonymous users only get access if * anonymous access is specified in the $username's profile. * * @param $username Name of the user's profile that is requested. * @return Boolean denoting if $user is a registered user. */ function origo_home_profile_visible_access($username) { global $user; $profile_visible = 1; if ($user->uid <= 0) { $ret = origo_auth_xml_rpc(variable_get('origo_api', ''), 'user.profile_visible', $username); $profile_visible = $ret['profile_visible']; } return $profile_visible; } /** * Access callback for testing access of the logged-in user against * user-specific pages, e.g. user-account pages. * @param $username Name of the affected user. * @return Boolean denoting if access is granted. */ function origo_home_user_account_access($username) { global $user; if (strcmp($user->name, $username) == 0) { return TRUE; } } /** * Access callback for testing access of the logged-in user against * admin-priviledges of the community $community_name. * @param $community_name Name of the community of interest. * @return Boolean denoting if access is granted. */ function origo_home_community_admin_access($community_name) { if (!is_string($community_name)) { return FALSE; } return (origo_home_community_is_origo_admin() || origo_home_community_is_community_admin($community_name)); } /** * Access callback for testing access of the logged-in user against * community membership of the community $community_name. * @param $community_name Name of the community of interest. * @return Boolean denoting if access is granted. */ function origo_home_community_member_access($community_name) { if (!is_string($community_name)) { return FALSE; } $is_community_member = origo_home_community_is_community_member($community_name); return ($is_community_member || origo_home_community_admin_access($community_name)); } /** * Loader function for menu-paths containing Origo-usernames. * @param $username String denoting an Origo-username. * @return The Origo-username or FALSE. */ function origo_username_load($username) { //TODO: can usernames be just numbers? like "1337"? if (!is_string($username)) { return FALSE; } // TODO: Here we could query Origo's backend to check if the username's valid, // but this will most likely be done by the menu-access function. // Thus, for now, we just return the string. return $username; } /* Loader function for menu-path containing Users Group_ID * @param $group_id Integer denoting an Users Group_ID * @return Users Group_ID or FALSE */ function origo_group_id_load($group_id) { $gid = (int) $group_id; if (!is_int($gid)) { return FALSE; } // TODO: Here we could query Origo's backend to check if the Group ID is valid, // but this will most likely be done by the menu-access function. // Thus, for now, we just return the ID. return $gid; } /** * Loader function for menu-paths containing Origo project IDs. * @param $project_id Integer denoting an Origo project ID. * @return The Origo project ID or FALSE. */ function origo_project_id_load($project_id) { $pid = (int)$project_id; if (!is_int($pid)) { return FALSE; } // TODO: Here we could query Origo's backend to check if the project ID is valid, // but this will most likely be done by the menu-access function. // Thus, for now, we just return the ID. return $pid; } /** * Loader function for menu-paths containing Origo project names. * @param $project_name String denoting an Origo project name. * @return The Origo project name or FALSE. */ function origo_project_name_load($project_name) { if (!is_string($project_name)) { return FALSE; } // TODO: Here we could query Origo's backend to check if the project name is valid, // but this will most likely be done by the menu-access function. // Thus, for now, we just return the name. return $project_name; } /** * Loader function for menu-paths containing Origo release IDs. * NOTE: The functionality is - for now - identical to `origo_project_id_load', * but is contained in a separate function for consistency's sake. Also, an * eventual backend-check would have to be separated. * @param $release_id Integer denoting an Origo release ID. * @return The Origo release ID or FALSE. */ function origo_release_id_load($release_id) { $id = (int)$release_id; if (!is_int($id)) { return FALSE; } // TODO: Here we could query Origo's backend to check if the release ID is valid, // but this will most likely be done by the menu-access function. // Thus, for now, we just return the ID. return $id; } /** * Loader function for menu-paths containing Origo workitem IDs. * NOTE: The functionality is - for now - identical to `origo_release_id_load', * but is contained in a separate function for consistency's sake. Also, an * eventual backend-check would have to be separated. * @param $workitem_id Integer denoting an Origo workitem ID. * @return The Origo workitem ID or FALSE. */ function origo_workitem_id_load($workitem_id) { $id = (int)$workitem_id; if (!is_int($id)) { return FALSE; } // TODO: Here we could query Origo's backend to check if the workitem ID is valid, // but this will most likely be done by the menu-access function. // Thus, for now, we just return the ID. return $id; } /** * Loader function for menu-paths containing Origo revision numbers. * @param $revision Integer denoting an Origo revision number. * @return The Origo revision number or FALSE. */ function origo_revision_load($revision) { $rev = (int)$revision; if (!is_int($rev)) { return FALSE; } // TODO: Here we could query Origo's backend to check if the revision number is valid, // but this will most likely be done by the menu-access function. // Thus, for now, we just return the revision. return $rev; } /** * Loader function for menu-paths containing Origo wiki-page names. * @param $wiki_page String denoting an Origo wiki-page name. * @return The name of the wiki-page or FALSE. */ function origo_wiki_page_load($wiki_page) { if (!is_string($wiki_page)) { return FALSE; } return $wiki_page; } /** * Loader function for menu-paths containing Origo community names. * @param $community_name String denoting an Origo community name. * @return The name of the wiki-page or FALSE. */ function origo_community_name_load($community_name) { if (!is_string($community_name)) { return FALSE; } // TODO: Here we could query Origo's backend to check if the community name is valid, // but this will most likely be done by the menu-access function. // Thus, for now, we just return the community name. return $community_name; } /** * Loader function for retrieving menu-paths containing Origo-Feeds. * NOTE: Such a path may contain an optional part specifying the project's ID. * @param $feed_auth An encrypted string containing the authentication data. * @param $project_id An optional parameter denoting a project ID. * @return unknown_type */ function origo_feed_string_load($feed_auth, $project_id = NULL) { if (!is_string($feed_auth)) { return FALSE; } if (isset($project_id)) { // check the project-ID using another loader-function $val = origo_project_id_load($project_id); if ($val == FALSE) { return FALSE; } } return $feed_auth; } // -------------------------------------------------------------------------------------- /** * Implementation of hook_menu(). * * Defines Menu entries and path callbacks. */ function origo_home_menu() { global $user; // Workitem Dashboard (former Origo Home) $items['dashboard'] = array( 'title' => '', 'title callback' => 'dashboard_workitems_title_callback', 'file' => 'dashboard/workitem/dashboard_workitem.inc', 'page callback' => 'dashboard_workitems_project', 'access callback' => 'user_access', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); // Workitem Dashboard (former Origo Home) $items['dashboard/%'] = array( 'title' => 'Work Items for @project', 'title arguments' => array('@project' => 1), 'file' => 'dashboard/workitem/dashboard_workitem.inc', 'page callback' => 'dashboard_workitems_project', 'page arguments' => array(1), 'access callback' => 'user_access', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); // AJAX callback for retrieving a workitem's details $items['ajax/get_workitem/%'] = array( 'page callback' => 'retrieve_workitem_details', 'page arguments' => array(2), 'file' => 'dashboard/workitem/dashboard_workitem.inc', 'access callback' => 'user_access', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK ); // Origo Home - Create Project $items['origo_home/create_project'] = array( 'title' => 'Request Project', 'page callback' => 'origo_home_create_project_page', 'access callback' => 'user_access', 'access arguments' => array('origo create project'), 'type' => MENU_CALLBACK, ); // AHAH callback for project creation. $items['origo_home/create_project_ahah'] = array( 'page callback' => 'origo_admin_create_project_ahah', 'access arguments' => array('origo create project'), 'type' => MENU_CALLBACK, ); // Origo Home - Create Project $items['origo_home/settings'] = array( 'title' => 'Settings', 'page callback' => 'origo_home_settings_dashboard_page', 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // Origo Home - Settings - Origo Web - Workitem Browser Settings $items['origo_home/settings/workitems'] = array( 'title' => 'Workitem Settings', 'page callback' => 'drupal_get_form', 'page arguments' => array('origo_home_settings_workitem_settings_form'), 'file' => 'origo_settings.inc', 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // Origo Home - Settings - Origo Web - Workitem Browser Settings $items['origo_home/settings/issues'] = array( 'title' => 'Issue Settings', 'page callback' => 'drupal_get_form', 'page arguments' => array('origo_home_settings_issues_form'), 'file' => 'origo_settings.inc', 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // Origo Home - Settings - Workitem Subscriptions $items['origo_home/settings/subscriptions'] = array( 'title' => 'Subscriptions', 'page callback' => 'drupal_get_form', 'page arguments' => array('origo_home_settings_subscriptions_form'), 'file' => 'origo_settings.inc', 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // Origo Home - Settings - Bookmarks $items['origo_home/settings/bookmarks'] = array( 'title' => 'Bookmarks', 'page callback' => 'origo_home_settings_bookmarks_page', 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // Origo Home - Settings - User Key $items['origo_home/settings/userkey'] = array( 'title' => 'User Key', 'page callback' => 'origo_home_settings_userkey_page', 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // Origo Home - Settings - Password $items['origo_home/settings/password'] = array( 'title' => 'Password', 'page callback' => 'drupal_get_form', 'page arguments' => array('origo_home_settings_password_form'), 'file' => 'origo_settings.inc', 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // Origo Home - Settings - User Icon $items['origo_home/settings/user_icon'] = array( 'title' => 'Account Details', 'page callback' => 'origo_home_settings_user_icon_page', 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // Origo Home - Settings - Personal Information $items['origo_home/settings/personal_information'] = array( 'title' => 'Account Details', 'page callback' => 'origo_home_settings_personal_information_page', 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // Origo Home - Settings - Contact Information $items['origo_home/settings/contact_information'] = array( 'title' => 'Account Details', 'page callback' => 'origo_home_settings_contact_information_page', 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // Origo Home - Settings - Privacy Settings $items['origo_home/settings/additional_settings'] = array( 'title' => 'Account Details', 'page callback' => 'origo_home_additional_settings_page', 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // Origo Home - Settings - Disable Account $items['origo_home/settings/disable_account'] = array( 'title' => 'Disable Account', 'page callback' => 'origo_home_settings_disable_account_page', 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // Origo Home - Settings - Communities $items['origo_home/settings/communities'] = array( 'title' => 'Communities', 'page callback' => 'origo_home_settings_communities_page', 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // ------------------------------------------------------------------------------------------------ // Origo Home - User page $items['users/%origo_username'] = array( 'title' => arg(1), 'page callback' => 'origo_home_user_page', 'page arguments' => array(1), 'access callback' => 'origo_home_profile_visible_access', 'access arguments' => array(1), 'type' => MENU_CALLBACK, ); // Origo Home - User vCard page $items['users/%origo_username/vcard'] = array( 'title' => 'vCard Download', 'page callback' => 'origo_home_vcard_page', 'page arguments' => array(1), 'access callback' => 'origo_home_profile_visible_access', 'access arguments' => array(1), 'type' => MENU_CALLBACK, ); // Origo Home - User icon editing $items['users/%origo_username/edit_user_icon'] = array( 'title' => 'Edit User Icon', 'page callback' => 'origo_home_settings_user_icon_page', 'access callback' => 'origo_home_user_account_access', 'access arguments' => array(1), 'weight' => 0, 'type' => MENU_CALLBACK, ); // Origo Home - Personal information editing $items['users/%origo_username/edit_personal_information'] = array( 'title' => 'Edit Personal Information', 'page callback' => 'origo_home_settings_personal_information_page', 'access callback' => 'origo_home_user_account_access', 'access arguments' => array(1), 'weight' => 2, 'type' => MENU_CALLBACK, ); // Origo Home - Contact information editing $items['users/%origo_username/edit_contact_information'] = array( 'title' => 'Edit Contact Information', 'page callback' => 'origo_home_settings_contact_information_page', 'access callback' => 'origo_home_user_account_access', 'access arguments' => array(1), 'weight' => 4, 'type' => MENU_CALLBACK, ); // Origo Home - privacy settings editing $items['users/%origo_username/additional_settings'] = array( 'title' => 'Edit Privacy Settings', 'page callback' => 'origo_home_additional_settings_page', 'access callback' => 'origo_home_user_account_access', 'access arguments' => array(1), 'weight' => 6, 'type' => MENU_CALLBACK, ); // ------------------------------------------------------------------------------------------------ // Origo Home - Bookmark Add $items['origo_home/bookmarks/add/%origo_project_id'] = array( 'title' => 'Bookmark Adding', 'page callback' => 'origo_home_bookmark_add', 'page arguments' => array(3), 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // Origo Home - Bookmark Remove $items['origo_home/bookmarks/remove/%origo_project_id'] = array( 'title' => 'Bookmark Removal', 'page callback' => 'origo_home_bookmark_remove', 'page arguments' => array(3), 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // Origo Home - Global Search $items['search_global'] = array( 'title' => 'Global Search', 'page callback' => 'origo_home_global_search_page', 'access callback' => 'user_access', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); // Origo Home - Request application key $items['origo_home/request_appkey'] = array( 'title' => 'Request application key', 'page callback' => 'origo_home_request_appkey_page', 'access callback' => 'user_access', 'access arguments' => array('origo request application key'), 'type' => MENU_CALLBACK, ); // Origo Home - DOAP file $items['doap'] = array( 'title' => 'DOAP file', 'file' => 'origo_doap.inc', // include doap.inc 'page callback' => 'origo_home_print_doap', 'access callback' => TRUE, 'type' => MENU_CALLBACK, ); // Origo Home - Releases $items['download'] = array( 'title' => 'Download', 'page callback' => 'origo_home_release_page', 'access callback' => 'user_access', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); // Origo Home - Release Details $items['download/%origo_release_id'] = array( 'title' => 'Download', 'page callback' => 'origo_home_release_detail_page', 'page arguments' => array(1), 'access callback' => 'user_access', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); // Origo Home - Create Release $items['create_release'] = array( 'title' => 'Create Release', 'page callback' => 'origo_home_create_release_page', 'access callback' => 'user_access', 'access arguments' => array('origo create release'), 'type' => MENU_CALLBACK, ); // Origo Home - Delete Release $items['download/delete/%origo_release_id'] = array( 'title' => 'Delete Release', 'page callback' => 'origo_home_release_delete_page', 'page arguments' => array(2), 'access callback' => 'user_access', 'access arguments' => array('origo delete release'), 'type' => MENU_CALLBACK, ); // Origo Home - Feeds $items['origo_feed/%origo_feed_string'] = array( 'title' => 'Origo Feed', 'page callback' => 'origo_feed_page', 'page arguments' => array(1, 2), 'access callback' => 'user_access', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); // Origo Home - Mark Workitem Read $items['origo_home/mark_read/%origo_workitem_id'] = array( 'file' => 'dashboard/workitem/dashboard_workitem.inc', 'page callback' => 'origo_home_mark_read', 'page arguments' => array(2), 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // Origo Home - Mark Workitem unread $items['origo_home/mark_unread/%origo_workitem_id'] = array( 'file' => 'dashboard/workitem/dashboard_workitem.inc', 'page callback' => 'origo_home_mark_unread', 'page arguments' => array(2), 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // Origo Home - Mark all workitems read $items['origo_home/mark_all_read/%origo_workitem_id'] = array( 'file' => 'dashboard/workitem/dashboard_workitem.inc', 'page callback' => 'origo_home_mark_read_project', 'page arguments' => array(2), 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // Origo Home - Workitem redirect $items['origo_home/workitem/%origo_workitem_id'] = array( 'page callback' => 'origo_home_workitem_page', 'page arguments' => array(2), 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // Origo Home - Reported Issues $items['origo_home/reported_issues'] = array( 'file' => 'origo_home_reported_issues.inc', 'title' => 'Reported Issues', 'page callback' => 'origo_home_reported_issues_page', 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // Origo Home - Invite Friend to Origo $items['origo_home/invite_friends'] = array( 'title' => 'Invite your Friends to Origo', 'page callback' => 'origo_home_invite_friends_page', 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // -------------------------------------------------------------------------------------- // Origo Admin $items['origo_admin'] = array( 'title' => 'Origo Admin', 'page callback' => 'origo_admin_page', 'access callback' => 'user_access', 'access arguments' => array('origo admin access'), 'type' => MENU_CALLBACK, ); // Origo Admin - Mass Mail $items['origo_admin/massmail'] = array( 'title' => 'Mass Mail', 'page callback' => 'origo_admin_massmail_page', 'access callback' => 'user_access', 'access arguments' => array('origo admin access'), 'type' => MENU_CALLBACK, ); // Origo Admin - System Status $items['origo_admin/status'] = array( 'title' => 'System Status', 'page callback' => 'origo_admin_status_page', 'access callback' => 'user_access', 'access arguments' => array('origo admin access'), 'type' => MENU_CALLBACK, ); // Origo Admin - Create Project $items['origo_admin/create_project'] = array( 'title' => 'Create Project', 'page callback' => 'origo_admin_create_project_page', 'access callback' => 'user_access', 'access arguments' => array('origo admin access'), 'type' => MENU_CALLBACK, ); // Origo Admin - Create Project from request $items['origo_admin/create_project/%'] = array( 'title' => 'Create Project', 'page callback' => 'origo_admin_create_project_page', 'page arguments' => array(2), 'access callback' => 'user_access', 'access arguments' => array('origo admin access'), 'type' => MENU_CALLBACK, ); // Origo Admin - Remove Project $items['origo_admin/remove_project'] = array( 'title' => 'Remove Project', 'page callback' => 'origo_admin_remove_project_page', 'access callback' => 'user_access', 'access arguments' => array('origo admin access'), 'type' => MENU_CALLBACK, ); // Origo Admin - Change Project $items['origo_admin/change_project_type'] = array( 'title' => 'Change Project Type', 'page callback' => 'drupal_get_form', 'page arguments' => array('origo_admin_change_project_type_form'), 'access callback' => 'user_access', 'access arguments' => array('origo admin access'), 'type' => MENU_CALLBACK, ); $items['ajax/ahah-change-project'] = array( 'page callback' => 'ahah_change_project_callback', 'access arguments' => array('origo admin access'), 'type' => MENU_CALLBACK, ); // Origo Admin - Disable a user account $items['origo_admin/disable_account/%'] = array( 'title' => 'Disable Account', 'page callback' => 'origo_admin_disable_user_page', 'page arguments' => array(2), 'access callback' => 'user_access', 'access arguments' => array('origo admin access'), 'type' => MENU_CALLBACK, ); // -------------------------------------------------------------------------------------- // Project settings - for everyone with special form for project owner $items['project_settings'] = array( 'title' => 'Project Settings', 'page callback' => 'origo_home_project_settings_members_page', 'access callback' => 'user_access', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); // Project settings - Confirm form if want to remove yourself as last owner $items['project_settings/confirm/%origo_project_id/%origo_group_id/%origo_username'] = array( 'title' => 'Confirm Change User Group', 'page callback' => 'drupal_get_form', 'page arguments' => array('origo_home_project_change_group_confirm_form', 2, 3, 4), 'access callback' => 'user_access', 'access arguments' => array('origo project settings'), 'type' => MENU_CALLBACK, ); // Project settings for owners - Remove Member $items['project_settings/members/remove/%origo_username/%origo_project_id'] = array( 'page callback' => 'origo_home_project_settings_members_remove_validate', 'page arguments' => array(3, 4), 'access callback' => 'user_access', 'access arguments' => array('origo project settings'), 'type' => MENU_CALLBACK, ); // Project settings - Confirm form if want to remove the last owner $items['project_settings/confirm/%origo_project_id/%origo_username'] = array( 'title' => 'Confirm remove from User Group', 'page callback' => 'drupal_get_form', 'page arguments' => array('origo_home_project_settings_members_remove_confirm_form', 2, 3), 'access callback' => 'user_access', 'access arguments' => array('origo project settings'), 'type' => MENU_CALLBACK, ); // Project settings - for everyone with special form for project owner - Members $items['project_settings/members'] = array( 'title' => 'Members', 'page callback' => 'origo_home_project_settings_members_page', 'access callback' => 'user_access', 'access arguments' => array('access content'), 'weight' => -8, 'type' => MENU_DEFAULT_LOCAL_TASK, ); // Project settings for owners - Description $items['project_settings/information'] = array( 'title' => 'Information', 'page callback' => 'origo_home_project_information_page', 'access callback' => 'user_access', 'access arguments' => array('origo project settings'), 'weight' => -6, 'type' => MENU_LOCAL_TASK, ); // Project settings for owners - Logo $items['project_settings/logo'] = array( 'title' => 'Logo', 'page callback' => 'origo_home_project_settings_logo_page', 'access callback' => 'user_access', 'access arguments' => array('origo project settings'), 'weight' => -4, 'type' => MENU_LOCAL_TASK, ); // Project settings for owners - Navigation $items['project_settings/navigation'] = array( 'file' => 'origo_home_project_settings.inc', 'title' => 'Navigation', 'page callback' => 'drupal_get_form', 'page arguments' => array('origo_home_project_settings_navigation_form'), 'access callback' => 'user_access', 'access arguments' => array('origo project settings'), 'weight' => -2, 'type' => MENU_LOCAL_TASK, ); // Project settings for owners - project pretty name $items['project_settings/project_prettyname'] = array( 'title' => 'Pretty Name', 'page callback' => 'origo_home_project_settings_project_prettyname_page', 'access callback' => 'user_access', 'access arguments' => array('origo project settings'), 'weight' => -2, 'type' => MENU_LOCAL_TASK, ); // -------------------------------------------------------------------------------------- // Wiki Diff redirect $items['wiki_diff/%origo_wiki_page/%origo_revision/%origo_revision'] = array( 'title' => 'Wiki Diff', 'page callback' => 'origo_home_wiki_diff_page', 'page arguments' => array(1, 2, 3), 'access callback' => 'user_access', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); // Blog Diff redirect $items['blog_diff/%origo_username/%origo_wiki_page/%origo_revision/%origo_revision'] = array( 'title' => 'Blog Diff', 'page callback' => 'origo_home_blog_diff_page', 'page arguments' => array(1, 2, 3, 4), 'access callback' => 'user_access', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); // Send message to user $items['message/%origo_username'] = array( // Title is string with placeholder, callback not defined, so falls back to the default t() 'title' => 'Send Message to @recipient', 'title arguments' => array('@recipient' => 1), 'page callback' => 'origo_home_message_page', 'page arguments' => array(1), 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // Friends overview page $items['friends/%origo_username'] = array( // Title is string with placeholder, callback not defined, so falls back to the default t() 'title' => '@friend\'s friends', 'title arguments' => array('@friend' => 1), 'page callback' => 'origo_home_friends_page', 'page arguments' => array(1), 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // Request Friendship $items['add_friend/%origo_username'] = array( 'title' => 'Add @friend as your friend', 'title arguments' => array('@friend' => 1), 'page callback' => 'origo_home_request_friendship_page', 'page arguments' => array(1), 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // Remove Friendship $items['remove_friend/%origo_username'] = array( 'title' => 'Remove @friend from your friends', 'title arguments' => array('@friend' => 1), 'page callback' => 'origo_home_remove_friendship_page', 'page arguments' => array(1), 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // Confirm Friendship $items['confirm_friend/%origo_username'] = array( 'title' => 'Confirm Friendship Request', 'page callback' => 'origo_home_confirm_friendship_page', 'page arguments' => array(1), 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // -------------------------------------------------------------------------------------- // List all communities $items['communities'] = array( 'title' => 'Origo - Communities', 'page callback' => 'origo_home_communities_page', 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // Community Main Page $items['communities/%origo_community_name'] = array( // Title is string with placeholder, callback not defined, so falls back to the default t() 'title' => '!community_name Community', 'title arguments' => array('!community_name' => 1), 'page callback' => 'origo_home_community_main_page', 'page arguments' => array(1), 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // Join a communtiy $items['communities/%origo_community_name/join'] = array( 'page callback' => 'origo_home_community_join', 'page arguments' => array(1), 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // Leave a community $items['communities/%origo_community_name/leave'] = array( 'page callback' => 'origo_home_community_leave', 'page arguments' => array(1), 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // Delete a community $items['communities/%origo_community_name/delete'] = array( 'page callback' => 'origo_home_community_delete_page', 'page arguments' => array(1), 'access callback' => 'user_access', 'access arguments' => array('origo admin access'), 'type' => MENU_CALLBACK, ); // Promote a member to admin $items['communities/%origo_community_name/promote/%origo_username'] = array( 'page callback' => 'origo_home_community_promote', 'page arguments' => array(1, 3), 'access callback' => 'origo_home_community_admin_access', 'access arguments' => array(1), 'type' => MENU_CALLBACK, ); // Demote an admin to member $items['communities/%origo_community_name/demote/%origo_username'] = array( 'page callback' => 'origo_home_community_demote', 'page arguments' => array(1, 3), 'access callback' => 'origo_home_community_admin_access', 'access arguments' => array(1), 'type' => MENU_CALLBACK, ); // Add a project to a community $items['communities/%origo_community_name/add_project'] = array( 'page callback' => 'origo_home_community_add_project_page', 'page arguments' => array(1), 'access callback' => 'origo_home_community_admin_access', 'access arguments' => array(1), 'type' => MENU_CALLBACK, ); // Remove a project from a community $items['communities/%origo_community_name/remove_project/%origo_project_name'] = array( 'page callback' => 'origo_home_community_remove_project', 'page arguments' => array(1, 3), 'access callback' => 'origo_home_community_admin_access', 'access arguments' => array(1), 'type' => MENU_CALLBACK, ); // Change community description $items['communities/%origo_community_name/change_description'] = array( 'page callback' => 'origo_home_community_change_description_page', 'page arguments' => array(1), 'access callback' => 'origo_home_community_admin_access', 'access arguments' => array(1), 'type' => MENU_CALLBACK, ); // List all wiki pages of a community $items['communities/%origo_community_name/wiki'] = array( 'title' => 'Wiki Pages', 'page callback' => 'origo_home_community_list_wiki_page', 'page arguments' => array(1), 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // Display a wiki page $items['communities/%origo_community_name/wiki/%origo_wiki_page'] = array( // Title is string with placeholder, callback not defined, so falls back to the default t() 'title' => '@wikipage_name', 'title arguments' => array('@wikipage_name' => 3), 'page callback' => 'origo_home_community_show_wiki_page', 'page arguments' => array(1, 3), 'access callback' => 'origo_home_existing_user_access', 'type' => MENU_CALLBACK, ); // Display a wiki page $items['communities/%origo_community_name/wiki/%origo_wiki_page/view'] = array( 'title' => 'View', 'page callback' => 'origo_home_community_show_wiki_page', 'page arguments' => array(1, 3), 'access callback' => 'origo_home_community_member_access', 'access arguments' => array(1), 'type' => MENU_DEFAULT_LOCAL_TASK, ); // Edit a wiki page $items['communities/%origo_community_name/wiki/%origo_wiki_page/edit'] = array( 'title' => 'Edit', 'page callback' => 'origo_home_community_edit_wiki_page', 'page arguments' => array(1, 3), 'access callback' => 'origo_home_community_member_access', 'access arguments' => array(1), 'weight' => 2, 'type' => MENU_LOCAL_TASK, ); // Add a wiki page $items['communities/%origo_community_name/wiki/add'] = array( 'title' => 'Edit', 'page callback' => 'origo_home_community_add_wiki_page', 'page arguments' => array(1), 'access callback' => 'origo_home_community_member_access', 'access arguments' => array(1), 'type' => MENU_CALLBACK, ); // Delete a wiki page $items['communities/%origo_community_name/wiki/%origo_wiki_page/delete'] = array( 'title' => 'Delete', 'page callback' => 'origo_home_community_delete_wiki_page', 'page arguments' => array(1, 3), 'access callback' => 'origo_home_community_admin_access', 'access arguments' => array(1), 'type' => MENU_CALLBACK, ); return $items; } /** * Redirect to workitem and mark as read * * @param $workitem_id workitem id */ function origo_home_workitem_page($workitem_id) { origo_auth_xmlrpc_session(variable_get('origo_api', ''), 'workitem.set_read_status', (int)$workitem_id, TRUE); drupal_goto(base64_decode($_GET['target'])); } /** * Add bookmark to project * * @param $project_id Project id */ function origo_home_bookmark_add($project_id) { //add bookmark $project = origo_auth_xmlrpc_session(variable_get('origo_api', ''), 'user.add_bookmark', (int)$project_id); drupal_goto('origo_home/settings/bookmarks'); } /** * Remove bookmark to project * * @param $project_id Project id */ function origo_home_bookmark_remove($project_id) { //remove bookmark $project = origo_auth_xmlrpc_session(variable_get('origo_api', ''), 'user.remove_bookmark', (int)$project_id); drupal_goto('origo_home/settings/bookmarks'); } /** * Redirects to global search page * */ function origo_home_global_search_page() { drupal_goto('search/google'); } /** * Redirects to the node diff page * * @param $page name of the wiki page * @param $old_revision old revision * @param $revision new revision */ function origo_home_wiki_diff_page($page, $old_revision, $revision) { $result = db_query("SELECT src FROM {url_alias} WHERE LOWER(dst) = LOWER('%s')", 'wiki/'. $page); $found_nodes = array(); while ($node = db_fetch_object($result)) { $found_nodes[] = $node; } if (count($found_nodes) == 1) { drupal_goto($found_nodes[0]->src .'/revisions/view/'. $old_revision .'/'. $revision); } } /** * Redirects to the node diff page * * @param $user name of the blog user * @param $page name of the blog page * @param $old_revision old revision * @param $revision new revision */ function origo_home_blog_diff_page($user, $page, $old_revision, $revision) { $result = db_query("SELECT src FROM {url_alias} WHERE LOWER(dst) = LOWER('%s')", 'blog/'. $user .'/'. $page); $found_nodes = array(); while ($node = db_fetch_object($result)) { $found_nodes[] = $node; } if (count($found_nodes) == 1) { drupal_goto($found_nodes[0]->src .'/revisions/view/'. $old_revision .'/'. $revision); } } /** * Create form to add users to a project * * @param $project_id id of project * @param $admin_mode was project settings page in admin mode */ function origo_home_project_user_add_form(&$form_state, $project_id, $admin_mode = FALSE) { $form['project_id'] = array('#type' => 'value', '#value' => $project_id); $form['admin_mode'] = array('#type' => 'value', '#value' => $admin_mode); $form['username'] = array( '#type' => 'textfield', '#title' => t('Username'), '#size' => 60, '#maxlength' => 64, '#description' => NULL, '#attributes' => NULL, '#required' => TRUE, ); $options = array('4' => t('Project Member'), '3' => t('Project Owner')); // the indices are the back-end's group_id's for these roles. $form['type'] = array( '#type' => 'radios', '#title' => t('Type'), '#default_value' => 1, '#options' => $options, '#description' => NULL, '#attributes' => NULL, '#required' => TRUE, ); // optional field for Drupal roles that differ from the back-end. $form['drupal_role'] = array( '#type' => 'hidden', '#value' => NULL, ); $form['submit'] = array( '#type' => 'submit', '#value' => t('Apply changes') ); return $form; } /* Validate that you aren't removing yourself as admin when you add yourself as member if there's just one admin. */ function origo_home_project_user_add_form_validate($form, &$form_state) { // Create Structure $values = array(); $values["stakeholders"] = array(); $values["project_id"] = variable_get('origo_project_id', 0); // Get owners $values["stakeholders"]["owners"] = origo_auth_xmlrpc_session(variable_get('origo_api', ''), 'project.members', (int)$values["project_id"], 3); // Check for Error && Check if there is just one owner && if userToAdd is equal the owner if ((int)xmlrpc_errno() > 0) { drupal_set_message(xmlrpc_error_msg()); } else { $messages = form_get_errors(); if (count($values['stakeholders']['owners']) == 1 ) { $usernameOwner = current($values['stakeholders']['owners']); $usertoAdd = $form_state['values']['username']; if ($usernameOwner['name'] === $usertoAdd && !isset($messages['type'])) { drupal_goto('project_settings/confirm/' . $form_state['values']['project_id'] . '/' . $form_state['values']['type'] . '/' . $form_state['values']['username']); } } } } /** * Create the confirm form. */ function origo_home_project_change_group_confirm_form($form_state, $pid, $gid, $username) { // Write values which are needed in confirm_form_submit in the storage. $form = array(); $form_state['storage']['project_id'] = (int) $pid; $form_state['storage']['group_id'] = (int) $gid; $form_state['storage']['username'] = $username; $form_state['storage']['drupal_role'] = (int) $gid; // Create array with form information. It gets built from drupal_get_form from the menu callback. return confirm_form($form, t('Are you sure you want to remove the last Owner?'), 'project_settings', t('This will remove the last Owner of the Project.'), t('I\'m sure'), t('Cancel')); } /** * Submit the changes which I accepted in the confirm form. */ function origo_home_project_change_group_confirm_form_submit($form, $form_state) { if (user_access('origo project settings')) { // Import global $user variable global $user; $group_id = (int) $form_state['storage']['group_id']; // Origo API Call to change group of user origo_auth_xmlrpc_session(variable_get('origo_api', ''), 'project.change_group', (int) ($form_state['storage']['project_id']), $form_state['storage']['username'], (int) $group_id); if ((int) xmlrpc_errno() > 0) { form_set_error('username', t(xmlrpc_error_msg())); } else { drupal_set_message(t('User ' . $form_state['storage']['username'] . ' has been added.')); // if the field 'drupal_role' was set, use it for assigning the front-end's user-role (should client group be showed?) if (isset($form_state['storage']['drupal_role']) && $form_state['storage']['drupal_role'] > 0) { // higher priority for form_value '#drupal_role', if it is set. $group_id = (int) $form_state['storage']['drupal_role']; } // make user role change instant // only assign 'owner' or 'developer' if user is not admin $user = user_load(array('name' => $form_state['storage']['username'])); if (!array_key_exists(5, $user->roles)) { // remove previous owner or member status unset($user->roles['4']); unset($user->roles['3']); // add the new status $user->roles[group_id] = TRUE; user_save($user, array('roles' => $user->roles)); } // the cache has to be cleared db_query("TRUNCATE TABLE {cache_menu}"); } drupal_goto('project_settings'); } } /** * Submit form handler to add user to a project */ function origo_home_project_user_add_form_submit($form, &$form_state) { if (user_access('origo project settings')) { global $user; $group_id = (int)$form_state['values']['type']; // Origo API call to change group of user origo_auth_xmlrpc_session(variable_get('origo_api', ''), 'project.change_group', (int)($form_state['values']['project_id']), $form_state['values']['username'], (int)$group_id); if ((int)xmlrpc_errno() > 0) { form_set_error('username', t(xmlrpc_error_msg())); } else { drupal_set_message(t('User '. $form_state['values']['username'] .' has been added.')); // if the field 'drupal_role' was set, use it for assigning the front-end's user role. if (isset($form_state['values']['drupal_role']) && $form_state['values']['drupal_role'] > 0) { // higher priority for form value '#drupal_role', if it is set. $group_id = (int)$form_state['values']['drupal_role']; } // make user role change instant // only assign 'owner' or 'developer' if user is not admin $user = user_load(array('name' => $form_state['values']['username'])); if (!array_key_exists(5, $user->roles)) { // remove previous 'owner' or 'member' status unset($user->roles['4']); unset($user->roles['3']); // add the new status $user->roles[$group_id] = TRUE; user_save($user, array('roles' => $user->roles)); } // the cache has to be cleared db_query("TRUNCATE TABLE {cache_menu}"); } if ($form_state['values']['admin_mode']) { drupal_goto('origo_admin/project/'. $form_state['values']['project_id']); } else { drupal_goto('project_settings'); } } } /** * Encrypt auth data for feed urls. * @param $auth an array with name and user. * @return the encoded auth data. */ function _encrypt($auth) { $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB); $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); $enc = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, variable_get('origo_feed_key', ''), serialize($auth), MCRYPT_MODE_ECB, $iv); $enc = strtr(base64_encode($enc), '+/', '-_'); return $enc; } /** * gets a list with all subscribed projects of the specified users. the list contains * all projects the user participates as member or owner and then all bookmarked projects * (both sorted per se in alphabetically ascending order). projects in which the user * participates AND has a bookmark will only be listed once in the list of participating * projects. * * @param string $username username * @return array[struct['id'=>project id, 'name'=>project name]] */ function _getSubscribedProjectsList($username) { $projects_own = array(); $projects_bookmarked = array(); // get own projects $own_projects = origo_auth_xmlrpc_session(variable_get('origo_api', ''), 'project.list_of_user', $username); if ((int)xmlrpc_errno() == 0) { foreach ($own_projects as $project) { $new_project['id'] = $project['project_id']; $new_project['name'] = $project['project_name']; $projects_own[$new_project['name']] = $new_project; } } ksort($projects_own); // get bookmarked projects $bookmarked_projects = origo_auth_xmlrpc_session(variable_get('origo_api', ''), 'user.list_bookmark', $username); if ((int)xmlrpc_errno() == 0) { foreach ($bookmarked_projects as $project) { $new_project['id'] = $project['project_id']; $new_project['name'] = $project['name']; if (!array_key_exists($new_project['name'], $projects_own)) { $projects_bookmarked[$new_project['name']] = $new_project; } } } ksort($projects_bookmarked); return array_merge($projects_own, $projects_bookmarked); } /** * Show form to create a new project */ function origo_home_create_project_page() { $output = ''; $output .= 'To request a new project on Origo use the following form.
'; $output .= 'Please note that project creation is done manually by an administrator. You will be informed as soon as your project is ready.

'; $output .= 'If you would like to migrate your data from an existing SVN/CVS into Origo please write so into the message field below and we will assist you with the migration.'; $output .= drupal_get_form('origo_home_create_project_form'); return $output; } /** * Create Origo create project form */ function origo_home_create_project_form(&$form_state) { $form['projectname'] = array( '#type' => 'textfield', '#title' => t('Project Name (no spaces, only a-z, 0-9 and - are allowed. Must start with a letter, end in letter or digit. Max. 50 characters.)'), '#size' => 60, '#maxlength' => 50, '#description' => t('This name will also be your URL:') .' '. get_origo_project_link('projectname') .'
'. t('Normally project names shouldn\'t be longer than 15-20 characters (the maximum is 50 characters).'), '#attributes' => NULL, '#required' => TRUE, ); $form['description'] = array( '#type' => 'textarea', '#title' => t('Short description of your project'), '#cols' => 60, '#rows' => 10, '#description' => t('Please write your description in either english or german.'), '#attributes' => NULL, '#required' => TRUE, ); $form['type'] = array( '#type' => 'radios', '#title' => t('Project Type'), '#default_value' => ORIGO_OPEN_SOURCE, '#options' => array( ORIGO_OPEN_SOURCE => t('Open Source'), ORIGO_CLOSED_SOURCE => t('Closed Source') ), '#description' => NULL, '#attributes' => NULL, '#required' => TRUE, '#prefix' => origo_home_access_matrix(), ); $form['rcs_type'] = array( '#type' => 'radios', '#title' => t('Repository Type'), '#default_value' => ORIGO_REPO_SVN, '#options' => array( ORIGO_REPO_SVN => t('Subversion'), ), '#description' => NULL, '#attributes' => NULL, '#required' => TRUE, ); $form['visibility'] = array( '#type' => 'radios', '#title' => t('Project Listing Visibility'), '#default_value' => ORIGO_PROJECT_VISIBLE, '#options' => array( ORIGO_PROJECT_VISIBLE => t('Visible (the project will be publically visible)'), ORIGO_PROJECT_HIDDEN => t('Not Visible (the project is only visible if people know the project url)')), '#description' => NULL, '#attributes' => NULL, '#required' => TRUE, ); $form['message'] = array( '#prefix' => "
", '#type' => 'textarea', '#title' => t('Message for the Origo team'), '#cols' => 60, '#rows' => 5, '#description' => t('Please write your message in either english or german.'), '#attributes' => NULL, '#required' => FALSE, ); $form['submit'] = array( '#type' => 'submit', '#value' => t('Send request') ); return $form; } /** * See common.inc -> drupal_mail() for more info. this is just a rewrite with additional parameters * for setting the envolope-from parameter. * * $additional_parameters should be set to '-f sendermail@origo.ethz.ch', matching the from mail address */ function origo_mail($mailkey, $to, $subject, $body, $from = NULL, $headers = array(), $additional_parameters = NULL) { $defaults = array( 'MIME-Version' => '1.0', 'Content-Type' => 'text/plain; charset=UTF-8; format=flowed', 'Content-Transfer-Encoding' => '8Bit', 'X-Mailer' => 'Drupal' ); // To prevent e-mail from looking like spam, the addresses in the Sender and // Return-Path headers should have a domain authorized to use the originating // SMTP server. Errors-To is redundant, but shouldn't hurt. $default_from = variable_get('site_mail', ini_get('sendmail_from')); if ($default_from) { $defaults['From'] = $defaults['Reply-To'] = $defaults['Sender'] = $defaults['Return-Path'] = $defaults['Errors-To'] = $default_from; } if ($from) { $defaults['From'] = $defaults['Reply-To'] = $from; } $headers = array_merge($defaults, $headers); // Custom hook traversal to allow pass by reference foreach (module_implements('mail_alter') AS $module) { $function = $module .'_mail_alter'; $function($mailkey, $to, $subject, $body, $from, $headers); } // Allow for custom mail backend if (variable_get('smtp_library', '') && file_exists(variable_get('smtp_library', ''))) { include_once './'. variable_get('smtp_library', ''); return drupal_mail_wrapper($mailkey, $to, $subject, $body, $from, $headers); } else { // Note: see comments in common.inc -> drupal_mail() $mimeheaders = array(); foreach ($headers as $name => $value) { $mimeheaders[] = $name .': '. mime_header_encode($value); } if ($additional_parameters === NULL) { return mail( $to, mime_header_encode($subject), str_replace("\r", '', $body), join("\n", $mimeheaders) ); } else { return mail( $to, mime_header_encode($subject), str_replace("\r", '', $body), join("\n", $mimeheaders), $additional_parameters ); } } } /** * Handler to validate input to create project form */ function origo_home_create_project_form_validate($form, &$form_state) { // allow only names with a-z, 0-9 and a - (but not at the beginning and end) if (!preg_match('/^([a-z])([a-z]|[0-9]|\-){1,48}([a-z]|[0-9])$/', $form_state['values']['projectname'])) { form_set_error('projectname', t('Your project name is not valid')); } } /** * Submit handler for create project form */ function origo_home_create_project_form_submit($form, &$form_state) { global $user; //add request $project_type = (int)$form_state['values']['type']; $rcs_type = (int)$form_state['values']['rcs_type']; $project_visibility = $form_state['values']['visibility']; $result = origo_auth_xmlrpc_session(variable_get('origo_api', ''), 'project.request_add', $form_state['values']['projectname'], $form_state['values']['description'], (int)$project_type, $rcs_type, (int)$project_visibility, $form_state['values']['message']); if ((int)xmlrpc_errno() > 0) { form_set_error('projectname', t(xmlrpc_error_msg())); } else { // Prepare the sender: $from = origo_auth_xmlrpc_session(variable_get('origo_api', ''), 'user.my_email'); $message[] = 'User: '. $user->name .' ('. $from .')'; $message[] = ''; $message[] = 'Project: '. $form_state['values']['projectname']; $message[] = ''; $message[] = 'Description:'; $message[] = _origo_home_plain_text($form_state['values']['description']); $message[] = ''; if ($form_state['values']['type'] == ORIGO_OPEN_SOURCE) { $message[] = 'Type: Open Source'; } elseif ($form_state['values']['type'] == ORIGO_CLOSED_SOURCE) { $message[] = 'Type: Closed Source'; } elseif ($form_state['values']['type'] == ORIGO_PRIVATE_PROJECT) { $message[] = 'Type: Private Project'; } else { // Fallback: use verbatim number $message[] = 'Type: '. $form_state['values']['type']; } $message[] = ''; if ($form_state['values']['rcs_type'] == ORIGO_REPO_SVN) { $message[] = 'RCS: Subversion'; } elseif ($form_state['values']['rcs_type'] == ORIGO_REPO_GIT) { $message[] = 'RCS: Git'; } $message[] = ''; if ($form_state['values']['visibility'] == ORIGO_PROJECT_HIDDEN) { $message[] = 'Visibility: Hidden'; } elseif ($form_state['values']['visibility'] == ORIGO_PROJECT_VISIBLE) { $message[] = 'Visibility: Visible'; } $message[] = ''; $message[] = 'Message:'; $message[] = _origo_home_plain_text($form_state['values']['message']); $message[] = ''; $message[] = 'Link: '. get_origo_project_link() .'/origo_admin/create_project/'. $form_state['values']['projectname']; // Tidy up the body: foreach ($message as $key => $value) { $message[$key] = wordwrap($value); } // Prepare the body: $body = implode("\r\n", $message); $subject = "Origo - Project Request \"{$form_state['values']['projectname']}\""; $to = '<'. variable_get('origo_support_email', '') .'>'; // Send the e-mail to the recipients: origo_mail('createproject', $to, $subject, $body, $from, array(), '-f '. variable_get('origo_support_email', '')); drupal_set_message(t('Your request has been sent. An administrator will inform you as soon as your project is ready')); drupal_goto(); } } /** * Show form to request application key */ function origo_home_request_appkey_page() { $output = ''; $output .= 'If you want to access Origo from within your own application using the API you will need an application key.
'; $output .= 'Please fill out a form to request an application key.
'; $output .= 'You will be informed as soon as your application key is ready.'; $output .= drupal_get_form('origo_home_request_appkey_form'); return $output; } /** * Create Origo request application key form */ function origo_home_request_appkey_form(&$form_state) { $form['projectname'] = array( '#type' => 'textfield', '#title' => t('Application Name'), '#size' => 60, '#maxlength' => 64, '#description' => NULL, '#attributes' => NULL, '#required' => TRUE, ); $form['description'] = array( '#type' => 'textarea', '#title' => t('Short description of your application'), '#cols' => 60, '#rows' => 10, '#description' => NULL, '#attributes' => NULL, '#required' => TRUE, ); $form['message'] = array( '#type' => 'textarea', '#title' => t('Message for the Origo team'), '#cols' => 60, '#rows' => 5, '#description' => NULL, '#attributes' => NULL, '#required' => FALSE, ); $form['submit'] = array( '#type' => 'submit', '#value' => t('Send request') ); return $form; } /** * Handler to validate input to request application key form * TODO: delete this, or fill with some buisness logic - bherlig, 2009-03-23 */ function origo_home_request_appkey_form_validate($form, &$form_state) { } /** * Submit handler for request application key form */ function origo_home_request_appkey_form_submit($form, &$form_state) { global $user; // Prepare the sender: $from = origo_auth_xmlrpc_session(variable_get('origo_api', ''), 'user.my_email'); $message[] = 'User: '. $user->name; $message[] = ''; $message[] = 'Application: '. $form_state['values']['projectname']; $message[] = ''; $message[] = 'Description:'; $message[] = _origo_home_plain_text($form_state['values']['description']); $message[] = ''; $message[] = 'Message:'; $message[] = _origo_home_plain_text($form_state['values']['message']); // Tidy up the body: foreach ($message as $key => $value) { $message[$key] = wordwrap($value); } // Prepare the body: $body = implode("\r\n", $message); $subject = 'Origo - Request Application Key'; $to = '<'. variable_get('origo_support_email', '') .'>'; // Send the e-mail to the recipients: origo_mail('appkeyrequest', $to, $subject, $body, $from, array(), '-f '. variable_get('origo_support_email', '')); drupal_set_message(t('Your request has been sent. An administrator will inform you as soon as your application key is ready')); drupal_goto(); } /** * Strips tags and makes entities readable */ function _origo_home_plain_text($string) { return html_entity_decode(strip_tags($string), ENT_QUOTES); } /** * Validate that a confirm form is shown if removing the last owner. */ function origo_home_project_settings_members_remove_validate($username, $pid) { // Create Structure $values = array(); $values["stakeholders"] = array(); $values["project_id"] = $pid; // Get owners $values["stakeholders"]["owners"] = origo_auth_xmlrpc_session(variable_get('origo_api', ''), 'project.members', (int)$values["project_id"], 3); // Check for Error && Check if there is just one owner && if userToAdd is equal the owner if ((int)xmlrpc_errno() > 0) { drupal_set_message(xmlrpc_error_msg()); } else { if (count($values['stakeholders']['owners']) == 1 && $values['stakeholders']['owners']['0']['name'] === $username) { drupal_goto('project_settings/confirm/' . (int) $pid . '/' . $username); } else { origo_home_project_settings_members_remove($username, $pid); } } } /** * Create the confirm form. */ function origo_home_project_settings_members_remove_confirm_form($form_state, $pid, $username) { // Write values which are needed in confirm_form_submit to the storage. $form = array(); $form_state['storage']['project_id'] = (int) $pid; $form_state['storage']['username'] = $username; // Create array with form information. It gets built from drupal_get_form from the menu callback. return confirm_form($form, t('Are you sure you want to remove the last Owner?'), 'project_settings', t('This will remove the last Owner of the Project.'), t('I\'m sure'), t('Cancel')); } /** * Submit the changes (remove) which I accepted in the confirm form. */ function origo_home_project_settings_members_remove_confirm_form_submit($form, $form_state) { $username = $form_state['storage']['username']; $pid = $form_state['storage']['project_id']; // Make API Call and Check for errors. If no errors perform remove action. origo_auth_xmlrpc_session(variable_get('origo_api', ''), 'project.change_group', (int) $pid, $username, 0); if ((int) xmlrpc_errno() > 0) { form_set_error('username', t(xmlrpc_error_msg())); } else { drupal_set_message(t("User $username has been removed")); // Make remove of user effective // Note: if `user_load' fails, the user was never logged into the project, // and thus has no entry in it's `users` table. A call to user_save would then fail. $user = user_load(array("name" => $username)); if (isset($user) && $user != FALSE) { unset($user->roles['4']); unset($user->roles['3']); user_save($user, array("roles" => $user->roles)); } } drupal_goto('project_settings'); } /** * Project settings page. * Displays an overview of a project's stakeholders (owners, members, bookmarkers), * associated communities, etc. * Project owners will be provided with a form to manipulate the project's members. */ function origo_home_project_settings_members_page() { $values = array(); $output = ""; // holds possible xmlrpc error-messages // basic data $values["project_id"] = variable_get('origo_project_id', 0); $values["admin_mode"] = FALSE; $values["stakeholders"] = array(); // All members of the array 'stakeholders' will be processed/displayed (by the // corresponding theme function) in the same way. // - Each entry's key-name will be a heading // - Each stakeholder-member will be displayed with an icon provided by the // special key "$values[ENTRY_KEY . '_icon']" // owners $values["stakeholders"]["owners"] = origo_auth_xmlrpc_session(variable_get('origo_api', ''), 'project.members', (int)$values["project_id"], 3); $values["owners_icon"] = "user_o.png"; if ((int)xmlrpc_errno() > 0) { $output .= xmlrpc_error_msg(); } // members $values["stakeholders"]["members"] = origo_auth_xmlrpc_session(variable_get('origo_api', ''), 'project.members', (int)$values["project_id"], 4); $values["members_icon"] = "user_m.png"; if ((int)xmlrpc_errno() > 0) { $output .= xmlrpc_error_msg(); } // bookmarkers $values["stakeholders"]["bookmarkers"] = origo_auth_xmlrpc_session(variable_get('origo_api', ''), 'project.list_bookmarkers', (int)$values["project_id"]); $values["bookmarkers_icon"] = "user_bookmarker.png"; if ((int)xmlrpc_errno() > 0) { $output .= xmlrpc_error_msg(); } // communities $values["communities"] = origo_auth_xmlrpc_session(variable_get('origo_api', ''), 'project.list_communities', (int)$values["project_id"]); if ((int)xmlrpc_errno() > 0) { $output .= xmlrpc_error_msg(); } // invoke (custom) hooks // NOTE: `module_invoke_all' does not support passing values by reference, // we thus have to use the return values. $ret_val = module_invoke_all('origo_project_members', $values); if (isset($ret_val) && sizeof($ret_val) > 0) { $values = $ret_val; } // theme list & render $person_list = theme('origo_home_project_settings_members_page', $values); $add_person_form = ""; if (user_access('origo project settings')) { $add_person_form .= "

"; $add_person_form .= '

Add project staff

'; $add_person_form .= drupal_get_form('origo_home_project_user_add_form', (int)$values["project_id"], $admin_mode); } $access_matrix = origo_home_access_matrix(); return "
". $output . $access_matrix . $person_list . $add_person_form ."
"; } function theme_origo_home_project_settings_members_page(&$values) { $output = "
\n"; $image_path = drupal_get_path('module', 'origo_home') .'/img/'; // process all the project's stakeholders foreach ($values["stakeholders"] as $sh_name => $stakeholder) { $output .= '

Project '. drupal_ucfirst($sh_name) .'

'; if (sizeof($stakeholder) == 0) { $output .= t('None'); } else { sort($stakeholder); foreach ($stakeholder as $usr) { $output .= l('', 'users/'. $usr['name'], array('html' => TRUE)); $output .= ' '; $output .= l($usr['name'], 'users/'. $usr['name']); if (user_access('origo project settings') && $sh_name !== "bookmarkers") { $output .= l('[remove]', 'project_settings/members/remove/'. $usr['name'] .'/'. (int)$values["project_id"], array('attributes' => array('style' => 'margin-left:20px'))); } $output .= '
'; } } } // process communities $output .= '

Associated Communities

'; if (sizeof($values["communities"]) == 0) { $output .= t('None'); } else { sort($values["communities"]); foreach ($values["communities"] as $community) { $output .= l($community['name'], 'communities/'. $community['name']); $output .= '
'; } } $outpu .= "
\n"; return $output; } /** * Remove specified user from specified project (for project owners) * * @param $username user to remove * @param $project_id project */ function origo_home_project_settings_members_remove($username, $project_id) { origo_auth_xmlrpc_session(variable_get('origo_api', ''), 'project.change_group', (int)$project_id, $username, 0); if ((int)xmlrpc_errno() > 0) { form_set_error('username', t(xmlrpc_error_msg())); } else { drupal_set_message(t("User $username has been removed.")); // Make user role change instantly effective. // Removing an admin from the project won't have an effect // Note: if `user_load' fails, the user was never logged into the project, // and thus has no entry in it's `users` table. A call to user_save would then fail. $user = user_load(array("name" => $username)); if (isset($user) && $user != FALSE) { unset($user->roles['4']); unset($user->roles['3']); user_save($user, array("roles" => $user->roles)); } } drupal_goto('project_settings'); } /** * Show project settings - description page */ function origo_home_project_information_page() { module_load_include('inc', 'origo_home', 'origo_project_information'); $output = drupal_get_form('origo_home_project_information_form'); return $output; } /** * Show project settings - logo page */ function origo_home_project_settings_logo_page() { $output = t('Set new project logo or restore the original Origo logo.
'); $output .= drupal_get_form('origo_home_project_settings_logo_form'); return $output; } function origo_home_project_settings_logo_form(&$form_state) { $form['#attributes'] = array('enctype' => "multipart/form-data"); $form['upload'] = array( '#title' => t('New Project Logo'), '#type' => 'file', '#description' => t('Don\'t use spaces in the filename. The logo will be reduced to a max size of 100x100px. Max. allowed filesize: 2 MB.'), ); $form['submit'] = array( '#type' => 'submit', '#value' => t('Save'), ); $form['restore'] = array( '#type' => 'submit', '#value' => t('Restore'), ); return $form; } function origo_home_project_settings_logo_form_submit($form, &$form_state) { if ($form_state['values']['op'] == t('Save')) { $validators = array( 'file_validate_is_image' => array(), 'file_validate_size' => array(2097152) // 2MB ); $result = file_save_upload('upload', $validators, file_directory_path(), FALSE); if ($result == 0) { form_set_error('upload', t('Invalid file')); } else { file_set_status($result, FILE_STATUS_PERMANENT); $settings = variable_get('theme_settings', ''); $settings['default_logo'] = 0; //remove the old logo if necessary if ($settings['logo_path'] != "" && $settings['logo_path'] != $result->filepath) { file_delete($settings['logo_path']); } $settings['logo_path'] = $result->filepath; //resize the project logo to max 100x100px using the image-module image_scale($result->filepath, $result->filepath, 100, 100); variable_set('theme_settings', $settings); origo_auth_xmlrpc_session(variable_get('origo_api', ''), 'project.change_logo', (int)variable_get('origo_project_id', 0), $result->filename); if ((int)xmlrpc_errno() > 0) { form_set_error('upload', t(xmlrpc_error_msg())); } else { drupal_set_message(t('Logo saved. You may have to clear your browser cache.')); } } } else { // restore the original logo $settings = variable_get('theme_settings', ''); $settings['default_logo'] = 1; //remove the old logo if necessary if ($settings['logo_path'] != "" && is_file($settings['logo_path'])) { unlink($settings['logo_path']); } variable_set('theme_settings', $settings); origo_auth_xmlrpc_session(variable_get('origo_api', ''), 'project.change_logo', (int)variable_get('origo_project_id', 0), 'no'); if ((int)xmlrpc_errno() > 0) { drupal_set_message(t('The following error occured: '. xmlrpc_error_msg()), 'error'); } else { drupal_set_message(t('Logo restored. You may have to clear your browser cache.')); } } } /** * Implementation of hook_nodeapi(). * Used to: * - catch insert and update events to create workitems for wiki and blog * - add static information to specific pages */ function origo_home_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) { if ($node->nid == 4 && $op == 'alter') { if (isset($node->body)) { $projectname = drupal_strtolower(variable_get('origo_project_name', '')); $repositories = array( 'Subversion' => array( 'links' => array( 'Path' => l(variable_get('origo_svn_url', '') .'/'. $projectname .'/', variable_get('origo_svn_url', '') .'/'. $projectname .'/'), ), ), ); // Add web svn link, if configured if (variable_get('origo_websvn_url', '')) { $repositories['Subversion']['links']['Web SVN'] = l(variable_get('origo_websvn_url', '') . $projectname .'/', variable_get('origo_websvn_url', '') . $projectname .'/'); } // Add viewvc link if configured if (variable_get('origo_viewvc_url', '')) { $repositories['Subversion']['links']['ViewVC'] = l(variable_get('origo_viewvc_url', '') . $projectname .'/', variable_get('origo_viewvc_url', '') . $projectname .'/'); } // Add dump link if configured if (variable_get('origo_svn_dump_url', '')) { $repositories['Subversion']['links']['Nightly SVN Dump'] = l(variable_get('origo_svn_dump_url', '') . $projectname .'/latest.tar.gz', variable_get('origo_svn_dump_url', '') . $projectname .'/latest.tar.gz'); } // invoke (custom) hooks // NOTE: `module_invoke_all' does not support passing values by reference, // we thus have to use the return values. $ret_val = origo_home_invoke_hook('origo_home_repository_links', $repositories); if (isset($ret_val) && sizeof($ret_val) > 0) { $repositories = $ret_val; } $node->body = theme('origo_home_repository_links', $repositories) . $node->body; } } elseif ($node->nid == 5 && $op == 'view') { if ($node->title == "Origo") { // Display statistics on Origo main page $project_stats = origo_auth_xml_rpc(variable_get('origo_api_internal', ''), 'internal_project.retrieve_statistics'); if ($project_stats === FALSE) { $node->content['body']['#value'] = '
Origo is currently experiencing technical difficulties, please try again later.
Error: '. xmlrpc_error_msg() .'
'. $node->content['body']['#value']; } else { // append recent projects $node->content['body']['#value'] .= '
Origo is currently hosting '. $project_stats['project_count'] ." projects of which ". $project_stats['open_source_count'] .' are open source
'; $node->content['body']['#value'] .= '
Bored? Check out the recently created projects: '; $recent_projects = split(",", $project_stats['recent_projects']); foreach ($recent_projects as $recent_project) { $node->content['body']['#value'] .= ''. $recent_project ." "; } $node->content['body']['#value'] .= '
'; } } // Add 'Bookmark' link to bottom of 'Home' page global $user; if ($user->uid > 0 && isset($node->content['body']['#value'])) { $project_id = variable_get('origo_project_id', 0); $project_name = variable_get('origo_project_name', ''); $node->content['body']['#value'] = $node->content['body']['#value'] ."

". l('[Bookmark '. $project_name .']', 'origo_home/bookmarks/add/'. $project_id); } // prepend project information, if there is any. if (variable_get('origo_home_project_information_visible', FALSE) || user_access('origo project settings')) { $project = origo_auth_xmlrpc_session(variable_get('origo_api', ''), 'project.retrieve_information', (int)variable_get('origo_project_id', 0)); if ((int)xmlrpc_errno() != 0) { drupal_set_message(t(xmlrpc_error_msg()), 'error'); } else { // clean up project information // use the same utf-8 escaping as for the DOAP file module_load_include('inc', 'origo_home', 'origo_doap'); $replacer = new unicode_replace_entities(); foreach ($project as $key => $value) { $project[$key] = _escape_for_rdf($replacer, $value); } // set the text in $info $info = '
Project Information'; if (user_access('origo project settings')) { $info_content .= '

'. l('[edit project information]', 'project_settings/information') . (!(variable_get('origo_home_project_information_visible', FALSE)) ? '
Note: The project information tab is currently hidden from visitors. ' : '') .'

'; } $info_field = array(); if ($project['category'] != '') { $info_field[] = array('Category: ', $project['category']); } if ($project['operating_system'] != '') { $info_field[] = array('Operating System: ', str_replace(',', ', ', $project['operating_system'])); } if ($project['license'] != '') { $info_field[] = array('License: ', str_replace(',', ', ', $project['license'])); } if ($project['programming_language'] != '') { $info_field[] = array('Programming Language: ', str_replace(',', ', ', $project['programming_language'])); } $info_field[] = array('Project description:', l('DOAP', 'doap')); $info_count = count($info_field); if ($project['description'] != '' && $info_count == 0) { // just project description $info_content .= '

'. str_replace(array("\r\n", "\n", "\r"), '
', $project['description']) .'

'; } elseif ($info_count > 0) { // we have project information $info_content .= ''; for ($i = 0; $i < $info_count; $i++) { if ($i == 0) { $info_content .= ''; } else { $info_content .= ''; } } $info_content .= '
'. str_replace( array("\r\n", "\n", "\r"), '
', $project['description']) .'
'. $info_field[$i][0] .''. $info_field[$i][1] .'
'. $info_field[$i][0] .''. $info_field[$i][1] .'
'; } if ($info_content != '') { $info = '
Project Information'; $info .= $info_content; $info .= '
'; drupal_add_js('misc/collapse.js'); $node->content['body']['#value'] = t($info) . $node->content['body']['#value']; } } } // add DOAP link drupal_set_html_head("\n".''); } elseif ($node->type == 'wiki') { // Act on Wikipage insert or update if ($op == 'insert') { //node information $title = $node->title; $private = (bool)$node->private; $vid = $node->vid; //Create the unified diff with PEAR Text_Diff class include_once 'Text/Diff.php'; include_once 'Text/Diff/Renderer.php'; include_once 'Text/Diff/Renderer/unified.php'; $textdiff = &new Text_Diff(array(), explode("\n", $node->body)); $renderer = &new Text_Diff_Renderer_unified(); $renderer_output = $renderer->render($textdiff); $diff = "Visibility:\n+". ($private?'Private':'Public') ."\n\n"; $title_diff = 'Title:'."\n"; $title_diff .= '+'. $node->title ."\n\n"; $diff .= $title_diff .'Content:'."\n". $renderer_output; // At this point, the pathauto-url is not created yet. // We thus have to put the node-title through the pathauto-replacement mechanism ourselves. module_load_include('inc', 'pathauto', 'pathauto'); $cleaned = pathauto_cleanstring($node->title, FALSE); $url = get_origo_project_link() . '/wiki/'. $cleaned; //add wiki workitem origo_auth_xmlrpc_session(variable_get('origo_api_internal', ''), 'internal_wiki.add', (int)variable_get('origo_project_id', 0), $title, $url, $diff, (int)$vid, (int)0, (bool)$private); } elseif ($op == 'update') { //node information $title = $node->title; $private = (bool)$node->private; $new_vid = $node->vid; // Note: `node_revision_list' is sorted by the timestamp of the nodes // See: http://api.drupal.org/api/function/node_revision_list $revisions = node_revision_list($node); // The array keys are the nids of the nodes, let's sort them krsort($revisions, $sort_descending = True); // Get the vid of the 2nd entry in the (associative) array. $rev_keys = array_keys($revisions); $old_vid = $revisions[$rev_keys[1]]->vid; // load the current and last revisions $old_node = node_load($node->nid, $old_vid); // TODO: why do we re-load the node, and not use $node directly? // bherlig, 2009-10-23 $new_node = node_load($node->nid, $new_vid); $diff = ''; //Create the unified diff with PEAR Text_Diff class include_once 'Text/Diff.php'; include_once 'Text/Diff/Renderer.php'; include_once 'Text/Diff/Renderer/unified.php'; // Process node body $textdiff = &new Text_Diff(explode("\n", $old_node->body), explode("\n", $new_node->body)); $renderer = &new Text_Diff_Renderer_unified(); $renderer_output = $renderer->render($textdiff); // Process visibility // TODO: this doesn't seem to work yet, as the "private" flag is not revisioned by drupal. Is there a way to add it?? // bherlig, 2009-10-23 if ($old_node->private != (int)$private) { $diff_visibility = "Private status: "; if ($private) { $diff_visibility .= 'wiki page only visible to project members.'; } else { $diff_visibility .= 'wiki page is now publicly available.'; } $diff_visibility .= "\n\n"; } // Process title if ($old_node->title != $new_node->title) { $title_diff = "Title:\n"; $title_diff .= '-'. $old_node->title ."\n"; $title_diff .= '+'. $new_node->title ."\n\n"; } // Process tags $old_taxonomy = array_keys($old_node->taxonomy); $new_taxonomy = array_keys($new_node->taxonomy); $tags_removed = array_diff($old_taxonomy, $new_taxonomy); // the removed terms $tags_added = array_diff($new_taxonomy, $old_taxonomy); // the newly added terms if (count($tags_removed) > 0 || count($tags_added) > 0) { // tags have changed $diff_tags = "Tags:\n"; foreach ($tags_removed as $tag) { $diff_tags .= '-'. $old_node->taxonomy[$tag]->name ."\n"; } foreach ($tags_added as $tag) { $diff_tags .= '+'. $new_node->taxonomy[$tag]->name ."\n"; } $diff_tags .= "\n\n"; } // check all differences & build diff-text to send to the backend. if (isset($title_diff)) { $diff .= $title_diff; } if (isset($diff_visibility)) { $diff .= $diff_visibility; } if (isset($diff_tags)) { $diff .= $diff_tags; } if (isset($renderer_output) && $renderer_output != '') { $diff .= "Content:\n". $renderer_output; } if ($diff == '') { // $diff is still empty -> nothing changed. must be an update involving the trash. // Note: put the moved/restored status before the log-message if ($new_node->status == STATUS_TRASH) { // STATUS_TRASH defined by Trash module. $diff = "No changes, the wiki page was moved to the trash\n\n". $diff; } else { $diff = "No changes, the wiki page was restored from the trash.\n\n". $diff; } } // process log message if (isset($new_node->log) && $new_node->log != '') { // prepend log message $diff = "Log message:\n". $new_node->log ."\n\n". $diff; } $url = get_origo_project_link() . '/'. drupal_get_path_alias($node->path); //add wiki workitem origo_auth_xmlrpc_session(variable_get('origo_api_internal', ''), 'internal_wiki.add', (int)variable_get('origo_project_id', 0), $title, $url, $diff, (int)$new_vid, (int)$old_vid, (bool)$private); } } elseif ($node->type == 'blog') { // Act on blog insert or update if ($op == 'insert') { //node information $title = $node->title; $vid = $node->vid; $private = (bool)$node->private; //Create the unified diff $body_diff = origo_home_get_diff("", $node->body); $title_diff = 'Title:'."\n"; $title_diff .= '+'. $node->title ."\n\n"; $diff = $title_diff .'Content:'."\n". $renderer_output; // At this point, the pathauto-url is not created yet. // We thus have to put the node-title through the pathauto-replacement mechanism ourselves. module_load_include('inc', 'pathauto', 'pathauto'); $cleaned = pathauto_cleanstring($node->title, FALSE); $url = get_origo_project_link() . '/blog/'. $node->name .'/'. $cleaned; //add blog workitem origo_auth_xmlrpc_session(variable_get('origo_api_internal', ''), 'internal_blog.add', (int)variable_get('origo_project_id', 0), $title, $url, $diff, (int)$vid, (int)0, (bool)$private); } elseif ($op == 'update') { // Node information $title = $node->title; $new_vid = $node->vid; $old_vid = $node->old_vid; $private = (bool)$node->private; // Create the unified diff $old_node = node_load($node->nid, $old_vid); $new_node = node_load($node->nid, $new_vid); $body_diff = origo_home_get_diff($old_node->body, $new_node->body); $title_diff = ''; if ($old_node->title != $new_node->title) { $title_diff = 'Title:'."\n"; $title_diff .= '-'. $old_node->title ."\n"; $title_diff .= '+'. $new_node->title ."\n\n"; } $diff = $title_diff .'Content:'."\n". $body_diff; $url = get_origo_project_link() . '/'. drupal_get_path_alias($node->path); // Add blog workitem origo_auth_xmlrpc_session(variable_get('origo_api_internal', ''), 'internal_blog.add', (int)variable_get('origo_project_id', 0), $title, $url, $diff, (int)$new_vid, (int)$old_vid, (bool)$private); } } elseif ($node->type == 'forum' && $op == 'insert') { // act on forum topic insert $project_id = variable_get('origo_project_id', 0); $project_name = variable_get('origo_project_name', ''); $title = $node->title; $private = (bool)$node->private; $comment = $node->body; $url = get_origo_project_link($project_name) .'/node/'. $node->nid; origo_auth_xmlrpc_session(variable_get('origo_api_internal', ''), 'internal_comment.add', (int)$project_id, $title, $comment, $url, True, 'forum', (bool)$private); if ((int)xmlrpc_errno() != 0) { form_set_error(NULL, t(xmlrpc_error_msg())); } } elseif ($node->type == 'forum' && $op == 'update') { // act on forum topic update $project_id = variable_get('origo_project_id', 0); $project_name = variable_get('origo_project_name', ''); $title = $node->title; $private = (bool)$node->private; $url = get_origo_project_link($project_name) .'/node/'. $node->nid; // Create the unified diff $old_node = node_load($node->nid, $node->old_vid); $new_node = node_load($node->nid, $node->vid); $body_diff = origo_home_get_diff($old_node->body, $new_node->body); $title_diff = ''; if ($old_node->title != $new_node->title) { $title_diff = 'Title:'."\n"; $title_diff .= '-'. $old_node->title ."\n"; $title_diff .= '+'. $new_node->title ."\n\n"; } $diff = $title_diff .'Content:'."\n". $body_diff; origo_auth_xmlrpc_session(variable_get('origo_api_internal', ''), 'internal_comment.add', (int)$project_id, $title, $diff, $url, FALSE, 'forum', (bool)$private); if ((int)xmlrpc_errno() != 0) { form_set_error(NULL, t(xmlrpc_error_msg())); } } // Act on generic updates switch ($op) { case 'insert': case 'update': origo_home_update_tagnames($node); break; } } /** * Theme function for rendering the links to a project's source code repositories. * @param unknown_type $content */ function theme_origo_home_repository_links($content) { $output = ''; if (is_array($content)) { foreach ($content as $title => $section) { if (!empty($section)) { $output .= "

$title

\n"; } if (isset($section['description'])) { $output .= t("

${section['description']}

\n"); } if (isset($section['links']) && is_array($section['links'])) { $output .= "\n"; } } } $output .= '
'; return $output; } /** * vcard redirection */ function origo_home_vcard_page($username) { module_load_include('inc', 'origo_home', 'origo_vcard'); return _origo_home_vcard_page($username); } /** * Invite friends to origo */ function origo_home_invite_friends_page() { module_load_include('inc', 'origo_home', 'origo_invite_friends'); $output .= t('

Spread the word and let all your friends know about Origo, they will receive a very brief e-mail introducing them to Origo.

'); $output .= drupal_get_form('origo_home_invite_friends_form', $username); return $output; } function origo_home_message_page($username) { $output .= drupal_get_form('origo_home_message_form', $username); return $output; } function origo_home_message_form(&$form_state, $username) { $form['recipient'] = array( '#type' => 'hidden', '#value' => $username, ); $form['subject'] = array( '#type' => 'textfield', '#title' => t('Subject'), '#size' => 60, '#maxlength' => 64, '#description' => NULL, '#attributes' => NULL, '#required' => TRUE, ); $form['message'] = array( '#type' => 'textarea', '#title' => t('Message'), '#cols' => 60, '#rows' => 10, '#description' => NULL, '#attributes' => NULL, '#required' => TRUE, ); $form['submit'] = array( '#type' => 'submit', '#value' => t('Send mail') ); return $form; } function origo_home_message_form_submit($form, &$form_state) { // Prepare the sender: $subject = html_entity_decode(strip_tags($form_state['values']['subject']), ENT_QUOTES); $message = html_entity_decode(strip_tags($form_state['values']['message']), ENT_QUOTES); $test = origo_auth_xmlrpc_session(variable_get('origo_api', ''), 'user.send_message', $form_state['values']['recipient'], $subject, $message); if ((int)xmlrpc_errno() > 0) { form_set_error('subject', t('The following error occured: '. xmlrpc_error_msg())); } else { drupal_set_message(t('Message sent.')); } } /** * Implementation of hook block to create custom menu. * * @param Operation $op * @param int $delta * @param array $edit */ function origo_home_block($op = 'list', $delta = 0, $edit = array()) { global $user; // the $op parameter determines what piece of information is being requested switch ($op) { case 'list': // return a list of block descriptions to enable drupal admin to configure behaviour and visibility $blocks[0]['info'] = t('Origo - Anonymous User'); $blocks[1]['info'] = t('Origo - User'); $blocks[2]['info'] = t('Origo - Admin'); $blocks[3]['info'] = t('Drupal - Admin'); return $blocks; case 'configure': // return an empty array because no configuration allowed in administer menu return array(); case 'save': // save is also not allowed in administer menu return; case 'view': default: // if $op is "view", then we need to generate the block for display // the $delta parameter tells us which block is being requested switch ($delta) { case 0: // The subject is displayed at the top of the block. Note that it // should be passed through t() for translation. $block['subject'] = ''; $block['content'] = _origo_home_menu_anonymouse_user(); break; case 1: $block['subject'] = ''; $block['content'] = origo_home_menu_origo_user($user); break; case 2: $block['subject'] = ''; $block['content'] = origo_home_menu_origo_admin($user); break; case 3: $block['subject'] = ''; $block['content'] = _origo_home_menu_drupal_admin($user); break; } return $block; } } /** * Generate menu for anonymous user. * * @return String Block */ function _origo_home_menu_anonymouse_user() { $output = t(''); return $output; } /** * Generate menu for drupal admin to enable Administer. * * @param User user * @return String Block */ function _origo_home_menu_drupal_admin($user) { $output = ''; if ($user->name === 'admin' && $user->uid === '1') { $output .= ''; } return $output; } /** * Show project settings - project pretty name page */ function origo_home_project_settings_project_prettyname_page() { $output = t('

Define a \'pretty\' name for your project which is used throughout the UI instead of the real project name. This name is not related to your real project name (i.e. the name you provided at project creation and which is visible in the domain name).

'); $output .= drupal_get_form('origo_home_project_settings_project_prettyname_form'); return $output; } function origo_home_project_settings_project_prettyname_form(&$form_state) { $form['project_prettyname'] = array( '#type' => 'textfield', '#title' => t('Project Pretty Name'), '#default_value' => variable_get('origo_project_prettyname', ''), '#size' => 50, '#maxlength' => 50, '#description' => t('The maximum length is 50 chars.'), ); $form['submit'] = array( '#type' => 'submit', '#value' => t('Save'), ); return $form; } function origo_home_project_settings_project_prettyname_form_submit($form, &$form_state) { // send new pretty name to backend $changed_settings[] = array( 'setting_type' => 'project_pretty_name', 'setting_value' => $form_state['values']['project_prettyname'] ); $is_ok = origo_auth_xmlrpc_session(variable_get('origo_api', ''), 'project.change_settings', (int)variable_get('origo_project_id', 0), $changed_settings); if ((int)xmlrpc_errno() > 0) { form_set_error('subject', t('The following error occured: '. xmlrpc_error_msg())); } else { variable_set('origo_project_prettyname', $form_state['values']['project_prettyname']); drupal_set_message("Project Pretty Name updated."); } } function origo_home_access_matrix() { $headers = array( 'root' => ' ', 'os' => t('Open Source'), 'cs' => t('Closed Source'), 'private'=> t('Private'), ); $data = array( 'owner' => array( 'data' => array( t('Everything'), t('Everything'), t('Everything'), ), ), 'member' => array( 'data' => array( t('All but project and member settings'), t('All but project and member settings'), t('All but project and member settings'), ), ), 'client' => array( 'data' => array( t('Not available'), t('Not available'), t('Public content, downloads, create issues and forum articles'), ), ), 'user' => array( 'title' => t('Registered User'), 'data' => array( t('Public content, downloads, create issues and forum articles, read source'), t('Public content, downloads, create issues and forum articles'), t('No access'), ), ), 'anon' => array( 'title' => t('Anonymous'), 'data' => array( t('Public content, downloads, read issues, forum articles and source'), t('Public content, downloads, read issues and forum articles'), t('No access'), ), ), 'visibility' => array( 'title' => t('Default content visibility'), 'data' => array( t('Public'), t('Private'), t('Private'), ), ), ); return theme('origo_home_access_matrix', $headers, $data); } function theme_origo_home_access_matrix($headers, $data) { $output = "
\n"; // check headers if (!isset($headers) || !is_array($headers) || empty($headers)) { return $output; } // check data if (!isset($data) || !is_array($data) || empty($data)) { return $output; } $span = 1 + count($headers); $output .= "\n\n\t\t\n\t\t\n\t\n\t\n"; foreach ($headers as $col) { $output .= "\t\t\n"; } $output .= "\t\n\t\n\t\n"; foreach ($data as $id => $row) { $title = $row['title']; if (!isset($row['title'])) { $title = drupal_ucfirst($id); } $output .= "\t\n\t\t\n"; foreach ($row['data'] as $cell) { $output .= "\t\t\n"; } $output .= "\t\n"; } $output .= "\n
Access Rights
$col
$title$cell
\n
\n"; return $output; } /** * Implementation of hook_cron(). * * Deletes term data that isn't referenced by any node (#1238). */ function origo_home_cron() { $sql = "DELETE FROM {term_data} ". "WHERE tid IN ". " (SELECT tid FROM ". " (SELECT tid ". " FROM {term_node} tn ". " RIGHT JOIN {term_data} td USING(tid) ". " JOIN {vocabulary_node_types} vnt ON td.vid = vnt.vid ". " WHERE ". " (vnt.type='issue' OR vnt.type='wiki' OR vnt.type='blog') ". " AND ". " ISNULL(nid) ". " ) AS x ". " )"; db_query($sql); }