/**
  * This abstract function performs the processing of the user request.
  * @param User $user The requesting user. If the user is not null, then by convention
  * actions will assume the user is authenticated, otherwise not.
  * @throws Exception If an error was encountered while processing this request, an exception
  * will be thrown.
  * @return void
  */
 public function processRequest(User $user = NULL)
 {
     $returnUrl = UrlFormatter::formatRoutingItemUrl('actions/LoginAction');
     $imageSearchViewUrl = UrlFormatter::formatRoutingItemUrl('views/ImageSearchView');
     // if the user is already logged in redirect to the image search view
     if ($user != NULL) {
         header("Location: {$imageSearchViewUrl}");
         return;
     } else {
         if (!isset($_POST[self::POST_PARAM_USERNAME]) || !isset($_POST[self::POST_PARAM_USERNAME])) {
             $loginView = new LoginView();
             $loginView->processRequest();
             exit;
         }
         $username = $_POST[self::POST_PARAM_USERNAME];
         $password = $_POST[self::POST_PARAM_PASSWORD];
         $user = User::loadUserByUsername(DbConnectionUtil::getDbConnection(), $username);
         if ($user == NULL || $user->getPassword() != md5($password)) {
             $loginView = new LoginView();
             $loginView->setPreviousAttemptErrorMessage("Login Failed");
             $loginView->processRequest();
             exit;
         } else {
             UserAuthUtil::registerAuthenticatedUser($user);
             header("Location: {$imageSearchViewUrl}");
             return;
         }
     }
 }
 public function processRequest(User $user = NULL)
 {
     // check for a journey image list, if none exists, redirect to start journey view
     if (!isset($_SESSION['JOURNEY_IMAGE_LIST']) || empty($_SESSION['JOURNEY_IMAGE_LIST'])) {
         $startJourneyUrl = UrlFormatter::formatRoutingItemUrl('views/StartJourneyView');
         header("Location: {$startJourneyUrl}");
         exit;
     }
     // check for journey name and comments, if they're missing, redirect to finish journey view
     $finishJourneyUrl = UrlFormatter::formatRoutingItemUrl('views/FinishJourneyView');
     if (!isset($_POST[self::POST_PARAM_JOURNEY_NAME]) || empty($_POST[self::POST_PARAM_JOURNEY_NAME]) || !isset($_POST[self::POST_PARAM_JOURNEY_COMMENTS]) || empty($_POST[self::POST_PARAM_JOURNEY_COMMENTS])) {
         header("Location: {$finishJourneyUrl}");
         exit;
     }
     $journeyName = strip_tags($_POST[self::POST_PARAM_JOURNEY_NAME]);
     $journeyName = str_replace("\\", "", $journeyName);
     $journeyComments = strip_tags($_POST[self::POST_PARAM_JOURNEY_COMMENTS]);
     $journeyComments = str_replace("\\", "", $journeyComments);
     // populate and save a new journey data object
     $journeyData = new Journey();
     $journeyData->setTitle($journeyName);
     $journeyData->setComments($journeyComments);
     $journeyData->setCreationDate(time());
     foreach ($_SESSION['JOURNEY_IMAGE_LIST'] as $imageDataId) {
         $journeyData->addImageId($imageDataId);
     }
     $dbConnection = DbConnectionUtil::getDbConnection();
     $journeyData->save($dbConnection);
     // unset the journey image list
     unset($_SESSION['JOURNEY_IMAGE_LIST']);
     unset($_SESSION['JOURNEY_ATTRIBUTE_MAP']);
     // redirect to the journey details view
     $journeyDetailsUrl = UrlFormatter::formatRoutingItemUrl('views/JourneyDetailsView', array(JourneyDetailsView::GET_PARAM_JOURNEY_ID => $journeyData->getId()));
     header("Location: {$journeyDetailsUrl}");
 }
    /**
     * This function performs the processing of the user request.
     * @param User $user The requesting user. If the user is not null, then by convention
     * actions will assume the user is authenticated, otherwise not.
     * @throws Exception If an error was encountered while processing this request, an exception
     * will be thrown.
     * @return void
     */
    public function processRequest(User $user = NULL)
    {
        parent::displayHeader($user, 'Image Search');
        $searchActionUrl = UrlFormatter::formatRoutingItemUrl('views/ImageSearchResultsView');
        ?>
	<form class="imageForm" method="POST" action="<?php 
        echo $searchActionUrl;
        ?>
">
	     <label for="title_field">Title</label>
             <br/>
             <input type="text" id="title_field" name="<?php 
        echo ImageSearchresultsView::POST_PARAM_TITLE;
        ?>
"/>
             <?php 
        parent::formatImageDataAutoComplete(DbConnectionUtil::getDbConnection(), 'title', 'title_field');
        ?>
	     <br/>
             <label for="author_field">Author</label>
	     <br/>
             <input type="text" id="author_field" name="<?php 
        echo ImageSearchResultsView::POST_PARAM_AUTHOR;
        ?>
"/>
             <?php 
        parent::formatImageDataAutoComplete(DbConnectionUtil::getDbConnection(), 'author', 'author_field');
        ?>
	     <br/>
             <label for="year_field">Year</label>
             <br/>
             <input id="year_field" name="<?php 
        echo ImageSearchResultsView::POST_PARAM_YEAR;
        ?>
"/>
             <?php 
        parent::formatImageDataAutoComplete(DbConnectionUtil::getDbConnection(), 'year', 'year_field');
        ?>
             <br/>
             <label for="attribute_field">Attribute</label>
             <br/>
             <input id="attribute_field" name="<?php 
        echo ImageSearchResultsView::POST_PARAM_ATTRIBUTE;
        ?>
"/>
             <?php 
        parent::formatImageAttributeDataAutoComplete(DbConnectionUtil::getDbConnection(), 'attribute_field');
        ?>
	     <br/>
             <input type="submit" class="button" value="Search">
	</form>
	<?php 
        parent::displayFooter();
    }
 /**
  * This function returns a reference to the database connection. If none exists, it will establish
  * the connection to the database.
  * @return A reference to the database connection.
  * @throws PDOException If an error occurred during the process of establishing the database connection.
  */
 public static function getDbConnection()
 {
     // if the single DB connection has not yet been initialized, initialize it
     if (DbConnectionUtil::$dbConnection == NULL) {
         $dbConnectionString = 'mysql:host=' . Settings::getSetting('DB_URL');
         $dbConnectionString .= ';dbname=' . Settings::getSetting('DB_SCHEMA');
         DbConnectionUtil::$dbConnection = new PDO($dbConnectionString, Settings::getSetting('DB_USERNAME'), Settings::getSetting('DB_PASSWORD'));
         DbConnectionUtil::$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
     }
     return DbConnectionUtil::$dbConnection;
 }
    public function processRequest(User $user = NULL)
    {
        parent::displayHeader($user, 'Journeys List');
        $dbConnection = DbConnectionUtil::getDbConnection();
        $journeyIdList = Journey::loadAllJourneyIdList($dbConnection);
        $journeyDataList = array();
        foreach ($journeyIdList as $journeyId) {
            $journeyDataList[] = Journey::loadJourneyById($dbConnection, $journeyId);
        }
        ?>
        <div class="imageDetailsView">
        <?php 
        foreach ($journeyDataList as $journeyData) {
            $journeyDetailUrl = UrlFormatter::formatRoutingItemUrl('views/JourneyDetailsView', array(JourneyDetailsView::GET_PARAM_JOURNEY_ID => $journeyData->getId()));
            ?>
	    <div style="display:inline-block" class="searchResultItem">
	    <label for="journey_name_field">Journey Name</label>
	    <br/>
	    <a href="<?php 
            echo $journeyDetailUrl;
            ?>
"><span id="journey_name_field" class="imageDetailsField"><?php 
            echo $journeyData->getTitle();
            ?>
</span></a>
	    <br/>
	    <label for="journey_date_field">Journey Date</label>
	    <br/>
	    <span id="journey_date_field" class="imageDetailsField"><?php 
            echo $journeyData->getCreationDate();
            ?>
</span>
	    </div>
	    <div style="clear:both"></div>
	    <?php 
        }
        ?>
        </div>
	
	<?php 
        parent::displayFooter();
    }
    public function processRequest(User $user = NULL)
    {
        // if no journey exists, then redirect to the start journey page
        $startJourneyUrl = UrlFormatter::formatRoutingItemUrl('views/StartJourneyView');
        if (!isset($_SESSION['JOURNEY_IMAGE_LIST']) || empty($_SESSION['JOURNEY_IMAGE_LIST'])) {
            header("Location: {$startJourneyUrl}");
            exit;
        }
        parent::displayHeader($user, 'Finish Journey');
        //print( "JOURNEY IMAGE LIST: " ); print_r( $_SESSION['JOURNEY_IMAGE_LIST'] ); print( "<br/>" );
        // load the image data for images encountered on the journey
        $dbConnection = DbConnectionUtil::getDbConnection();
        $imageDataList = NULL;
        if (!empty($_SESSION['JOURNEY_IMAGE_LIST'])) {
            $imageDataList = ImageData::loadImageDataListByIdSet($dbConnection, $_SESSION['JOURNEY_IMAGE_LIST']);
        }
        //print( "JOURNEY ATTRIBUTE MAP: " ); print_r( $_SESSION['JOURNEY_ATTRIBUTE_MAP'] ); print( "<br/>" );
        // if possible, load image data for images with common attributes
        $commonImageDataList = NULL;
        $commonAttribute = NULL;
        //print( "<br/>att map: " ); print_r( $_SESSION['JOURNEY_ATTRIBUTE_MAP'] ); print("<br/>" );
        if (isset($_SESSION['JOURNEY_ATTRIBUTE_MAP']) && !empty($_SESSION['JOURNEY_ATTRIBUTE_MAP'])) {
            // find the attribute with the maximum number of entries
            $maxAttribute = NULL;
            $maxAttributeCount = 0;
            foreach ($_SESSION['JOURNEY_ATTRIBUTE_MAP'] as $attribute => $count) {
                if ($maxAttribute == NULL || $maxAttributeCount < $count) {
                    $maxAttribute = $attribute;
                    $maxAttributeCount = $count;
                }
            }
            $commonAttribute = $maxAttribute;
            // find images with common attributes
            $tempCommonImageIdList = ImageAttribute::loadCommonAttributeImageIdList($dbConnection, $commonAttribute, $_SESSION['JOURNEY_IMAGE_LIST']);
            $commonImageIdList = array();
            foreach ($tempCommonImageIdList as $imageId) {
                if (!in_array($imageId, $_SESSION['JOURNEY_IMAGE_LIST'])) {
                    $commonImageIdList[] = $imageId;
                }
            }
            if (!empty($commonImageIdList)) {
                $commonImageDataList = ImageData::loadImageDataListByIdSet($dbConnection, $commonImageIdList);
            }
        }
        // display the journey in an image grid
        ?>
	<p class="imageGridHeader">Your Journey Through Art</p>
	<div class="centerWrapper">
        <div class="imageGrid">
	<?php 
        foreach ($imageDataList as $imageData) {
            $this->displayImageDetailLink($imageData);
        }
        ?>
	</div>
	</div>
	<?php 
        if ($commonImageDataList != NULL) {
            ?>
	    <p class="imageGridHeader">Suggested Art</p>
	    <div class="centerWrapper">
		<p>Based upon your choices here is a selection of other art pieces to examine</p>
	    <div class="imageGrid">
	    <?php 
            foreach ($commonImageDataList as $imageData) {
                $this->displayImageDetailLink($imageData);
            }
            ?>
	    </div>
	    </div>
	    <?php 
        }
        $saveJourneyUrl = UrlFormatter::formatRoutingItemUrl('actions/SaveJourneyAction');
        ?>
	<script type="text/javascript">
	function validate( ) {
	    var result = true;
	    $("#errorSection").html("");
	    var nameVal = $("#journey_name_field").val( );
	    if( nameVal == null || nameVal == "" ) {
		$("#errorSection").append( "<span clas=\"errorMessage\">Journey Name Required</span><br/>" );
		$("#errorSection").css( "display", "inline-block");
		$("#journey_name_field_label").css( "color", "#EE3124" );
		result = false;
	    }
	    var commentsVal = $("#journey_comments_field").val( );
	    if( commentsVal == null || commentsVal == "" ) {
		$("#errorSection").append( "<span clas=\"errorMessage\">Comments Required</span><br/>" );
		$("#errorSection").css( "display", "inline-block");
		$("#journey_comments_field_label").css( "color", "#EE3124" );
		result = false;
	    }
	    return result;
	}
	</script>
	<p class="imageGridHeader">Journey Feedback</p>
        <p style="width:50%">
	     You are now encouraged to take a moment to reflect on your journey through art. Consider the feelings which were illicited during the experience. Also think about how each piece might have had an affect on your perception of subsequent pieces. Please share your thoughts in the comments field.
	</p>
	<form class="imageForm" method="POST" action="<?php 
        echo $saveJourneyUrl;
        ?>
" onsubmit="return validate( )">
	     <div class="errorSection" id="errorSection"></div>
	     <br/>
	     <label id="journey_name_field_label" for="journey_name_field">Journey Name</label>
	     <br/>
             <input id="journey_name_field" type="text" name="<?php 
        echo SaveJourneyAction::POST_PARAM_JOURNEY_NAME;
        ?>
"/>
             <br/>
             <label id="journey_comments_field_label" for="journey_comments_field">Comments</label>
             <br/>
             <textarea id="journey_comments_field" rows="10" cols="100" name="<?php 
        echo SaveJourneyAction::POST_PARAM_JOURNEY_COMMENTS;
        ?>
" value=""></textarea>
             <br/>
             <input class="button" type="submit" value="Save"/>
	</form>
	<?php 
        parent::displayFooter();
    }
require_once dirname(dirname(__FILE__)) . '/util/ClassLoader.class.php';
ClassLoader::requireClassOnce('model/User');
ClassLoader::requireClassOnce('model/UserRole');
ClassLoader::requireClassOnce('model/UserPreferences');
ClassLoader::requireClassOnce('util/DbConnectionUtil');
// create a new test user
printf("Testing user creation...");
$testNetId = 'testNetId';
$testEmail = '*****@*****.**';
$testRealName = 'Test User';
$testRoleTypes = array(UserRole::USER_ROLE_TYPE_EDITOR, UserRole::USER_ROLE_TYPE_VIEWER);
$testUser = User::generateNewUser($testNetId, $testEmail, $testRealName, $testRoleTypes, TRUE);
print "PASSED\n";
// insert the new user
printf("Testing user insertion...");
$dbConnection = DbConnectionUtil::getDbConnection();
$testUser->save($dbConnection);
print "PASSED\n";
// retrieve the user
$userId = $testUser->getId();
printf("Testing user retrieval, id: {$userId} ...");
$testUser = NULL;
$testUser = User::loadUserByNetId($dbConnection, $testNetId);
// verify the retrieve user data
if (!$testUser) {
    print "FAILED: did not load user data\n";
    exit(-1);
}
if ($userId != $testUser->getId()) {
    print "FAILED: retrieved id did not match, original: {$userId} retrieved: {$testUser->getId()}\n";
    exit(-1);
    public function processRequest(User $user = NULL)
    {
        parent::displayHeader($user, 'Image Search Results');
        // compose and execute query
        $dbConnection = DbConnectionUtil::getDbConnection();
        $queryString = 'SELECT imd.id FROM image_data imd ';
        $attribute = RequestParser::parseRequestParam($_REQUEST, ImageSearchResultsView::POST_PARAM_ATTRIBUTE, RequestParser::PARAM_FILTER_TYPE_ALPHA_NUMERIC_WS_ONLY);
        if ($attribute != NULL) {
            $queryString .= "INNER JOIN image_attribute ima ON imd.id = ima.image_data_id AND ima.attribute LIKE '%{$attribute}%' ";
        }
        $queryString .= ' WHERE 1=1 ';
        $title = RequestParser::parseRequestParam($_REQUEST, ImageSearchResultsView::POST_PARAM_TITLE, RequestParser::PARAM_FILTER_TYPE_ALPHA_NUMERIC_WS_ONLY);
        if ($title != NULL) {
            $queryString .= "AND imd.title LIKE '%{$title}%' ";
        }
        $year = RequestParser::parseRequestParam($_REQUEST, ImageSearchResultsView::POST_PARAM_YEAR, RequestParser::PARAM_FILTER_TYPE_INT);
        if ($year != NULL) {
            $queryString .= "AND imd.year LIKE '%{$year}%' ";
        }
        $author = RequestParser::parseRequestParam($_REQUEST, ImageSearchResultsView::POST_PARAM_AUTHOR, RequestParser::PARAM_FILTER_TYPE_ALPHA_WS_ONLY);
        if ($author != NULL) {
            $queryString .= "AND imd.author LIKE '%{$author}%' ";
        }
        //print( "<br/>queryString: $queryString<br/><br/>" );
        $preparedStatement = $dbConnection->prepare($queryString);
        $preparedStatement->execute();
        $idList = array();
        while ($resultRow = $preparedStatement->fetch(PDO::FETCH_ASSOC)) {
            $idList[] = $resultRow['id'];
        }
        $preparedStatement = NULL;
        if (count($idList) > 0) {
            $imageDataResultList = ImageData::loadImageDataListByIdSet($dbConnection, $idList);
        } else {
            $imageDataResultList = array();
        }
        ?>
	<h1>Search Results</h1>
	<br/>
	<div class="imageDetailsView">
	<?php 
        foreach ($imageDataResultList as $imageData) {
            $viewImageDetailsUrl = UrlFormatter::formatRoutingItemUrl('views/ImageDetailsView', array(ImageDetailsView::GET_PARAM_IMAGE_ID => $imageData->getId()));
            ?>
		 <div class="searchResultItem">
		 <?php 
            $thumbnailUri = $imageData->getThumbnailUri();
            if (!empty($thumbnailUri)) {
                ?>
		       <div>
		       	<a href="<?php 
                echo $viewImageDetailsUrl;
                ?>
"><img  id="thumbnail_field" src="<?php 
                echo UrlFormatter::formatImageUrl($imageData->getThumbnailUri());
                ?>
"/></a>
			 <br/>
			 <a href="<?php 
                echo $viewImageDetailsUrl;
                ?>
">Details</a>
		       
		       </div>
		       <?php 
                $title = $imageData->getTitle();
                if ($title != null) {
                    ?>
		       		<label for="title_field">Title</label>
		      		 <span  id="title_field" class="imageDetailsField"><?php 
                    echo $title;
                    ?>
</span>
		      		 <br/>
		      		 <?php 
                }
                ?>
		       <?php 
                $author = $imageData->getAuthor();
                if ($author != null) {
                    ?>
		       		<label for="author_field">Author</label>
		      		 <span  id="author_field" class="imageDetailsField"><?php 
                    echo $author;
                    ?>
</span>
		      		 <br/>
		      		 <?php 
                }
                ?>
			<br/>
		       	
		       <?php 
            }
            ?>
		 </div>
		 <div style="clear:both"></div>
		 <?php 
        }
        ?>
	</div>
	<?php 
        parent::displayFooter();
    }
    public function processRequest(User $user = NULL)
    {
        // attempt to parse and load the next image id
        $nextImageId = RequestParser::parseRequestParam($_REQUEST, self::GET_PARAM_NEXT_IMAGE_ID, RequestParser::PARAM_FILTER_TYPE_INT);
        // if no image was specified, redirect to the start journey view
        $startJourneyUrl = UrlFormatter::formatRoutingItemUrl('views/StartJourneyView');
        if (!$nextImageId) {
            header("Location: {$startJourneyUrl}");
            exit;
        }
        $dbConnection = DbConnectionUtil::getDbConnection();
        $nextImageData = ImageData::loadImageDataById($dbConnection, $nextImageId);
        if (!$nextImageData) {
            header("Location: {$startJourneyUrl}");
            exit;
        }
        parent::displayHeader($user, 'Journey');
        // attempt to parse the chosen attribute, if specified add to its tally
        if (isset($_GET[self::GET_PARAM_CHOSEN_ATTRIBUTE])) {
            $chosenAttribute = $_GET[self::GET_PARAM_CHOSEN_ATTRIBUTE];
            // verify the specified chosen attribute is actually an attribute of the chosen image
            if ($nextImageData->hasAttribute($chosenAttribute)) {
                if (!isset($_SESSION['JOURNEY_ATTRIBUTE_MAP'][$chosenAttribute])) {
                    $_SESSION['JOURNEY_ATTRIBUTE_MAP'][$chosenAttribute] = 1;
                } else {
                    $_SESSION['JOURNEY_ATTRIBUTE_MAP'][$chosenAttribute]++;
                }
            }
        }
        // store the current image id, in the journey session array, check for membership incase of a page re-load
        if (!in_array($nextImageId, $_SESSION['JOURNEY_IMAGE_LIST'])) {
            $_SESSION['JOURNEY_IMAGE_LIST'][] = $nextImageId;
        }
        $commonAttributeImageDataTupleList = NULL;
        $commonAttributeImageIdList = NULL;
        $randomImageDataList = NULL;
        // find NUM_SIMILAR_CHOICES common images if possible
        $commonAttributeImageIdTupleList = ImageAttribute::loadCommonAttributeImageIdTupleList($dbConnection, $nextImageId, $_SESSION['JOURNEY_IMAGE_LIST']);
        //print( "<br/>common id list: " ); print_r( $commonAttributeImageIdTupleList ); print("<br/>" );
        shuffle($commonAttributeImageIdTupleList);
        $commonAttributeImageIdList = array();
        $commonAttributeImageDataTupleList = array();
        while (count($commonAttributeImageDataTupleList) < self::NUM_SIMILAR_CHOICES && count($commonAttributeImageIdTupleList) > 0) {
            $currentEntry = array();
            $commonAttributeImageIdTuple = array_shift($commonAttributeImageIdTupleList);
            if (!in_array($commonAttributeImageIdTuple['imageId'], $commonAttributeImageDataTupleList) && !in_array($commonAttributeImageIdTuple['imageId'], $_SESSION['JOURNEY_IMAGE_LIST'])) {
                $imageData = ImageData::loadImageDataById($dbConnection, $commonAttributeImageIdTuple['imageId']);
                //print( "<br/>Image Data: " ); print_r( $imageData ); print( '<br/>' );
                $commonAttributeImageIdList[] = $commonAttributeImageIdTuple['imageId'];
                $currentEntry['imageData'] = $imageData;
                $currentEntry['attribute'] = $commonAttributeImageIdTuple['attribute'];
                $commonAttributeImageDataTupleList[] = $currentEntry;
            }
        }
        //print( "<br/>common map: " ); print_r( $commonAttributeImageDataTupleList ); print("<br/>" );
        // add a random image to the choices list, and fill in the gaps if NUM_SIMILAR_CHOICES could not be found, if possible
        /*
          print( "<br/>commonAttributeImageDataTupleList: " ); print_r( $commonAttributeImageDataTupleList ); print( "<br/>" );
          print( "allImageIdList: " ); print_r( $allImageIdList ); print( "<br/>" );
          print( "att_map: " ); print_r( $_SESSION['JOURNEY_IMAGE_LIST'] ); print( "<br/>" );
        */
        $allImageIdList = ImageData::loadAllImageIdList($dbConnection);
        shuffle($allImageIdList);
        $randomImageIdList = array();
        while (count($randomImageIdList) + count($commonAttributeImageIdList) < self::NUM_SIMILAR_CHOICES + 1 && count($allImageIdList) > 0) {
            $imageId = array_shift($allImageIdList);
            if ($imageId != $nextImageId && !in_array($imageId, $randomImageIdList) && !in_array($imageId, $commonAttributeImageIdList) && !in_array($imageId, $_SESSION['JOURNEY_IMAGE_LIST'])) {
                $randomImageIdList[] = $imageId;
            }
        }
        if (!empty($randomImageIdList)) {
            $randomImageDataList = ImageData::loadImageDataListByIdSet($dbConnection, $randomImageIdList);
        } else {
            $randomImageDataList = array();
        }
        // If the journey session array size has reached the number of journey steps, then set the is last
        // step flag to true, otherwise it should be false
        $IS_LAST_STEP = FALSE;
        if (count($_SESSION['JOURNEY_IMAGE_LIST']) == self::NUM_JOURNEY_STEPS) {
            $IS_LAST_STEP = TRUE;
        }
        // display the current image
        ?>
	<div class="currentJourneyImageSection">
	     <img src="<?php 
        echo UrlFormatter::formatImageUrl($nextImageData->getContentUri());
        ?>
"/>
	</div>
	<?php 
        // if this is not the last step, display further choices
        if (!$IS_LAST_STEP) {
            ?>
	    <p class="imageGridHeader">Choose Your Journey's Next Step</p>
	    <div class="centerWrapper">
	    <div class="imageGrid">
	    <?php 
            // list common choices
            foreach ($commonAttributeImageDataTupleList as $commonAttributeImageDataTuple) {
                $commonImageId = $commonAttributeImageDataTuple['imageData']->getId();
                $commonImageThumbUrl = UrlFormatter::formatImageUrl($commonAttributeImageDataTuple['imageData']->getThumbnailUri());
                $commonAttribute = $commonAttributeImageDataTuple['attribute'];
                $choiceUrl = UrlFormatter::formatRoutingItemUrl('views/JourneyStepView', array(self::GET_PARAM_NEXT_IMAGE_ID => $commonImageId, self::GET_PARAM_CHOSEN_ATTRIBUTE => $commonAttribute));
                ?>
		<a href="<?php 
                echo $choiceUrl;
                ?>
"><img src="<?php 
                echo $commonImageThumbUrl;
                ?>
"/></a>
		<?php 
            }
            // list random choices
            foreach ($randomImageDataList as $randomImageData) {
                $randomImageId = $randomImageData->getId();
                $thumbnailUrl = UrlFormatter::formatImageUrl($randomImageData->getThumbnailUri());
                $choiceUrl = UrlFormatter::formatRoutingItemUrl('views/JourneyStepView', array(self::GET_PARAM_NEXT_IMAGE_ID => $randomImageId));
                ?>
		<a href="<?php 
                echo $choiceUrl;
                ?>
"><img src="<?php 
                echo $thumbnailUrl;
                ?>
"/></a>
		<?php 
            }
            ?>
	    </div>
	    </div>
	    <?php 
        } else {
            $finishJourneyUrl = UrlFormatter::formatRoutingItemUrl('views/FinishJourneyView');
            ?>
	    <div class="finishJourneyButtonSection">
		 <a class="button" href="<?php 
            echo $finishJourneyUrl;
            ?>
">Finish Journey</a>
	    </div>
	    <?php 
        }
        parent::displayFooter();
    }
    /**
     * This function performs the processing of the user request.
     * @param User $user The requesting user. If the user is not null, then by convention
     * actions will assume the user is authenticated, otherwise not.
     * @throws Exception If an error was encountered while processing this request, an exception
     * will be thrown.
     * @return void
     */
    public function processRequest(User $user = NULL)
    {
        // if an image id was specified, assuming editting an existing image, otherwise assume it's a new image
        $imageId = NULL;
        if (isset($_GET[EditImageView::GET_PARAM_IMAGE_ID])) {
            $imageId = $_GET[EditImageView::GET_PARAM_IMAGE_ID];
        }
        $pageHeader = $imageId == NULL ? 'Add New Image' : 'Edit Image';
        parent::displayHeader($user, $pageHeader);
        $editImageActionUrl = NULL;
        $getParamMap = NULL;
        $imageData = NULL;
        if ($imageId != NULL) {
            $getParamMap = array();
            $getParamMap[EditImageAction::GET_PARAM_IMAGE_ID] = $imageId;
            $imageData = ImageData::loadImageDataById(DbConnectionUtil::getDbConnection(), $imageId);
        }
        $author = '';
        $title = '';
        $year = '';
        $attributeList = NULL;
        $attributeListString = "";
        $thumbnailUri = NULL;
        $contentUri = NULL;
        if ($imageData != NULL) {
            $contentUri = $imageData->getContentUri();
            $thumbnailUri = $imageData->getThumbnailUri();
            $title = $imageData->getTitle();
            $year = $imageData->getYear();
            $author = $imageData->getAuthor();
            $attributeList = $imageData->getAttributeList();
            foreach ($attributeList as $attribute) {
                $attributeListString .= "," . $attribute->getAttribute();
            }
        }
        $editImageActionUrl = UrlFormatter::formatRoutingItemUrl('actions/EditImageAction', $getParamMap);
        $submitLabel = $imageId == NULL ? 'Create' : 'Save';
        ?>
	<script type="text/javascript" >
	
	function replaceThumbnail( ) {
		$("#thumbnail_div").html( "<input type=\"file\" id=\"thumbnail_field\" name=\"<?php 
        echo EditImageAction::POST_PARAM_THUMBNAIL;
        ?>
\">" ); 
	}

	function replaceFile( ) {
		$("#file_div").html( "<input type=\"file\" id=\"file_field\" name=\"<?php 
        echo EditImageAction::POST_PARAM_FILE;
        ?>
\">" ); 
	}

	function cancel( ) {
	    var previousPageUrl = "<?php 
        echo $_SERVER['HTTP_REFERER'];
        ?>
";
	    window.location.href = previousPageUrl;
	}

	function removeAttributeAtIndex( index ) {
	    var rowList = $("#attribute_list_table tr");
	    
	    for( i = 0; i < rowList.length; i++ ) {
		if ( i == index ) {
		    var removedAttString = $( rowList[i] ).children( ).first( ).text( );
		    var attList = $( "#attribute_list").val( ).split( "," );
		    attList.splice( attList.indexOf( removedAttString ), 1 );
		    $( "#attribute_list").val( attList.join( ) );
		    $( rowList[i] ).remove( );		    
		}
	    }
	}

	function addAttribute( ) {
	    var attributeValue = prompt( "Specify New Attribute" );
	    var attList = $( "#attribute_list").val( ).split( "," );
	    if ( attributeValue != null && attributeValue != "" && attList.indexOf( attributeValue ) == -1 ) {
		var newIndex = $( "#attribute_list_table tr" ).length;
		$( "#attribute_list_table" ).append( "<tr><td>" + attributeValue + "</td><td><a onclick=\"removeAttributeAtIndex( " + newIndex + " );\">Remove</a></td></tr>" );
		
		attList.push( attributeValue );
		$( "#attribute_list").val( attList.join( ) );
	    }
	}
	
	function validate( ) {
	    var result = true;
	    $("#errorSection").html("" );
	    <?php 
        if ($imageData == NULL) {
            ?>
		var thumbnailVal = $("#thumbnail_field").val( );
		if ( thumbnailVal == null || thumbnailVal == "" ) {
		    $("#errorSection").append( "<span class=\"errorMessage\">Thumbnail Required</span><br/>" );
		    $("#errorSection").css( "display", "inline-block");
		    $("#thumbnail_field_label").css( "color", " #EE3124" );
		    result = false;
		}
		var fileVal = $("#file_field").val( );
		if ( fileVal == null || fileVal == "" ) {
		    $("#errorSection").append( "<span class=\"errorMessage\">File Required</span><br/>" );
		    $("#errorSection").css( "display", "inline-block");
		$("#file_field_label").css( "color", " #EE3124" );
		result = false;
		}
		<?php 
        }
        ?>
	    var authorVal = $("#author_field").val( );
	    if ( authorVal == null || authorVal == "" ) {
		$("#errorSection").append( "<span class=\"errorMessage\">Author Required</span><br/>" );
		$("#errorSection").css( "display", "inline-block");
		$("#author_field_label").css( "color", " #EE3124" );
		result = false;
	    }
	    var titleVal = $("#title_field").val( );
	    if ( titleVal == null || titleVal == "" ) {
		$("#errorSection").append( "<span class=\"errorMessage\">Title Required</span><br/>" );
		$("#errorSection").css( "display", "inline-block");
		$("#title_field_label").css( "color", " #EE3124" );
		result = false;
	    }
	    var yearVal = $("#year_field").val( );
	    if ( yearVal == null || yearVal == "" ) {
		$("#errorSection").append( "<span class=\"errorMessage\">Year Required</span><br/>" );
		$("#errorSection").css( "display", "inline-block");
		$("#year_field_label").css( "color", " #EE3124" );
		result = false;
	    }
	    return result;
	}

	
	</script>
	<form class="imageForm" method="POST" action="<?php 
        echo $editImageActionUrl;
        ?>
" enctype="multipart/form-data" onsubmit="return validate( )">
	      <div class="errorSection" id="errorSection"></div>
	      <br/>

	      <label id="author_field_label" for="author_field">Author</label>
	     <br/>
	     <input id="author_field" type="text" name="<?php 
        echo EditImageAction::POST_PARAM_AUTHOR;
        ?>
" value="<?php 
        echo $author;
        ?>
"/>
		  <?php 
        parent::formatImageDataAutoComplete(DbConnectionUtil::getDbConnection(), 'author', 'author_field');
        ?>
	     <br/>
	     <label id="title_field_label" for="title_field">Title</label>
	     <br/>
             <input id="title_field" type="text" name="<?php 
        echo EditImageAction::POST_PARAM_TITLE;
        ?>
" value="<?php 
        echo $title;
        ?>
"/>
             <br/>
             <label id="year_field_label" for="year_field">Year</label>
             <br/>
	     <input id="year_field" name="<?php 
        echo EditImageAction::POST_PARAM_YEAR;
        ?>
" value="<?php 
        echo $year;
        ?>
"/>
             <br/><br/>

	     <input id="attribute_list" type="hidden" name="<?php 
        echo EditImageAction::POST_PARAM_ATTRIBUTE_LIST;
        ?>
" value="<?php 
        echo $attributeListString;
        ?>
"/>
             <label for="attribute_table">Attributes</label>
	     <table class="attribute_table" id="attribute_list_table">
	     <?php 
        if ($attributeList != NULL) {
            for ($i = 0; $i < count($attributeList); $i++) {
                ?>
						      <tr>
						      <td><?php 
                echo $attributeList[$i]->getAttribute();
                ?>
</td>
						      <td><a onclick="removeAttributeAtIndex(<?php 
                echo $i;
                ?>
);">Remove</a>
						      </tr>
						      <?php 
            }
        }
        ?>
             </table>
             <br/>
	     <a class="button" onclick="addAttribute( );">Add Attribute</a>
	     <br/><br/>

	     <label id="thumbnail_field_label" for="thumbnail_field">Thumbnail</label>
	      <br/>
	      <div id="thumbnail_div">
	      <?php 
        if ($thumbnailUri == NULL) {
            ?>
	         <input type="file" id="thumbnail_field" name="<?php 
            echo EditImageAction::POST_PARAM_THUMBNAIL;
            ?>
"/>
	      <?php 
        } else {
            ?>
		  <img src="<?php 
            echo UrlFormatter::formatImageUrl($thumbnailUri);
            ?>
"/>
		  <br/>
		  <input type="button" onclick="replaceThumbnail( )" value="Replace"/>
	      <?php 
        }
        ?>
	      </div>

             <label id="file_field_label" for="file_field">File</label>
             <br/>
	      <div id="file_div">
	      <?php 
        if ($contentUri == NULL) {
            ?>
			<input type="file" id="file_field" name="<?php 
            echo EditImageAction::POST_PARAM_FILE;
            ?>
"/>
		    <?php 
        } else {
            ?>
			<img style="max-width: 100%" src="<?php 
            echo UrlFormatter::formatImageUrl($contentUri);
            ?>
"/>
			<br/>
		        <input type="button" onclick="replaceFile( )" value="Replace"/>
			<br/>
		    <?php 
        }
        ?>
	      </div>	      
	     
	     <input class="button" type="submit" value="<?php 
        echo $submitLabel;
        ?>
"/>
	     <input class="button" type="button" onclick="cancel( )" value="Cancel"/>
	</form>
	<?php 
        parent::displayFooter();
    }
    public function processRequest(User $user = NULL)
    {
        parent::displayHeader($user, 'Start Journey');
        // TODO query for existing journeys
        // query for distinct image attributes
        $dbConnection = DbConnectionUtil::getDbConnection();
        $distinctAttributeList = ImageAttribute::loadExistingValues($dbConnection);
        // randomly select attributes, foreach attribute, retrieve the id of a unique image, store in sourceImageList
        shuffle($distinctAttributeList);
        $sourceImageIdList = array();
        for ($i = 0; $i < self::NUM_START_SELECTION_COUNT && count($distinctAttributeList) > 0; $i++) {
            $attribute = array_shift($distinctAttributeList);
            $imageIdList = ImageAttribute::loadImageIdListByAttribute($dbConnection, $attribute);
            shuffle($imageIdList);
            while (count($imageIdList) > 0) {
                $imageId = array_shift($imageIdList);
                if (!in_array($imageId, $sourceImageIdList)) {
                    $sourceImageIdList[] = $imageId;
                    break;
                }
            }
        }
        // if the full number of starting images could not be found with distinct attributes, then randomly select more to fill in the gap
        if (count($sourceImageIdList) < self::NUM_START_SELECTION_COUNT) {
            $allImageIdList = ImageData::loadAllImageIdList($dbConnection);
            shuffle($allImageIdList);
            while (count($sourceImageIdList) < self::NUM_START_SELECTION_COUNT && count($allImageIdList) > 0) {
                $imageId = array_shift($allImageIdList);
                if (!in_array($imageId, $sourceImageIdList)) {
                    $sourceImageIdList[] = $imageId;
                }
            }
        }
        // load the randomly selected images
        $sourceImageDataList = ImageData::loadImageDataListByIdSet($dbConnection, $sourceImageIdList);
        shuffle($sourceImageDataList);
        // reset the journey's session data
        if (isset($_SESSION['JOURNEY_IMAGE_LIST'])) {
            unset($_SESSION['JOURNEY_IMAGE_LIST']);
        }
        $_SESSION['JOURNEY_IMAGE_LIST'] = array();
        if (isset($_SESSION['JOURNEY_ATTRIBUTE_MAP'])) {
            unset($_SESSION['JOURNEY_ATTRIBUTE_MAP']);
        }
        $_SESSION['JOURNEY_ATTRIBUTE_MAP'] = array();
        ?>
	<p class="imageGridHeader">Choose Your Journey's Starting Image</p>
	<div class="centerWrapper">
	<div class="imageGrid">	     
             <?php 
        foreach ($sourceImageDataList as $imageData) {
            $imageJourneyUrl = UrlFormatter::formatRoutingItemUrl('views/JourneyStepView', array(JourneyStepView::GET_PARAM_NEXT_IMAGE_ID => $imageData->getId()));
            $imageThumbUrl = UrlFormatter::formatImageUrl($imageData->getThumbnailUri());
            ?>
		 <a href="<?php 
            echo $imageJourneyUrl;
            ?>
"> <img src="<?php 
            echo $imageThumbUrl;
            ?>
"></a>
		 <?php 
        }
        ?>
	</div>
	</div>
	<?php 
        // TODO display a list of existing journeys
        parent::displayFooter();
    }
    public function processRequest(User $user = NULL)
    {
        $journeyId = RequestParser::parseRequestParam($_GET, self::GET_PARAM_JOURNEY_ID, RequestParser::PARAM_FILTER_TYPE_INT);
        $baseUrl = Settings::getSetting('APPLICATION_URL');
        if (!$journeyId) {
            header("Location: {$baseUrl}");
            exit;
        }
        // load the journey data
        $dbConnection = DbConnectionUtil::getDbConnection();
        $journeyData = Journey::loadJourneyById($dbConnection, $journeyId);
        if (!$journeyData) {
            header("Location: {$baseUrl}");
            exit;
        }
        // load the images from the journey
        $imageDataList = ImageData::loadImageDataListByIdSet($dbConnection, $journeyData->getImageIdList());
        parent::displayHeader($user, 'Journey Details');
        ?>
	<div class="imageDetailsView">
	     <label for="journey_name_field">Journey Name</label>
	     <br/>
             <span id="journey_name_field" class="imageDetailsViewField"><?php 
        echo $journeyData->getTitle();
        ?>
</span>
	     <br/>
	     <label for="journey_creation_date_field">Journey Date</label>
             <br/>
             <span id="journey_creation_date_field" class="imageDetailsViewField"><?php 
        echo $journeyData->getCreationDate();
        ?>
</span>
	     <br/>
             <label for="journey_comments_field">Journey Comments</label>
             <br/>
             <p id="journey_comments_field" class="imageDetailsViewField"><?php 
        echo $journeyData->getComments();
        ?>
</p>
	</div>
        <div class="imageGrid">
        <?php 
        foreach ($imageDataList as $imageData) {
            $imageDetailsUrl = UrlFormatter::formatRoutingItemUrl('views/ImageDetailsView', array(ImageDetailsView::GET_PARAM_IMAGE_ID => $imageData->getId()));
            $thumbnailUrl = UrlFormatter::formatImageUrl($imageData->getThumbnailUri());
            ?>
	       <a target="_blank" href="<?php 
            echo $imageDetailsUrl;
            ?>
"><img src="<?php 
            echo $thumbnailUrl;
            ?>
"/></a>
	       <?php 
        }
        ?>
        </div>
	
	<?php 
        parent::displayFooter();
    }
 /**
  * This abstract function performs the processing of the user request.
  * @param User $user The requesting user. If the user is not null, then by convention
  * actions will assume the user is authenticated, otherwise not.
  * @throws Exception If an error was encountered while processing this request, an exception
  * will be thrown.
  * @return void
  */
 public function processRequest(User $user = NULL)
 {
     // if image id was specified, parse it, attempt to load an image data object using the id
     $imageId = RequestParser::parseRequestParam($_REQUEST, EditImageAction::GET_PARAM_IMAGE_ID, RequestParser::PARAM_FILTER_TYPE_INT);
     $imageData = NULL;
     if ($imageId != NULL) {
         $imageData = ImageData::loadImageDataById(DbConnectionUtil::getDbConnection(), $imageId);
     }
     // otherwise create a new image data object
     if ($imageData == NULL) {
         $imageData = new ImageData();
         $imageData->setSubmitterUserId($user->getId());
     }
     // set the fields in the image data object
     $author = NULL;
     if (isset($_POST['author'])) {
         $author = $_POST['author'];
     }
     if ($author != NULL) {
         $imageData->setAuthor($author);
     }
     $title = NULL;
     if (isset($_POST['title'])) {
         $title = $_POST['title'];
     }
     if ($title != NULL) {
         $imageData->setTitle($title);
     }
     $year = NULL;
     if (isset($_POST['year'])) {
         $year = $_POST['year'];
     }
     if ($year != NULL) {
         $imageData->setYear($year);
     }
     // update attributes list
     $attributeString = $_POST[EditImageAction::POST_PARAM_ATTRIBUTE_LIST];
     if (!empty($attributeString)) {
         $attributeStringList = explode(",", $attributeString);
     } else {
         $attributeStringList = array();
     }
     // add new attributes
     foreach ($attributeStringList as $attString) {
         if ($attString != "") {
             if (!$imageData->hasAttribute($attString)) {
                 $imageData->addAttributeByString($attString);
             }
         }
     }
     $dbConnection = DbConnectionUtil::getDbConnection();
     // remove deleted ones
     $attributeList = $imageData->getAttributeList();
     foreach ($attributeList as $attribute) {
         if (!in_array($attribute->getAttribute(), $attributeStringList)) {
             $imageData->removeAttributeBystring($attribute->getAttribute());
             $attribute->delete($dbConnection);
         }
     }
     // save the image data object
     $imageData->save($dbConnection);
     // if image data was uploaded, process the image uploads and save again
     if (!empty($_FILES[EditImageAction::POST_PARAM_THUMBNAIL]['name'])) {
         $thumbnailUri = $this->processImageUpload('image_data_thumbs', $imageData->getId(), EditImageAction::POST_PARAM_THUMBNAIL);
         $imageData->setThumbnailUri($thumbnailUri);
         $imageData->save($dbConnection);
     }
     if (!empty($_FILES[EditImageAction::POST_PARAM_FILE]['name'])) {
         $fileUri = $this->processImageUpload('image_data', $imageData->getId(), EditImageAction::POST_PARAM_FILE);
         $imageData->setContentUri($fileUri);
         $imageData->save($dbConnection);
     }
     // redirect the user to the image viewing page
     $getParamMap = array(ImageDetailsView::GET_PARAM_IMAGE_ID => $imageData->getId());
     $imageDetailsViewUrl = UrlFormatter::formatRoutingItemUrl('views/ImageDetailsView', $getParamMap);
     header("Location: {$imageDetailsViewUrl}");
 }
    /**
     * This function performs the processing of the user request.
     * @param User $user The requesting user. If the user is not null, then by convention
     * actions will assume the user is authenticated, otherwise not.
     * @throws Exception If an error was encountered while processing this request, an exception
     * will be thrown.
     * @return void
     */
    public function processRequest(User $user = NULL)
    {
        parent::displayHeader($user, 'Image Details');
        if (isset($_REQUEST[ImageDetailsView::GET_PARAM_RETURN_URL])) {
            ?>
	    <a href="<?php 
            echo $_REQUEST[ImageDetailsView::GET_PARAM_RETURN_URL];
            ?>
">Return</a>
	    <br/>
	    <?php 
        }
        if (isset($_REQUEST[ImageDetailsView::GET_PARAM_IMAGE_ID])) {
            $imageId = $_REQUEST[ImageDetailsView::GET_PARAM_IMAGE_ID];
            $imageData = ImageData::loadImageDataById(DbConnectionUtil::getDbConnection(), $imageId);
            if ($imageData == NULL) {
                print "Failed to load image data ";
            } else {
                $editImageUrl = UrlFormatter::formatRoutingItemUrl('views/EditImageView', array(EditImageView::GET_PARAM_IMAGE_ID => $imageData->getId()));
                $thumbnailUri = $imageData->getThumbnailUri();
                $contentUri = $imageData->getContentUri();
                ?>
		<div class="imageDetailsView">
		<label for="title_field">Title</label>
                <br/>
	        <span id="title_field" class="imageDetailsViewField"><?php 
                echo $imageData->getTitle();
                ?>
</span>
	        <br/>
                <label for="author_field">Author</label>
                <br/>
                <span id="author_field" class="imageDetailsViewField"><?php 
                echo $imageData->getAuthor();
                ?>
</span>
                <br/>                
                <label for="year_field">Year</label>
                <br/>
                <span id="year_field" class="imageDetailsViewField"><?php 
                echo $imageData->getYear();
                ?>
</span>
		<br/>
                <label for="attributes_field">Attributes</label>
                <br/>
                <table class="attribute_table" id="attributes_field">
                <?php 
                foreach ($imageData->getAttributeList() as $attribute) {
                    ?>
                   <tr><td><?php 
                    echo $attribute->getAttribute();
                    ?>
</td></tr>
                <?php 
                }
                ?>
                </table>
	        <br/>
		<br/>
		<label for="content_uri_field">Image</label>
		<br/>
                <span id="content_uri_field" class="imageDetailsViewField">
                <image style="max-width: 100%" id="content_uri_field" src="<?php 
                echo UrlFormatter::formatImageUrl($contentUri);
                ?>
"/>
                </span>
    	        <br/><br/>
		<label for="thumbnail_field">Thumbnail</label>
                <br/>
		<img id="thumbnail_field" src="<?php 
                echo UrlFormatter::formatImageUrl($thumbnailUri);
                ?>
"/>
		<br/><br/>
		<?php 
                if ($user != NULL) {
                    ?>
		      <a class="button" href="<?php 
                    echo $editImageUrl;
                    ?>
">Edit</a>
		   <?php 
                }
                ?>
	        </div>
	        <?php 
            }
        } else {
            print "No image specified";
        }
        parent::displayFooter();
    }