src/NCBS/WebsiteBundle/Controller/GeneralController.php line 27

Open in your IDE?
  1. <?php
  2. namespace NCBS\WebsiteBundle\Controller;
  3. use NCBS\WebsiteBundle\Tools\DataAssembly;
  4. use Symfony\Component\HttpFoundation\Response;
  5. use Symfony\Component\HttpFoundation\Request;
  6. class GeneralController extends NCBSWController
  7. {
  8.     protected $prefix 'General';
  9.     // Simplify the code for determining whether Bible content is using canonical numbering or not
  10.     protected $bibleCategoryIsCanonical = array('c' => false'v' => false'cc' => true'cv' => true'st' => true);
  11.     
  12.     protected $language1 null;
  13.     protected $work1 null;
  14.     public function spotlightFragmentAction($spot)
  15.     {
  16.         $method $spot.'SpotlightAction';
  17.         if(method_exists($this$method)) {
  18.             return $this->$method();
  19.         }
  20.     }
  21.     public function multicolumnAction($column1Details$column2DetailsRequest $request$column3Details null$renderingData = array())
  22.     {            
  23.         $this->onloadPage($request);
  24.         $bStory = (isset($renderingData['content_class']) && $renderingData['content_class'] == 'story');                
  25.         $this->language1 null;
  26.         $this->work1 null;
  27.         $request->getSession()->set('has_explanation_cchapter_id_temp_bible''');
  28.         $request->getSession()->set('has_explanation_cchapter_id_temp_trans''');
  29.         $request->getSession()->set('current_explanation_cchapter_id_temp_bible''');
  30.         $request->getSession()->set('current_explanation_cchapter_id_temp_trans''');
  31.         $request->getSession()->set('current_explanation_cchapter_id''');
  32.         $renderingData['columns'] = array(
  33.                 => $this->convertColumnData($column1Details1$request),
  34.                 => $this->convertColumnData($column2Details2$request)
  35.             );
  36.             
  37.         $nLastColNum 2;
  38.         $sLastColNewUrl "";   
  39.         $renderingData['multicolumn_route_params'] = array(
  40.                 'column1Details' => $column1Details,
  41.                 'column2Details' => $column2Details
  42.             );
  43.         if(empty($column3Details)) {
  44.             $renderingData['multicolumn_path'] = 'arbitrary_two_column';
  45.         } else {
  46.             $nLastColNum 3;
  47.             $renderingData['multicolumn_path'] = 'arbitrary_three_column';
  48.             $renderingData['columns'][3] = $this->convertColumnData($column3Details3$request);
  49.             $renderingData['multicolumn_route_params']['column3Details'] = $column3Details;
  50.         }
  51.         $curr_book null;
  52.         $story_translation_url null;
  53.         $explained_verse null;
  54.         $first_col_chapter_id null;
  55.         $bExplainedChapter false;
  56.         $first_col_verse_id null;
  57.         $bExplainedVerse false;
  58.         $bExplainedVersePage false// The explanation is for the verse on column 1
  59.         foreach($renderingData['columns'] as $columnNum => $columnDetails) {
  60.             if(empty($columnDetails)|| $columnDetails['column_type'] === 'unrecognized')
  61.             {
  62.                 $response = new Response();
  63.                 $response->setStatusCode(404);
  64.                 return $this->renderView('no_content_back', array(), $response);
  65.             }         
  66.         
  67.             $columnDetails['column_number'] = $columnNum;
  68.             if($columnDetails['column_type'] === 'dependent') {
  69.                 return $this->assembleMulticolumnWithDependencies($renderingData$column1Details$column2Details$request$column3Details);
  70.             }
  71.             if($columnDetails['column_type'] === 'bible') {
  72.                 //$chapterExplanation = $columnDetails['chapter_explanations_for_commentary'];  
  73.                 $curr_book null;
  74.                 if(isset($columnDetails['curr_book']))
  75.                     $curr_book $columnDetails['curr_book']; 
  76.                     
  77.                 $story_translation_url $columnDetails['story_translation_url'];   
  78.                 if($columnNum == 1)
  79.                 {
  80.                     $explained_verse $columnDetails['explained_verse']; 
  81.                     
  82.                     if($columnDetails['content_category'] == 'c')
  83.                         $first_col_chapter_id $columnDetails['chapter_id'];
  84.                         
  85.                     if($columnDetails['content_category'] == 'v')
  86.                         $first_col_verse_id $columnDetails['verse_id'];    
  87.                 }    
  88.            
  89.                 if(empty($column3Details) && $columnNum == && isset($columnDetails['verse_meta_desc']))
  90.                     $renderingData['verse_meta_desc'] = $columnDetails['verse_meta_desc'];         
  91.             }
  92.             elseif($columnDetails['column_type'] === 'exposition') {
  93.                 //$renderingData['chapter_explanations'] = $chapterExplanation;
  94.                 if(isset($columnDetails['translation']) && $columnDetails['translation'] != null) {                   
  95.                    $translation_id $columnDetails['translation']->getId();
  96.                    if($columnNum == $nLastColNum && @$_GET["fs"] == 1)
  97.                    {
  98.                            $passage_id $columnDetails['passage']->getId();
  99.                         $sLastColNewUrl $this->getNewWorkTranslationUrl($translation_id$passage_id);            
  100.                         if(!empty($sLastColNewUrl))
  101.                         {
  102.                             break;
  103.                         }            
  104.                    }
  105.                    $nBibleBookIDForSummary $this->getBibleBookIDForSummary($translation_id);
  106.                    $bBibleBookSummary = ($nBibleBookIDForSummary != '');
  107.                    $aBibleBookSummaryList null;
  108.                    if($bBibleBookSummary)
  109.                    {
  110.                            $aBibleBookSummaryList $this->getBibleBookSummaryList($nBibleBookIDForSummary);
  111.                            
  112.                            if(!empty($aBibleBookSummaryList))
  113.                                $renderingData['book_id_for_summaries'] = $nBibleBookIDForSummary;
  114.                    }
  115.                    
  116.                    $renderingData['book_summaries'] = $aBibleBookSummaryList;
  117.                    
  118.                    $tempchapterExplanation null;
  119.                    $tempchapterExplanationForCombo null;
  120.                    if(!$bBibleBookSummary)
  121.                    {
  122.                        if($curr_book != null)
  123.                        {
  124.                                $tempchapterExplanation $this->getChapterExplanations($curr_book$columnDetails['translation'], $request);
  125.                                $tempchapterExplanationForCombo $this->getChapterExplanationsForCombo($curr_book$columnDetails['translation']);
  126.                                
  127.                                $renderingData['explained_book'] = $curr_book;
  128.                            }    
  129.                            else
  130.                            {
  131.                                $tempchapterExplanation $this->getChapterExplanationsForText($columnDetails['translation']);    
  132.                                $tempchapterExplanationForCombo $tempchapterExplanation;
  133.                            }    
  134.                         if($tempchapterExplanation != null)
  135.                         {                    
  136.                             $renderingData['chapter_explanations'] = $tempchapterExplanation;
  137.                             $columnDetails['chapter_explanations'] = $tempchapterExplanation;
  138.                             
  139.                             $renderingData['chapter_explanations_for_combo'] = $tempchapterExplanationForCombo;
  140.                             
  141.                             if($columnNum == && $first_col_chapter_id != null && $curr_book != null)
  142.                             {
  143.                                 foreach($tempchapterExplanation as $explanation)
  144.                                 {                  
  145.                                     if($explanation['chapter_id'] == $first_col_chapter_id)
  146.                                     { 
  147.                                         $bExplainedChapter true;
  148.                                         break;
  149.                                     }    
  150.                                 }
  151.                             }
  152.                         }    
  153.                         
  154.                         if($columnNum && $explained_verse != null)
  155.                         {       
  156.                             if($columnNum == && !empty($first_col_verse_id))  
  157.                                 $bExplainedVersePage $this->isExplainedVerse($translation_id$first_col_verse_id); 
  158.                             
  159.                             $tempVerse_explanations $this->getVerseExplanations($explained_verse['chapter_id'], $explained_verse['language_id'], $request);                   
  160.                             $renderingData['verse_explanations'] = $tempVerse_explanations;
  161.                             $renderingData['chapter_id_for_verse_explanation'] = $explained_verse['chapter_id'];
  162.                             $renderingData['language_id_for_verse_explanation'] = $explained_verse['language_id'];
  163.                             
  164.                             foreach($tempVerse_explanations as $explanation)
  165.                             {                  
  166.                                 if($explanation['verse_id'] == $first_col_verse_id)
  167.                                 { 
  168.                                     $bExplainedVerse true;
  169.                                     break;
  170.                                 }    
  171.                             }                            
  172.                         }    
  173.                     } 
  174.                 }              
  175.                 if($story_translation_url != null)
  176.                 {
  177.                     $renderingData['story_translation_url'] = $story_translation_url
  178.                 } 
  179.              
  180.                  if($bStory)
  181.                  {
  182.                      $nTextLength 140;
  183.                      $sTransText $this->getWorkTranslationDesc($translation_id);
  184.                      if(empty($sTransText))
  185.                      {
  186.                          $sTransText $this->getExplanationContents($translation_id);
  187.                      }
  188.                      
  189.                      $sMetaDesc $this->fixWorkText($sTransText);
  190.                       $sMetaDesc $this->getTextWithinLength($sMetaDesc$nTextLength);
  191.                       $renderingData['story_meta_desc'] = $sMetaDesc;
  192.                  }
  193.                  else if(empty($column3Details) && $columnNum == && isset($renderingData['verse_meta_desc']))
  194.                  {
  195.                      if($bExplainedVersePage)
  196.                      {
  197.                          $sTransTitle $columnDetails['translation']->getTranslatedTitle();
  198.                         $renderingData['verse_explanation_meta_desc'] = $sTransTitle " - "$renderingData['verse_meta_desc'];
  199.                     }                    
  200.                 }          
  201.             }
  202.         }
  203.         
  204.         if(!empty($sLastColNewUrl))
  205.         {
  206.             // redirect
  207.             $renderingData['multicolumn_route_params']['column'.$nLastColNum.'Details'] = $sLastColNewUrl;
  208.             return $this->redirect($this->get('router')->generate($renderingData['multicolumn_path'], $renderingData['multicolumn_route_params']), 301);
  209.         }
  210.         if($bExplainedChapter)
  211.         {   
  212.             foreach($renderingData['columns'] as $columnNum => $columnDetails) { 
  213.                 if($columnDetails['column_type'] === 'bible' && $columnNum == 1) {               
  214.                     $renderingData['chapter_explanation_page'] = true;  
  215.                     break;       
  216.                 }
  217.             }
  218.         }
  219.         else if($bExplainedVerse)
  220.         {   
  221.             foreach($renderingData['columns'] as $columnNum => $columnDetails) {            
  222.                 if($columnDetails['column_type'] === 'bible' && $columnNum == 1) {               
  223.                     $renderingData['verse_explanation_page'] = true;
  224.                     break;         
  225.                 }
  226.             }
  227.         }
  228.         
  229.         $this->setCurrentUrl($request); 
  230.                 
  231.         $nTempChapterID_Bible $request->getSession()->get('current_explanation_cchapter_id_temp_bible');
  232.         $nTempChapterID_Trans $request->getSession()->get('current_explanation_cchapter_id_temp_trans');   
  233.         if($nTempChapterID_Trans != '')
  234.         {
  235.             $nTempTransID_Trans $request->getSession()->get('current_explanation_translation_id_temp_trans'); 
  236.             $request->getSession()->set('current_explanation_cchapter_id'$nTempChapterID_Trans);
  237.             $request->getSession()->set('current_explanation_translation_id'$nTempTransID_Trans);
  238.         }    
  239.         else if($nTempChapterID_Bible != '')
  240.         {
  241.             $nTempTransID_Bible $request->getSession()->get('current_explanation_translation_id_temp_bible');
  242.             $request->getSession()->set('current_explanation_cchapter_id'$nTempChapterID_Bible);
  243.             $request->getSession()->set('current_explanation_translation_id'$nTempTransID_Bible);
  244.         }    
  245.                 
  246.         // If no dependencies, can proceed with normal page generation
  247.         return $this->createMulticolumnView($renderingData$request);
  248.     }
  249.     protected function assembleMulticolumnWithDependencies($renderingData$column1Details$column2DetailsRequest $request$column3Details null)
  250.     {
  251.         $numColumns count($renderingData['columns']);
  252.         // We want an array of column dependencies for each column; a non-dependent column doesn't have its own, so we'll patch in this array:
  253.         $noDependencies = array(=> 'none'=> 'none'=> 'none');
  254.         // This array says which columns have any dependencies at all (used to determine if we need to process dependencies in the first place)
  255.         $isDependent = array();
  256.         // And this array says exactly which columns depend on which other ones, and how
  257.         $columnDependencies = array();
  258.         // While we set up those arrays, we'll try to resolve optional self-dependencies that don't have other dependencies attached
  259.         foreach($renderingData['columns'] as $columnNum => $columnData) {
  260.             if($columnData['column_type'] === 'dependent') {
  261.                 $columnDependencies[$columnNum] = $columnData['depends_on'];
  262.                 $onlyOptionalSelfDependency true;
  263.                 foreach($columnDependencies[$columnNum] as $dependencyColumnNum => $dependencyType) {
  264.                     // Need == here instead of === because we might be comparing strings to integers
  265.                     if( ($dependencyColumnNum == $columnNum && $dependencyType !== 'optional')
  266.                         || ($dependencyColumnNum != $columnNum && $dependencyType !== 'none')
  267.                     ) {
  268.                         $onlyOptionalSelfDependency false;
  269.                     }
  270.                 }
  271.                 if($onlyOptionalSelfDependency) {
  272.                     $columnDetailVar 'column'.$columnNum.'Details';
  273.                     $columnData $this->convertColumnData($columnDetailVar$columnNum$request$columnNum$renderingData);
  274.                     $renderingData['columns'][$columnNum] = $columnData;
  275.                     if($columnData['column_type'] === 'dependent') {
  276.                         $columnDependencies[$columnNum] = $columnData['depends_on'];
  277.                     } else {
  278.                         $columnDependencies[$columnNum] = $noDependencies;
  279.                     }
  280.                 }
  281.             } else {
  282.                 $columnDependencies[$columnNum] = $noDependencies;
  283.             }
  284.             $isDependent[$columnNum] = $columnData['column_type'] === 'dependent';
  285.         }
  286.         // Double-check that we actually need to resolve dependencies (i.e. at least one column is dependent)
  287.         if(!in_array(true$isDependent)) {
  288.             return $this->createMulticolumnView($renderingData$request);
  289.         }
  290.         // Check for cycles: make sure no column that has a required dependency on itself ...
  291.         if( ($columnDependencies[1][1] === 'required')
  292.             || ($columnDependencies[2][2] === 'required')
  293.             || ($numColumns === && $columnDependencies[3][3] === 'required')
  294.         ) {
  295.             throw new \Exception('Invalid column specification: Required self-dependency');
  296.         }
  297.         // ... at least one column can, if necessary, be built without using dependencies ...
  298.         $numRequiredDependencies 0;
  299.         if($columnDependencies[1][2] === 'required' || $columnDependencies[1][3] === 'required') {
  300.             $numRequiredDependencies++;
  301.         }
  302.         if($columnDependencies[2][1] === 'required' || $columnDependencies[2][3] === 'required') {
  303.             $numRequiredDependencies++;
  304.         }
  305.         if($numColumns === && ($columnDependencies[3][1] === 'required' || $columnDependencies[3][1] === 'required')) {
  306.             $numRequiredDependencies++;
  307.         }
  308.         if($numRequiredDependencies === $numColumns) {
  309.             throw new \Exception('Invalid column specification: All columns have required dependencies');
  310.         }
  311.         // ... and no mutual required dependencies
  312.         // (Note: if there are 2 columns, we will have already caught this case because all columns are dependent)
  313.         if($numColumns === && (
  314.                 ($columnDependencies[1][2] === 'required' && $columnDependencies[2][1] === 'required')
  315.                 || ($columnDependencies[1][3] === 'required' && $columnDependencies[3][1] === 'required')
  316.                 || ($columnDependencies[2][3] === 'required' && $columnDependencies[3][2] === 'required')
  317.         )) {
  318.             throw new \Exception('Invalid column specification: Two columns depend on each other');
  319.         }
  320.         // Also, let's make sure there are no required dependencies on the third column if it doesn't exist
  321.         if($numColumns === && ($columnDependencies[1][3] === 'required' || $columnDependencies[2][3] === 'required')) {
  322.             throw new \Exception('Invalid column specification: Required dependency on a nonexistent column');
  323.         }
  324.         // At this point, we have made sure that:
  325.         // (a) at least one dependency needs to be resolved
  326.         // (b) there is a way to acceptably resolve all dependencies
  327.         // Now we need to actually do the dependency resolution
  328.         // (keeping in mind that we should have already resolved optional self-dependencies).
  329.         if($numColumns === 2) {
  330.             // If only two total columns, then there can only be one required dependency (or we would have thrown an exception earlier)
  331.             // ... but there still might be mutual dependencies if at least one is optional, in which case we must process the optional dependency first.
  332.             // So we'll process optional dependencies first, then required dependencies.
  333.             // In case of mutual optional dependencies, this code should work OK, simply by arbitrarily processing column 1 first.
  334.             // In other cases, it will work because there will only be one dependency at most.
  335.             if($columnDependencies[1][2] === 'optional') {
  336.                 $renderingData['columns'][1] = $this->convertColumnData($column1Details1$request1$renderingData);
  337.             }
  338.             if($columnDependencies[2][1] === 'optional') {
  339.                 $renderingData['columns'][2] = $this->convertColumnData($column2Details2$request2$renderingData);
  340.             }
  341.             if($columnDependencies[1][2] === 'required') {
  342.                 $renderingData['columns'][1] = $this->convertColumnData($column1Details1$request1$renderingData);
  343.             }
  344.             if($columnDependencies[2][1] === 'required') {
  345.                 $renderingData['columns'][2] = $this->convertColumnData($column2Details2$request2$renderingData);
  346.             }
  347.             return $this->createMulticolumnView($renderingData$request);
  348.         }
  349.         /*
  350.          * If we get to this point, then we should have three columns.
  351.          * We'll use the following priority list to process one column at a time until there are no more to process:
  352.          * 1. If possible, process a column which doesn't depend on other columns that also have dependencies.
  353.          *    (In other words, it depends only on non-dependent columns and/or itself.)
  354.          * 2. If no such column exists, process a column that meets similar criteria, except that it:
  355.          *    (a) can also have optional dependencies on columns that have required dependencies
  356.          *    (b) MUST have another column that depends on it
  357.          * 3. If no column fits either of the first two cases, process any column that doesn't have a required dependency on a dependent column.
  358.          *
  359.          * These criteria will always match at least one column, as long as there isn't a required dependency loop,
  360.          * and are intended to maximize the likelihood that required dependencies will have appropriate content in the column they depend on.
  361.          * (They probably aren't the best possible rules, but they should at least work well for all common cases and not completely break even in corner cases.)
  362.          *
  363.          * The numbers 1, 2, 3 are used in some places in the code below to indicate the priority tiers given above.
  364.          */
  365.         $strongestDependencies = array(=> 'none'=> 'none'=> 'none');
  366.         foreach($columnDependencies as $columnNum => $columnDependsOn) {
  367.             if(in_array('required'$columnDependsOn)) {
  368.                 $strongestDependencies[$columnNum] = 'required';
  369.             } elseif(in_array('optional'$columnDependsOn)) {
  370.                 $strongestDependencies[$columnNum] = 'optional';
  371.             }
  372.         }
  373.         for($numProcessed 0; ; $numProcessed++) {
  374.             // When no columns have dependencies left, we can stop with dependency resolution and return to normal view generation
  375.             if($strongestDependencies[1] === 'none' && $strongestDependencies[2] === 'none' && $strongestDependencies[3] === 'none') {
  376.                 return $this->createMulticolumnView($renderingData$request);
  377.             }
  378.             if($numProcessed >= 6) {
  379.                 // If we reach this, then on average, we've run convertColumnData TWICE PER COLUMN and still haven't resolved everything!
  380.                 // So we'll throw in a failsafe in case we somehow get into an infinite loop
  381.                 throw new \Exception('Unexpected error: Excessive repeated processing of dependencies');
  382.             }
  383.             $topPriorityRank 99// where 99 is just an arbitrary number later than any priority we actually use
  384.             $topPriorityColumnNum null;
  385.             foreach($renderingData['columns'] as $columnNum => $columnData) {
  386.                 // Non-dependent columns can't be candidates for processing
  387.                 if($columnData['column_type'] !== 'dependent') {
  388.                     continue;
  389.                 }
  390.                 $runningPriorityMeasure 1;
  391.                 foreach($columnData['depends_on'] as $otherColumnNum => $dependencyLevel) {
  392.                     /*
  393.                      * The following don't affect priority:
  394.                      * (optional) self-dependencies
  395.                      * columns that this column doesn't depend on
  396.                      * dependencies on non-dependent columns
  397.                      */
  398.                     if($otherColumnNum == $columnNum || $dependencyLevel === 'none' || $strongestDependencies[$otherColumnNum] === 'none') {
  399.                         continue;
  400.                     } elseif($dependencyLevel === 'required') {
  401.                         // We know the other column is dependent (or else we would have fallen into the previous if case).
  402.                         // A column with a required dependency on a dependent column is never a candidate for dependency resolution.
  403.                         continue 2;
  404.                     } elseif($strongestDependencies[$otherColumnNum] === 'optional') {
  405.                         // A dependency on a column with optional dependencies knocks this column to priority 3
  406.                         $runningPriorityMeasure 3;
  407.                     } elseif($runningPriorityMeasure === 1) {
  408.                         // Here, we know this is an optional dependency (or else we would have hit the first or second case)
  409.                         // on a column that has a required dependency (or else we would have hit the first or third case).
  410.                         // Such a thing can't exist in priority case 1, but can exist in priority case 2.
  411.                         $runningPriorityMeasure 2;
  412.                     }
  413.                 }
  414.                 // The above loop figures out where this column's outgoing dependencies fit into the priority scheme.
  415.                 // For priority 2, we also need to check whether the column has an incoming dependency.
  416.                 if($runningPriorityMeasure === 2) {
  417.                     // We'll temporarily set priority to 3, then revert to 2 if we find an incoming dependency
  418.                     $runningPriorityMeasure 3;
  419.                     foreach($columnDependencies as $sourceColumnNum => $dependencyData) {
  420.                         if($sourceColumnNum == $columnNum) {
  421.                             // Self-dependencies don't count here
  422.                             continue;
  423.                         } elseif($dependencyData[$columnNum] !== 'none') {
  424.                             // Incoming dependency! No need to continue the loop now that we know such a dependency exists.
  425.                             $runningPriorityMeasure 2;
  426.                             break;
  427.                         }
  428.                     }
  429.                 }
  430.                 // The value of $runningPriorityMeasure should now indicate the final priority for this column.
  431.                 // If it's an earlier priority than our previous best, then set this column as the new first priority.
  432.                 if($runningPriorityMeasure $topPriorityRank) {
  433.                     $topPriorityRank $runningPriorityMeasure;
  434.                     $topPriorityColumnNum $columnNum;
  435.                 }
  436.             } // end "find column with top priority" loop foreach($renderingData['columns'] as $columnNum => $columnData)
  437.             if($topPriorityColumnNum !== null) {
  438.                 $columnDetailVar 'column'.$topPriorityColumnNum.'Details';
  439.                 $newColumnData $this->convertColumnData($columnDetailVar$topPriorityColumnNum$request$topPriorityColumnNum$renderingData);
  440.                 $renderingData['columns'][$topPriorityColumnNum] = $newColumnData;
  441.                 if($newColumnData['column_type'] === 'dependent') {
  442.                     $columnDependencies[$topPriorityColumnNum] = $newColumnData['depends_on'];
  443.                     if(in_array('required'$newColumnData['depends_on'])) {
  444.                         $strongestDependencies[$topPriorityColumnNum] = 'required';
  445.                     } else {
  446.                         $strongestDependencies[$topPriorityColumnNum] = 'optional';
  447.                     }
  448.                 } else {
  449.                     $columnDependencies[$topPriorityColumnNum] = $noDependencies;
  450.                     $strongestDependencies[$topPriorityColumnNum] = 'none';
  451.                 }
  452.             } else {
  453.                 // There must be SOME dependency, or else we would have broken the loop near the beginning of the iteration.
  454.                 // But we haven't found any column that matches any of our criteria for choosing which column to process ...
  455.                 throw new \Exception('Unexpected error: Expected a resolvable column dependency but could not find one');
  456.             }
  457.         } // end dependency processing loop for($numProcessed = 0; ...)
  458.     }
  459.     protected function createMulticolumnView($renderingData$request)
  460.     {
  461.         // Certain types of content require additional data for certain purposes -- e.g. Bible content needs a list of all Bible translations
  462.         $this->checkIfOnMobile($request); 
  463.         $locale $request->getLocale();
  464.         $hasBible false;
  465.         $hasSwedenborg false;
  466.         $hasOther false;
  467.         $hasStory false;
  468.         $nStoryID null;
  469.         $book_translation null;
  470.         $book null;
  471.         $sCommentaryUrl null;
  472.         foreach($renderingData['columns'] as $columnNum => $singleColumnData) {
  473.             if($singleColumnData['column_type'] === 'bible') {
  474.                 $hasBible true;
  475.                 $book_translation $singleColumnData['translation'];
  476.                 $book $singleColumnData['book'];
  477.                 
  478.                 if(isset($singleColumnData['content_category']) && $singleColumnData['content_category'] === 'st')
  479.                     $hasStory true;    
  480.             } elseif($singleColumnData['column_type'] === 'exposition' && !isset($singleColumnData['translation'])) {
  481.                 // Do nothing (specifically, don't try to use $singleColumnData['translation'] in the next two clauses)                
  482.             } elseif($singleColumnData['column_type'] === 'exposition') {
  483.                 if($this->isSwedenborg($singleColumnData['translation']->getId()))
  484.                     $hasSwedenborg true;
  485.                 else
  486.                     $hasOther true;    
  487.             } 
  488.             elseif($singleColumnData['column_type'] === 'exposition'
  489.             {     
  490.                 //$aStory = $singleColumnData['translation']->getWork()->getStories();
  491.                 $aStory $this->getStoryInfo($singleColumnData['translation']->getId());
  492.                 if(!empty($aStory))
  493.                 {                   
  494.                     $nLevelID $aStory['level_id'];               
  495.                     if($nLevelID == $this->STORY_LEVEL_ID_BIBLE)
  496.                     {  
  497.                         $hasStory true;                                             
  498.                     }
  499.                     elseif($nLevelID == $this->STORY_LEVEL_ID_CHAPTER)
  500.                         $renderingData['is_chapter_explanation'] = '1';
  501.                     elseif($nLevelID == $this->STORY_LEVEL_ID_VERSE)
  502.                         $renderingData['is_verse_explanation'] = '1';    
  503.                     
  504.                     $nStoryID $aStory['story_id'];
  505.                     $renderingData['story_id'] = $nStoryID;
  506.                     
  507.                     $sCommentaryUrl "";                    
  508.                     if(isset($singleColumnData['translation_url']))                        
  509.                         $sCommentaryUrl $singleColumnData['translation_url']; 
  510.                 }    
  511.             }
  512.             // While we're looping through the columns, we'll also find and apply any uri overrides (used e.g. with story explanations)
  513.             if(array_key_exists('column_uri_override'$singleColumnData)) {
  514.                 $renderingData['multicolumn_route_params']['column'.$columnNum.'Details'] = $singleColumnData['column_uri_override'];
  515.             }
  516.             // Also, check for unresolved dependencies
  517.             if($singleColumnData['column_type'] === 'dependent') {
  518.                 $singleColumnData['errors'][] = array('code' => '500''message' => 'unresolveddependency');
  519.             }
  520.         }
  521.   
  522.  /*       if($hasSwedenborg) {
  523.            // $renderingData['swedenborg_works'] = $this->getCategorizedSwedenborgWorks($request);
  524.         } */
  525.         if($hasStory && $nStoryID != null) {
  526.             $aAllStory = array();
  527.             $aSearchedStory $request->getSession()->get('searched_bible_story_list');
  528.             if(!empty($aSearchedStory))
  529.             {
  530.                 foreach($aSearchedStory as $s)
  531.                 {                
  532.                     if($s['commentary_url'] == $sCommentaryUrl)
  533.                     {
  534.                         $aAllStory $aSearchedStory;
  535.                         break;
  536.                     }
  537.                 }
  538.             }
  539.             
  540.             if(empty($aAllStory))
  541.             {
  542.                 $aAllStory $this->getExplainedStoryList($locale);
  543.             }
  544.         //    print_r($aAllStory);
  545.             $renderingData['all_stories'] = $aAllStory;
  546.             $renderingData['story_explanations'] = $this->getWorkListForStory($locale$nStoryID);
  547.             $renderingData['story_id'] = $nStoryID;
  548.                         
  549.             if(!empty($book_translation))
  550.                 $renderingData['book_translation_url'] = $book_translation['url'];
  551.                 
  552.            // if(!empty($sCommentaryUrl))
  553.                 $renderingData['commentary_url'] = $sCommentaryUrl;    
  554.         }
  555.         $response null;
  556.         $returnErrorStatusCode null;
  557.         foreach($renderingData['columns'] as $columnNum => $singleColumnData) {
  558.             if(array_key_exists('errors'$singleColumnData)) {
  559.                 foreach($singleColumnData['errors'] as $error) {
  560.                     // If different columns have different problems, we can still only send one HTTP status code.
  561.                     // Coincidentally, among the four most likely error codes, it's better to send the lower-numbered ones:
  562.                     // 301 (permanent redirect) over 302 (temporary redirect) over 404 (not found) over 500 (server error)
  563.                     // (note that this does NOT work with code 200 (OK), which we don't want to use if there's anything remotely like an error)
  564.                     if($returnErrorStatusCode === null || $error['code'] < $returnErrorStatusCode) {
  565.                         $returnErrorStatusCode $error['code'];
  566.                     }
  567.                 }
  568.             }
  569.         }
  570.         if($returnErrorStatusCode !== null) {
  571.             $response = new Response();
  572.             $response->setStatusCode($returnErrorStatusCode);
  573.         }
  574.         $nLinkTypeID $this->LINK_TYPE_ID_OTHER;
  575.         if(!$hasOther)
  576.         {
  577.             if($hasBible && !$hasSwedenborg)
  578.             {
  579.                 $nLinkTypeID $this->LINK_TYPE_ID_BIBLE;
  580.             }
  581.             else if(!$hasBible && $hasSwedenborg)
  582.             {
  583.                 $nLinkTypeID $this->LINK_TYPE_ID_SWEDENBORG;
  584.             }
  585.         }
  586.         $renderingData['linktype_id'] = $nLinkTypeID;
  587.         
  588.         return $this->renderView('multicolumn/generic_multicolumn'$renderingData$response);
  589.     }
  590.     protected function convertColumnData($columnDetails$column_number$request$targetColumnNum null$renderingData null)
  591.     {
  592.         $dataElementDetails explode('_'strtolower($columnDetails));
  593.         $domainIndicator array_shift($dataElementDetails);
  594.         if($domainIndicator === $this->MULTI_URL_INDICATOR_BIBLE || $domainIndicator === $this->MULTI_URL_INDICATOR_BIBLE_STORYTEXT) {
  595.             return $this->bibleColumnDataNew($columnDetails$column_number$request$targetColumnNum$renderingData);
  596.         }
  597.         else if($domainIndicator === $this->MULTI_URL_INDICATOR_SWEDENBORG_WORK || $domainIndicator === $this->MULTI_URL_INDICATOR_EXPLANATION) {
  598.             return $this->expositionColumnDataNew($columnDetails$column_number$request$targetColumnNum$renderingData);
  599.         }
  600.         else
  601.         {        
  602.             // old functions, keep them for bible stories
  603.     /*        if($domainIndicator === 'b') {
  604.                 return $this->bibleColumnData($dataElementDetails, $column_number, $request, $targetColumnNum, $renderingData);
  605.             }
  606.             else if($domainIndicator === 'e') {
  607.                 return $this->expositionColumnData($dataElementDetails, $column_number, $request, $targetColumnNum, $renderingData);
  608.             } */
  609.         }
  610.         return $this->badColumnRequestData($columnDetails$targetColumnNum$renderingData);
  611.     }
  612.     protected function badColumnRequestData($columnDetails$targetColumnNum$renderingData)
  613.     {
  614.         $rval = array('column_type' => 'unrecognized');
  615.         $rval['errors'][] = array('code' => 404'message' => 'badcolumnrequest');
  616.         return $rval;
  617.     }
  618.     public function storyExplanationAction($storyUrlRequest $request$bibleTranslationUrl null$commentaryUrl null)
  619.     {
  620.         $locale $request->getLocale();
  621.         $response null;
  622.         $story $this->bibleData('Stories\Story')->findOneBy(array('url' =>$storyUrl'level_id' => $this->STORY_LEVEL_ID_BIBLE'isPublic' => true)); 
  623.         if($story==null)
  624.         {
  625.             $response = new Response();
  626.             $response->setStatusCode(404);
  627.             return $this->renderView('no_content_back', array(), $response);
  628.         }       
  629.                 
  630.         if($locale != 'en')
  631.         {
  632.             $sStoryName $this->getBibleStoryName($story->getId(), $locale); 
  633.             if(!empty($sStoryName))
  634.                 $story->setName($sStoryName);
  635.         }  
  636.         
  637.         $sCommentaryUrl $commentaryUrl;
  638.         if($sCommentaryUrl == null)
  639.         {
  640.             $sCommentaryUrl $this->getCommentaryUrl($story->getId(), $bibleTranslationUrl);
  641.         }
  642.         else
  643.         {
  644.             $sCommentaryUrl $this->getPublicCommentaryUrl($story->getId(), $commentaryUrl);
  645.         }    
  646.         
  647.         if($sCommentaryUrl == '')
  648.         {
  649.             $response = new Response();
  650.             $response->setStatusCode(404);
  651.             return $this->renderView('no_content_back', array(), $response);
  652.         }
  653.                                           
  654.         $renderingData = array('route_story' => $story);        
  655.         $renderingData['commentary_url_from_link'] = $commentaryUrl;
  656.                 
  657.         $storySpec $this->MULTI_URL_INDICATOR_BIBLE_STORYTEXT '_' $story->getUrl();
  658.         $renderingData['right_to_left'] = False;
  659.         if($bibleTranslationUrl !== null) {
  660.         
  661.             if($bibleTranslationUrl !== $this->DEFAULT_BIBLE_VERSION)
  662.             {
  663.                 // check bible translation match
  664.                 $bHasBibleBookForTrans $this->HasBibleBookForTrans($request$story->getId(), $bibleTranslationUrl);
  665.                 if(!$bHasBibleBookForTrans)
  666.                 {
  667.                     $bibleTranslationUrl $this->DEFAULT_BIBLE_VERSION;
  668.                     if($commentaryUrl != null)
  669.                     {
  670.                         return $this->redirect($this->get('router')->generate('bible_translated_story_for_commentary', array(
  671.                             'storyUrl' => $storyUrl,
  672.                             'bibleTranslationUrl' => $bibleTranslationUrl,
  673.                             'commentaryUrl' => $commentaryUrl
  674.                         )), 301);
  675.                     }
  676.                     else 
  677.                     { 
  678.                         return $this->redirect($this->get('router')->generate('bible_translated_story', array(
  679.                             'storyUrl' => $storyUrl,
  680.                             'bibleTranslationUrl' => $bibleTranslationUrl
  681.                         )), 301);
  682.                     }
  683.                 }
  684.             }
  685.         
  686.             $bibleTranslation $this->bibleData('Translation')->findOneBy(array('url' => $bibleTranslationUrl'enabled' => true));
  687.             
  688.             if($bibleTranslation !== null)
  689.             {
  690.                 $renderingData['route_bible_translation'] = $bibleTranslation;
  691.                 $storySpec .= '_'.$bibleTranslation->getUrl();
  692.                 $renderingData['right_to_left'] = $bibleTranslation->getLanguage()->getRightToLeft();  
  693.             }                 
  694.         }
  695.                 
  696.         $renderingData['content_class'] = 'story';
  697.         
  698.         $explanationSpec $this->MULTI_URL_INDICATOR_EXPLANATION '_' $sCommentaryUrl;
  699.         $this->setCurrentUrl($request);         
  700.         return $this->multicolumnAction($storySpec$explanationSpec$requestnull$renderingData);
  701.     }
  702.     
  703.     public function showExceptionAction()
  704.     {        
  705.         return $this->renderView('no_content', array(), $response);
  706.     }
  707.     
  708.     public function storyRedirectAction($storyUrlRequest $request)
  709.     {
  710.         $bibleTranslationUrl $this->DEFAULT_BIBLE_VERSION;
  711.         $nBibleTransID $request->getSession()->get('current_bible_translation_id');
  712.         if($nBibleTransID != '')
  713.         {
  714.    //         $bibleTranslation = $this->getRepository('Bible\Translation')->findOneById($nBibleTransID);
  715.    //         $bibleTranslationUrl = $bibleTranslation->getUrl();
  716.    
  717.                $bibleTranslation $this->getBibleTranslationByID($request$nBibleTransID);
  718.                $bibleTranslationUrl $bibleTranslation['url'];
  719.         }
  720.         
  721.         return $this->redirect($this->get('router')->generate('bible_translated_story', array(
  722.                     'storyUrl' => $storyUrl,
  723.                     'bibleTranslationUrl' => $bibleTranslationUrl
  724.                 )), 301);
  725.         //return $this->redirect('/bible/story/'.$storyUrl.'/'.$bibleTranslationUrl);
  726.     }
  727.     
  728.     // Anytime you are reading content that has a link to other content, if available, 
  729.     // link to a translation of the new content in the same language as the content that links to it. 
  730.     public function checkBibleTranslation($vTranslation$vLanguage)
  731.     {        
  732.         $ret $this->bibleData('Translation')->findOneBy(array('language' => $vLanguage'enabled'=> true'languageDefault' => true));
  733.         if($ret == null)
  734.             $ret $this->bibleData('Translation')->findOneBy(array('language' => $vLanguage'enabled' => true));
  735.                             
  736.         return $ret;        
  737.     }     
  738.     
  739.     function getQBibleUrl($book$chapter$verses$isCanonical)
  740.     {
  741.         if($isCanonical)
  742.             $cbook $book;
  743.         else
  744.             $cbook $book->getCanonicalization();
  745.                         
  746.         $nCBookId $cbook->getId();
  747.         $nChapterOrder $chapter->getOrdering();
  748.         $nVerseOrder 1;
  749.         foreach($verses as $key => $val) {
  750.             if(!is_array($val)) {
  751.                 $nVerseOrder $val->getIndexDisplay();  
  752.                 break;              
  753.             }
  754.         }
  755.                        
  756.         $nTestmentId $cbook->getTestament()->getId();
  757.         $sLinkStart '';
  758.         if($nTestmentId == 1// old testament
  759.             $sLinkStart 'http://qbible.com/hebrew-old-testament/';
  760.         else
  761.             $sLinkStart 'http://qbible.com/greek-new-testament/';    
  762.     
  763.         return $this->getNativeQueryResults("SELECT '" $sLinkStart "' || qbible_url || '/' || '" $nChapterOrder "' || '.html#' || '" $nVerseOrder "' as url from canonicalbiblebook"                
  764.                 ." WHERE id = " $nCBookId " and qbible_url is not null and qbible_url <> ''");
  765.     } 
  766.     
  767.     function getFirstExplanationID($story_id)
  768.     {        
  769.         $sSql "SELECT work_id"
  770.                 ." FROM story_work"
  771.                 ." WHERE story_id = " $story_id " order by ordering";
  772.         $sRet '';
  773.         $aRet $this->getNativeQueryResults($sSql);
  774.         if(count($aRet) > 0
  775.             $sRet implode(''$aRet[0]);        
  776.               
  777.         return $sRet;    
  778.     }  
  779.     
  780.     function getFirstExplanation($explanationOptions$firstExplanationID)
  781.     {
  782.         $firstExplanation null;
  783.         foreach($explanationOptions as $expanation)
  784.         {
  785.             if($expanation->getId() == $firstExplanationID)
  786.             {
  787.                 $firstExplanation $expanation;
  788.                 break;
  789.             }
  790.         }
  791.         
  792.         if($firstExplanation == null)
  793.             $firstExplanation $explanationOptions[0];
  794.             
  795.         return $firstExplanation;    
  796.     }
  797.     
  798.     protected function bibleColumnDataNew($columnDetails$column_number$request$targetColumnNum null$renderingData null)
  799.     {
  800.         // Old Possible formats:
  801.         // b_c_### (chapter by id)
  802.         // b_c_###-### (chapter range by ids)
  803.         // b_v_### (verse by ids)
  804.         // b_v_###-### (verse range by ids, possibly spanning multiple chapters)
  805.         // To use canonical numbering, replace "c" with "cc" or "v" with "cv" in the above
  806.         // b_st_### (bible text for the story with the given id)
  807.         // Canonical-numbered content (including stories) will use default or arbitrary translation; adding "_###" to the end specifies the translation ID
  808.         
  809.         // e.g. bible_king-james-version_genesis_1_2
  810.         
  811.         $dataElementDetails explode('_'strtolower($columnDetails));
  812.         $domainIndicator array_shift($dataElementDetails);
  813.         $columnSpec $dataElementDetails;                   
  814.                 
  815. //echo 'ttt1:'.time(); 
  816.         $chapterExplanation null;
  817.         $qbible_link null;
  818.         $verses null;
  819.         $translation = array();
  820.         $nChapterId null;
  821.         $nLastChapterId null;
  822.         $nVerseId null;
  823.         $isCanonical false;                
  824.         $nextChapter null;
  825.           $prevChapter null;
  826.           $nextVerse null;
  827.           $prevVerse null;  
  828.           
  829.           $nSpecCount count($columnSpec);        
  830.         $bChapterLevel false;
  831.         $bVerseLevel false;
  832.         $bStoryText = ($domainIndicator === $this->MULTI_URL_INDICATOR_BIBLE_STORYTEXT);
  833.         $aChapter = array();
  834.         $aVerse = array();
  835.         $nChapterNum null;
  836.         $nLastChapterNum null;
  837.         $sVerseIndex null;
  838.         $sLastVerseIndex null;
  839.         $sTranslationUrl null;
  840.         $firstChapter null;
  841.           
  842.           if(!$bStoryText)
  843.         {                  
  844.             $bChapterLevel = ($nSpecCount == 3);
  845.             $bVerseLevel = ($nSpecCount == 4);        
  846.             $sTranslationUrl array_shift($columnSpec);            
  847.             $sBookUrl array_shift($columnSpec);
  848.             $sChapterStr array_shift($columnSpec);
  849.             $aChapter explode('-'$sChapterStr);
  850.             $nChapterNum $aChapter[0];
  851.             if(count($aChapter) > 1)
  852.             {
  853.                 $nLastChapterNum $aChapter[1];
  854.                 if ( $nLastChapterNum $nChapterNum >= 
  855.                       $nLastChapterNum $nChapterNum+2;
  856.             }    
  857.                 
  858.             $nChapterIDCount count($aChapter);
  859.             if($bVerseLevel)
  860.             {
  861.                 $sVerseStr array_shift($columnSpec);    
  862.                 $aVerse explode('-'$sVerseStr);
  863.                 $nVerseIDCount count($aVerse);
  864.                 $sVerseIndex $aVerse[0];
  865.                 if($nVerseIDCount 1)
  866.                     $sLastVerseIndex $aVerse[1];
  867.             }     
  868.             
  869.             $nChapterId $this->getBibleChapterID($sTranslationUrl$sBookUrl$nChapterNum);      
  870.             if($nLastChapterNum != null)
  871.                 $nLastChapterId $this->getBibleChapterID($sTranslationUrl$sBookUrl$nLastChapterNum);
  872.             
  873.             if($nChapterId == null)
  874.             {
  875.                 $nChapterNum 1;
  876.                 $bChapterLevel true;
  877.                 $nChapterId $this->getBibleChapterID($sTranslationUrl$sBookUrl$nChapterNum); 
  878.             }
  879.             
  880.             if($nChapterId == null)
  881.                 return array();
  882.                  
  883.               $translation $this->getBibleTranslationByChapter($request$nChapterId$isCanonical);       
  884.         }
  885.         else
  886.         {
  887.             $sStoryUrl array_shift($columnSpec);
  888.             $sTranslationUrl array_shift($columnSpec);
  889.         }
  890.         
  891.         $contentCategory '';
  892.         if($bStoryText)
  893.             $contentCategory 'st';
  894.         else if ($bChapterLevel)
  895.             $contentCategory 'c';
  896.         else
  897.             $contentCategory 'v';    
  898.                   
  899.         if($bChapterLevel) {  
  900.             $chapterRepos $this->bibleData($isCanonical 'Canonical\Chapter' 'Chapter');
  901.             $firstChapter $chapterRepos->findOneById($nChapterId);
  902.             $lastChapter null;
  903.             $chapterEndIndex null;
  904.             if($firstChapter !== null) {
  905.                 $book $firstChapter->getBook();
  906.                 $chapterStartIndex $firstChapter->getOrdering();
  907.                 if($nChapterIDCount == || !empty($nLastChapterId)) {
  908.                     $lastChapter null;
  909.                     $chapterEndIndex null;
  910.                 } else {
  911.                 //    $nLastChapterNum = $aChapter[1];
  912.                 //    $nLastChapterId = $this->getBibleChapterID($sTranslationUrl, $sBookUrl, $nLastChapterNum);
  913.                     if(!empty($nLastChapterId))
  914.                     {
  915.                         $lastChapter $chapterRepos->findOneById($nLastChapterId);
  916.                         $chapterEndIndex $lastChapter->getOrdering();
  917.                     }                    
  918.                 }
  919.             } else {
  920.                 $book null;
  921.                 $lastChapter null;
  922.                 $chapterStartIndex null;
  923.                 $chapterEndIndex null;
  924.             }
  925.             $verseStartIndex null;
  926.             $verseEndIndex null;
  927.             $rangeStart $firstChapter;
  928.             $rangeEnd $lastChapter
  929.             
  930.             if($chapterExplanation == null && !empty($translation))
  931.             {            
  932.                 // get chapter explanation                    
  933.                 $chapterExplanation $this->getChapterExplanation($translation['chapter_id'], $sTranslationUrl$request); 
  934.                 $nextChapter $this->getNextChapter($nChapterId);
  935.                   $prevChapter $this->getPreviousChapter($nChapterId);
  936.             }
  937.             
  938.             $nCChapterID null;
  939.             if($isCanonical)
  940.                 $nCChapterID $firstChapter->getId();
  941.             else
  942.             {
  943.                 $cchapter $firstChapter->getCanonicalization();
  944.                 if($cchapter != null)
  945.                     $nCChapterID $cchapter->getId();    
  946.             }            
  947.             // It's very slow, we will find a better way to do it
  948.              $nExplainChapterTranslationID $this->getExplainChapterTranslation($nCChapterID$this->getCurrUserID($request), $sTranslationUrl);            
  949.               if($nExplainChapterTranslationID > -1)
  950.               {                  
  951.                   if($request->getSession()->get('has_explanation_cchapter_id_temp_bible') == '1')
  952.                 {
  953.                     // For multi-column views, explain chapter icon is not shown 
  954.                     // if there are more than 1 chapter column
  955.                     $request->getSession()->set('current_explanation_cchapter_id_temp_bible''');
  956.                     $request->getSession()->set('current_explanation_translation_id_temp_bible''');                   
  957.                 }
  958.                 else
  959.                 {
  960.                     $request->getSession()->set('has_explanation_cchapter_id_temp_bible''1'); 
  961.                     $request->getSession()->set('current_explanation_cchapter_id_temp_bible'$nCChapterID); 
  962.                       $request->getSession()->set('current_explanation_translation_id_temp_bible'$nExplainChapterTranslationID);  
  963.                 }       
  964.               }       
  965.         } else {
  966.             if($bStoryText) {    
  967.                 $isCanonical true;                        
  968.                 if(empty($sStoryUrl)) {
  969.                     $story null;
  970.                     $firstVerse null;
  971.                     $lastVerse null;
  972.                 } else {
  973.                     $story $this->bibleData('Stories\Story')->findOneBy(array('url' => $sStoryUrl'level_id' => $this->STORY_LEVEL_ID_BIBLE'isPublic' => true));
  974.                     if($story === null) {
  975.                         $firstVerse null;
  976.                         $lastVerse null;
  977.                     } else {
  978.                         $firstVerse $story->getStartVerse();
  979.                         $lastVerse $story->getEndVerse();  
  980.                         
  981.                         if($chapterExplanation == null && $firstVerse !== null)
  982.                         {                     
  983.                             $firstChapter $firstVerse->getChapter(); 
  984.                             $CChapter $firstChapter;
  985.                             if($CChapter != null)
  986.                             {
  987.                                 $nChapterId $CChapter->getId();
  988.                                 $chapterExplanation $this->getChapterExplanation($nChapterId$sTranslationUrl$request);
  989.                             }
  990.                             $nextChapter $this->getNextChapter($firstChapter->getId());
  991.                               $prevChapter $this->getPreviousChapter($firstChapter->getId());
  992.                         }                
  993.                     }
  994.                 }
  995.             } else {            
  996.                 $verseRepos $this->bibleData($isCanonical 'Canonical\Verse' 'Verse');
  997.                 $nVerseId $this->getBibleVerseID($sTranslationUrl$sBookUrl$nChapterNum$sVerseIndex); 
  998.                   if($nVerseId == null)
  999.                   {
  1000.                       $sTranslationUrl $this->DEFAULT_BIBLE_VERSION;
  1001.                       $nVerseId $this->getBibleVerseID($sTranslationUrl$sBookUrl$nChapterNum$sVerseIndex);
  1002.                   }    
  1003.                            
  1004.                 $firstVerse $verseRepos->findOneById($nVerseId);
  1005.                 
  1006.                 $lastVerse null;
  1007.                 if($sLastVerseIndex != null)
  1008.                 {
  1009.                     if($nLastChapterNum != null)
  1010.                         $nLastVerseId $this->getBibleVerseID($sTranslationUrl$sBookUrl$nLastChapterNum$sLastVerseIndex);
  1011.                     else
  1012.                         $nLastVerseId $this->getBibleVerseID($sTranslationUrl$sBookUrl$nChapterNum$sLastVerseIndex);
  1013.                             
  1014.                     $lastVerse $verseRepos->findOneById($nLastVerseId);
  1015.                 }
  1016.                 if(!$isCanonical) {
  1017.                     if($firstVerse !== null) {
  1018.                         $firstVerse $firstVerse->findMainVerse();
  1019.                     }
  1020.                     if($lastVerse !== null) {
  1021.                         $lastVerse $lastVerse->findMainVerse();
  1022.                     }                                        
  1023.              
  1024.                     if($chapterExplanation == null && $firstVerse !== null)
  1025.                     {                     
  1026.                         $firstChapter $firstVerse->getChapter(); 
  1027.                         $CChapter $firstChapter->getCanonicalization();
  1028.                         if($CChapter != null)
  1029.                         {
  1030.                             $nChapterId $CChapter->getId();
  1031.                             $chapterExplanation $this->getChapterExplanation($nChapterId$sTranslationUrl$request);
  1032.                         }
  1033.                         $nextChapter $this->getNextChapter($firstChapter->getId());
  1034.                           $prevChapter $this->getPreviousChapter($firstChapter->getId());
  1035.                     }                        
  1036.                 }     
  1037.                 if($nVerseId != null && $nVerseId != '')
  1038.                 {
  1039.                     $nextVerse $this->getNextVerse($nVerseId);
  1040.                       $prevVerse $this->getPreviousVerse($nVerseId); 
  1041.                   }          
  1042.             }
  1043.             if($firstVerse !== null) {
  1044.                 $firstChapter $firstVerse->getChapter();
  1045.                 $book $firstChapter->getBook();
  1046.                 $chapterStartIndex $firstChapter->getOrdering();                                
  1047.                 $verseStartIndex $contentCategory === 'v' $firstVerse->getIndexDisplay() : $firstVerse->getOrdering();
  1048.                 if($lastVerse === null) {
  1049.                     $chapterEndIndex null;
  1050.                     $verseEndIndex null;
  1051.                 } else {
  1052.                     $chapterEndIndex $lastVerse->getChapter()->getOrdering();
  1053.                     $verseEndIndex $contentCategory === 'v' $lastVerse->getIndexDisplay() : $lastVerse->getOrdering();
  1054.                 }
  1055.             } else {
  1056.                 $book null;
  1057.                 $chapterStartIndex null;
  1058.                 $verseStartIndex null;
  1059.                 $chapterEndIndex null;
  1060.                 $verseEndIndex null;
  1061.             }
  1062.             $rangeStart $firstVerse;
  1063.             $rangeEnd $lastVerse;            
  1064.         }
  1065.         
  1066.         if($bStoryText) { 
  1067.             if($sTranslationUrl == null) {
  1068.                 // default or arbitrary translation
  1069.                 // TODO: Select language-default translation for current or default language, or use last viewed translation
  1070.                 $nLanguageID null;
  1071.                 if($this->language1 !== null)
  1072.                     $nLanguageID $this->language1->getId();
  1073.                                      
  1074.                 if($book != null)
  1075.                 {
  1076.                     $translation $this->getBibleTranslationByCanonBookID($request$book->getId(), $nLanguageID);
  1077.                     
  1078.                     if(empty($translation))
  1079.                         $translation $this->getBibleTranslationByUrl($request$book->getTranslation()->getUrl(), $nLanguageID);        }
  1080.                 else
  1081.                 {
  1082.                     if($nLanguageID != null)
  1083.                         $translation $this->getBibleTranslationByLanguage($request$nLanguageID);
  1084.                      else
  1085.                          $translation $this->getBibleTranslationByUrl($request$this->DEFAULT_BIBLE_VERSION);                  
  1086.                 }             
  1087.             } else {
  1088.                 // translation ID provided, use that    
  1089.                    $translation $this->getBibleTranslationByUrl($request$sTranslationUrl);
  1090.             }
  1091.             
  1092.             if($sTranslationUrl == '')
  1093.             {                 
  1094.                 $sTranslationUrl $translation['url'];
  1095.             }
  1096.       } 
  1097.       else
  1098.       {          
  1099.         // If not canonical, get translation from book so we know what language to use for referring Swedenborg passages
  1100.         // (and so we can pass the translation to the template without having to first check whether we've defined it already)               
  1101.         
  1102.         if($sTranslationUrl != '')
  1103.             $translation $this->getBibleTranslationByUrl($request$sTranslationUrl); 
  1104.      }
  1105.      
  1106.          $sStoryTranslationUrl null;
  1107.         if($bStoryText && isset($translation['url'])) 
  1108.         {
  1109.             $sStoryTranslationUrl $translation['url'];            
  1110.         }
  1111.          
  1112.         $curr_book null;        
  1113.         if($book !== null) {   
  1114.             if($isCanonical)  
  1115.             {       
  1116.                 $book2 null;
  1117.                 if(!empty($translation) && isset($translation['id']))                  
  1118.                     $book2 $this->bibleData('Book')->getBookFromCanon($book->getId(), $translation['id']);
  1119.                     
  1120.                 if($book2 == null)
  1121.                 {
  1122.                     $book2 $this->bibleData('Book')->getBookFromCanon($book->getId(), $this->DEFAULT_BIBLE_TRANSLATION_ID);                    
  1123.                     $sTranslationUrl $this->DEFAULT_BIBLE_VERSION;
  1124.                     $translation $this->getBibleTranslationByUrl($request$sTranslationUrl);
  1125.                 }    
  1126.             }    
  1127.             else
  1128.                 $book2 $book;
  1129.                 
  1130.             $curr_book $book2;    
  1131.           
  1132.             $aCheck $this->checkBookInfo($book2->getId(), $chapterStartIndex$chapterEndIndex$verseStartIndex$verseEndIndex);
  1133.             if($chapterStartIndex != null && isset($aCheck['chapterStartIndex']))
  1134.                 $chapterStartIndex $aCheck['chapterStartIndex'];
  1135.                 
  1136.             if($chapterEndIndex != null && isset($aCheck['chapterEndIndex']))
  1137.                 $chapterEndIndex $aCheck['chapterEndIndex'];    
  1138.                 
  1139.             if($verseStartIndex != null && isset($aCheck['verseStartIndex']))
  1140.                 $verseStartIndex $aCheck['verseStartIndex'];
  1141.                 
  1142.             if($verseEndIndex != null && isset($aCheck['verseEndIndex']))
  1143.                 $verseEndIndex $aCheck['verseEndIndex']; 
  1144.                  
  1145.             $verses DataAssembly::getVerseRangeFromBook($book2$chapterStartIndex$chapterEndIndex$verseStartIndex$verseEndIndex);           
  1146.         } else {
  1147.           //  $verses = array();
  1148.             return array();
  1149.         }
  1150.                 
  1151.         $expositionRefTranslationMap = array();
  1152.         $allVerses array_reduce($verses'array_merge', array());
  1153.         
  1154.         $aTempChapter = array();
  1155.         if($bChapterLevel)        
  1156.             $aTempChapter[] = $firstChapter;
  1157.         $aVerseInfo $this->getVerseInfo($allVerses);   
  1158.         $bHasSliderItem $this->hasSliderItem($aVerseInfofalse$requesttrue);
  1159.         if($bHasSliderItem)
  1160.         {
  1161.             $sSliderUrl "";
  1162.     //    echo $verseStartIndex . ";;". $verseEndIndex;
  1163.             $sBookUrl $book->getUrl();
  1164.             if($bChapterLevel)
  1165.             {
  1166.                 $sSliderUrl $this->get('router')->generate('bible_slider_chapter', array(
  1167.                     'translationUrl' => $sTranslationUrl,
  1168.                     'bookUrl' => $sBookUrl,
  1169.                     'chapterIndex' => $chapterStartIndex
  1170.                 ));    
  1171.             }
  1172.             elseif($bVerseLevel)
  1173.             {
  1174.                 $sSliderUrl $this->get('router')->generate('bible_slider_verse', array(
  1175.                     'translationUrl' => $sTranslationUrl,
  1176.                     'bookUrl' => $sBookUrl,
  1177.                     'chapterIndex' => $chapterStartIndex,
  1178.                     'verseStartIndex' => $verseStartIndex
  1179.                 ));
  1180.             }
  1181.             else if($chapterEndIndex != null && $verseStartIndex != null)
  1182.             {
  1183.                 $sSliderUrl $this->get('router')->generate('bible_slider_chapter_range', array(
  1184.                     'translationUrl' => $sTranslationUrl,
  1185.                     'bookUrl' => $sBookUrl,
  1186.                     'chapterStartIndex' => $chapterStartIndex,
  1187.                     'chapterEndIndex' => $chapterEndIndex
  1188.                 ));
  1189.             }
  1190.             else if($chapterEndIndex != null && $verseStartIndex == null)
  1191.             {
  1192.                 $sSliderUrl $this->get('router')->generate('bible_slider_chapter_verse_range', array(
  1193.                     'translationUrl' => $sTranslationUrl,
  1194.                     'bookUrl' => $sBookUrl,
  1195.                     'chapterStartIndex' => $chapterStartIndex,
  1196.                     'chapterEndIndex' => $chapterEndIndex,
  1197.                     'verseStartIndex' => $verseStartIndex,
  1198.                     'verseEndIndex' => $verseEndIndex
  1199.                 ));
  1200.             }
  1201.             else
  1202.             {
  1203.                 $sSliderUrl $this->get('router')->generate('bible_slider_verserange', array(
  1204.                     'translationUrl' => $sTranslationUrl,
  1205.                     'bookUrl' => $sBookUrl,
  1206.                     'chapterIndex' => $chapterStartIndex,
  1207.                     'verseStartIndex' => $verseStartIndex,
  1208.                     'verseEndIndex' => $verseEndIndex
  1209.                 ));
  1210.             }
  1211.         }
  1212.                       
  1213.         $aOTLE $this->getOTLERefForBible($aVerseInfo, array(), true);                     
  1214.    //     $otle_ref = $aOTLE['otle_nonmusic']; 
  1215.         $otle_ref_music $aOTLE['otle_music'];
  1216.         
  1217.     //    $book_list = array();
  1218.         if(empty($translation) && !empty($allVerses))                    
  1219.              $translation $this->getBibleTranslationByChapter($request$nChapterIdfalse);
  1220.         
  1221.         if (empty($translation)) {
  1222.             $right_to_left False;    
  1223.         } else {
  1224.             $right_to_left $translation['righttoleft'];    
  1225.     //        $book_list = $this->getBibleBookListForMultiColumn($translation['id']);
  1226.         }
  1227.                 
  1228.         if($book !== null && $firstChapter !== null && $verses !== null)
  1229.             $qbible_link $this->getQBibleUrl($book$firstChapter$verses$isCanonical);
  1230.         
  1231.         if($book !== null && $firstChapter !== null)    
  1232.             $commentary_with_doc $this->getCommentaryWithDocForBible($book$firstChapter->getOrdering(), $isCanonical);    
  1233.         
  1234.         //$verseExplanations = DataAssembly::filterExplainedVerses($verses, $this->getManager());
  1235.         $verseExplanations $this->getFirstExplainedVerse($aVerseInfo$request);
  1236.         
  1237.         $sTranslatPattern1 $domainIndicator '_';
  1238.         $sTranslatPattern2 '';
  1239.         if($bStoryText
  1240.         {
  1241.             $sTranslatPattern1 .= $sStoryUrl '_';
  1242.         }
  1243.         else
  1244.         {
  1245.             $sTranslatPattern2 '_' $nChapterNum;
  1246.             if($bVerseLevel)
  1247.                 $sTranslatPattern2 .= '_' $sVerseIndex;
  1248.         }    
  1249.         
  1250.         $bible_column_spec '';
  1251.         if($bChapterLevel || $bVerseLevel)
  1252.              $bible_column_spec $columnDetails;
  1253.          else
  1254.          {
  1255.              $bible_column_spec $this->getBibleMultiColumnSpec($sTranslationUrl$book->getUrl(), $chapterStartIndex$verseStartIndex$verseEndIndex);
  1256.          }
  1257.     
  1258.         $rval = array(
  1259.             'column_type' => 'bible',
  1260.             'content_category' => $contentCategory,
  1261.             'canonically_numbered' => $isCanonical,
  1262.             'book' => $book,
  1263.             'curr_book' => $curr_book,
  1264.             'translation' => $translation,
  1265.             'contents' => $verses,
  1266.             'content_start_bound' => $rangeStart,
  1267.             'content_end_bound' => $rangeEnd,
  1268.             'translate_pattern1' => $sTranslatPattern1,
  1269.             'translate_pattern2' => $sTranslatPattern2,
  1270.             'has_slider_item' => $bHasSliderItem,
  1271.             'slider_url' => $sSliderUrl,
  1272.    /*         'referring_passages' => $referringPassages,
  1273.             'core_passages' => $corePassages,     */  
  1274.             'verses_concept' => $this->getVerseContentWithConceptLinks($request$allVersesnull$column_number),
  1275.             'right_to_left' => $right_to_left,    
  1276.             'prev_chapter' => $prevChapter,
  1277.             'next_chapter' => $nextChapter,   
  1278.             'prev_verse' => $prevVerse,
  1279.             'next_verse' => $nextVerse,
  1280.             'chapter_explanation' => $chapterExplanation,
  1281.             'explained_verse' => $verseExplanations,
  1282.             'qbible_link' => $qbible_link,
  1283.             'commentary_with_doc' => $commentary_with_doc
  1284.         //    'book_list' => $book_list,
  1285.             'story_translation_url' => $sStoryTranslationUrl,
  1286.             'chapter_id' => $nChapterId,
  1287.             'verse_id' => $nVerseId,            
  1288.             'otle_ref_music' => $otle_ref_music
  1289.         );
  1290.         
  1291.         if(!empty($chapterExplanation))
  1292.           {
  1293.               $nTransID current($chapterExplanation)['translation_id'];
  1294.               $explanation_translation $this->expositionData('Translation')->findOneById($nTransID);
  1295.               
  1296.               if($explanation_translation != null)
  1297.               {
  1298.                   $passage $explanation_translation->getWork()->findFirstNonEmptyPassage($explanation_translation);
  1299.                   if($passage != null)
  1300.                   {    
  1301.                       $rval['explanation_text_style_override'] = $this->getTextStyleOverride($nTransID);
  1302.                       $rval['explanation_translation'] = $explanation_translation;
  1303.                       $rval['explanation_passage'] = $passage;
  1304.                       $rval['explanation_authors'] = $this->getAuthorInfo($request$nTransID);
  1305.                       $rval['explanation_text_to_speech'] = $this->getTextToSpeech($request$explanation_translation->getLanguage()->getId());
  1306.                       $chapterData['passage_ref'] = $this->getWorkPassageRefs($passage->getId(),$nTransID$request);
  1307.                       $rval['passage_multilink'] = $this->getWorkPassageMultiLink($passage->getId(),$nTransID$request);
  1308.                       $rval['explanation_col1_ref'] = $columnDetails;
  1309.                       $rval['explanation_col2_ref'] = $this->MULTI_URL_INDICATOR_EXPLANATION "_" $explanation_translation->getUrl();
  1310.                       
  1311.                       $nExplainChapterID $this->getExplainChapterID($nTransID$this->getCurrUserID($request));        
  1312.                       if(!empty($nExplainChapterID))
  1313.                       {
  1314.                           $rval['explanation_cchapter_id'] = $nExplainChapterID;  
  1315.                           $rval['explanation_translation_id'] = $nTransID;                                  
  1316.                       }                      
  1317.                   }
  1318.               }    
  1319.           }
  1320.                   
  1321.         if($book != null)
  1322.         {
  1323.             $nBookID null;
  1324.             if($isCanonical)
  1325.                 $nBookID $book->getId();
  1326.             else
  1327.                 $nBookID $book->getCanonicalization()->getId();    
  1328.          
  1329.             $rval['translations_by_language'] = $this->getBibleTranslationsByLanguageForVerses($request$curr_book->getCanonicalization()->getId(), current($allVerses)->getChapter()->getOrdering(), current($allVerses)->getIndexDisplay(), end($allVerses)->getChapter()->getOrdering(), end($allVerses)->getIndexDisplay()); 
  1330.             
  1331.             $rval['cbook_id'] = $curr_book->getCanonicalization()->getId();
  1332.             $rval['verse_start_index'] = current($allVerses)->getIndexDisplay();
  1333.             $rval['chapter_end_order'] = end($allVerses)->getChapter()->getOrdering();
  1334.             $rval['verse_end_index'] = end($allVerses)->getIndexDisplay();
  1335.    
  1336.         }
  1337.         if($contentCategory === 'st') {
  1338.             $rval['story'] = $story;    
  1339.             $rval['multi_story_column'] = '1';          
  1340.         } else {            
  1341.            // $rval['verse_story'] = $this->getStoriesForVerses($aVerseInfo, $request);
  1342.         }
  1343.   /*      if(count($verses) === 0) {
  1344.             $rval['errors'][] = array('code' => 404, 'message' => 'translationmismatch.bible');
  1345.         } */
  1346.         
  1347.         if($translation != null)
  1348.         {
  1349.               $msgData $this->checkBibleTranslationMsg($request$translation['url']); 
  1350.               if(!empty($msgData))
  1351.               {              
  1352.                   $rval['contents'] = null;
  1353.                   $rval['no_content_msg'] = $msgData['no_content_msg'];
  1354.               }
  1355.               
  1356.               $rval['text_style_override'] = $this->getTextStyleOverride($translation['language_id']);
  1357.               $rval['text_to_speech'] = $this->getTextToSpeech($request$translation['language_id']);
  1358.               $rval['language_for_speech'] = $this->getLanguageForSpeech($translation['language_id']);
  1359.               $rval['bible_credit'] = $this->getBibleTranslationCredit($translation['url']);
  1360.               $rval['translation_url'] = $translation['url'];
  1361.               $rval['book_url'] = $book->getUrl();
  1362.               $rval['chapter_order'] = $chapterStartIndex;
  1363.               $rval['chapter_index'] = $chapterStartIndex;
  1364.               $rval['hide_highlights'] = !$this->showBibleHighlights($translation['language_id']);
  1365.               $rval['translation_name'] = $translation['name'];
  1366.               
  1367.               if ($this->canEditExplanation($request))
  1368.               {              
  1369.                   $rval['chapter_id_to_edit'] = $nChapterId;
  1370.               }
  1371.          } 
  1372.          
  1373.          if($bVerseLevel)
  1374.          {
  1375.              // get meta description
  1376.              $nTextLength 140;
  1377.              $sVerseContent current($allVerses)->getContent(); 
  1378.               $sMetaDesc $this->fixVerseText($sVerseContent);   
  1379.               $sMetaDesc $this->getTextWithinLength($sMetaDesc$nTextLength);          
  1380.               $rval['verse_meta_desc'] = $sMetaDesc;
  1381.           }
  1382.                   
  1383.         return $rval;
  1384.     }
  1385.     protected function expositionColumnDataNew($columnDetails$column_number$request$targetColumnNum null$renderingData null)
  1386.     {
  1387.         // Old Possible formats:
  1388.         // e_### (passage by id)
  1389.         // e_###_### (first number is passage id, second number is translation id)
  1390.         // e_w_### (first passage of work with given id)
  1391.         // e_t_### (first passage of translation with given id)
  1392.         // e_w_###_### (first number is id of a swedenborg work, second is section number -- use this to allow client-side generation of URLs for arbitrary Swedenborg sections)
  1393.         // e_t_###_### (as above, but first number is id of a specific translation)
  1394.         // e_xb_# (show explanation, if any, of the Bible story/verse/chapter in the specified column, e.g. e_ex_1 to show explanation)
  1395.         // e_xb_#_### (as above, but if that column doesn't show explained Bible content, then use the ExpositionTranslation whose ID is the second number)
  1396.         
  1397.         // new link e.g. swedenborg_divine-love-and-wisdom-dole_10
  1398.         // explanation_angels
  1399.         
  1400.         $bOnMobile $this->isOnMobile();
  1401.         $locale $request->getLocale();
  1402.         $dataElementDetails explode('_'strtolower($columnDetails));
  1403.         $domainIndicator array_shift($dataElementDetails);
  1404.         $columnSpec $dataElementDetails;
  1405.         $rval = array('column_type' => 'exposition');
  1406.         
  1407.         $nSpecCount count($columnSpec); 
  1408.         $bSwedenborgWork = ($domainIndicator === $this->MULTI_URL_INDICATOR_SWEDENBORG_WORK);
  1409.         $sTranslationUrl array_shift($columnSpec);
  1410.   
  1411.         $work null;
  1412.                         
  1413.         // Find specified work or translation            
  1414.         $rval['lock_translation'] = true;        
  1415.         $rval['translation'] = $this->expositionData('Translation')->findOneBy(array('url' => $sTranslationUrl'isPublic' => true'type_id' => $this->TRANSLATION_TYPE_ID_TEXT));    
  1416.         if($rval['translation'] != null) {  
  1417.             $msgData $this->checkWorkTranslationMsg($request$sTranslationUrl); 
  1418.               if(!empty($msgData))
  1419.               {              
  1420.                   $rval['contents'] = null;
  1421.                   $rval['no_content_msg'] = $msgData['no_content_msg'];                                    
  1422.               }
  1423.              
  1424.             $work $rval['translation']->getWork();
  1425.         } 
  1426.         else
  1427.             return array();     
  1428.             
  1429.         $nTransID $rval['translation']->getId(); 
  1430.         $nLanguageID $rval['translation']->getLanguage()->getId();           
  1431.         $rval['is_swedenborg'] = $bSwedenborgWork;          
  1432.       
  1433.         if(empty($columnSpec) || !$bSwedenborgWork) {
  1434.             // No section number specified; use first passage
  1435.             $rval['passage'] = $work->findFirstNonEmptyPassage($rval['translation']);           
  1436.         } else {
  1437.         
  1438.             if($bSwedenborgWork)
  1439.             {
  1440.                 // Swedenborg section number specified
  1441.                 if($work == null || $work->getSwedenborgType() === null) {
  1442.                     $rval['errors'][] = array('code' => 404'message' => 'notswedenborg');
  1443.                     return $rval;
  1444.                 }
  1445.                 $sectionNum array_shift($columnSpec);            
  1446.                 $rval['passage'] = $this->expositionData('Passage')->findSwedenborgSection($work$sectionNum);
  1447.                 if($rval['passage'] === null) {
  1448.                     $rval['passage'] = (intval($sectionNum) <= 1) ? $work->findFirstNonEmptyPassage($rval['translation']) : $work->findLastPassage();
  1449.                 }
  1450.             }            
  1451.         }
  1452.         
  1453.          if($rval['passage'] == null) {  
  1454.             return array(); 
  1455.          }    
  1456.                  
  1457.          if(!$bSwedenborgWork)
  1458.             $rval['authors'] = $this->getAuthorInfo($request$rval['translation']->getId());
  1459.          else
  1460.             $rval['IsSwedenborgWork'] = 1;    
  1461.        
  1462.                                 
  1463.         $bCheckTrans = ($this->language1 == null);
  1464.         if($bCheckTrans)
  1465.         {
  1466.             $this->language1 $rval['translation']->getLanguage();
  1467.             $this->work1 $work;
  1468.         }
  1469.                
  1470.         if($work !== null && !$bSwedenborgWork) {
  1471.             // get concept illustrations
  1472.             $sConceptUrl $this->getConceptUrl($work->getId());            
  1473.             if($sConceptUrl != '')
  1474.             {
  1475.                 $concept $this->getRepository('Concepts\Concept')->findOneByUrl($sConceptUrl);
  1476.                 if($concept !== null) {
  1477.                     $illustrations $concept->getIllustrations();    
  1478.                     $rval['image'] = ($illustrations->isEmpty()) ? null $illustrations[0]->getImage();
  1479.                     $rval['category_prev_next'] = $this->getNextPrevConceptUrl($rval['translation']->getId(), $rval['translation']->getLanguage()->getId(), $locale);
  1480.                     $rval['is_concept'] = true;
  1481.                 }
  1482.             }
  1483.             
  1484.             $bConsider false;
  1485.             $bBibleStudy false;
  1486.             $bConcordance false;
  1487.             $bConcept false;   
  1488.             foreach($work->getCategories() as $category) {
  1489.                 if($category->getId() == $this->CATEGORY_ID_SPIRITUAL_TOPIC) {
  1490.                     $bConsider true;
  1491.                 }
  1492.                 else if($category->getId() == $this->CATEGORY_ID_BIBLE_STUDY) {
  1493.                     $bBibleStudy true;
  1494.                 }
  1495.                 else if($category->getId() == $this->CATEGORY_ID_CONCORDANCE) {
  1496.                     $bConcordance true;
  1497.                 }
  1498.                 elseif($category->getId() == $this->CATEGORY_ID_CONCEPT) {
  1499.                     $bConcept true;                        
  1500.                 }
  1501.             }           
  1502.             
  1503.             if($bConsider)
  1504.             {
  1505.                 $rval['consider_data'] = $this->getConsiderList($locale);
  1506.             }
  1507.             
  1508.             if($bBibleStudy)
  1509.             {
  1510.                 $rval['biblestudy_data'] = $this->getBibleStudyList($locale);
  1511.             }
  1512.             
  1513.             if($bConcept)
  1514.             {    
  1515.                 $rval['concept_url'] = $this->getConceptUrlFromTranslation($nTransID);
  1516.             }
  1517.             
  1518.             if($bConcordance)
  1519.             {
  1520.                 $aAllConcordance = array();                
  1521.                 $aSearchedConcordance $request->getSession()->get('searched_concordance_list');
  1522.                 if(!empty($aSearchedConcordance))
  1523.                 {                
  1524.                     foreach($aSearchedConcordance as $s)
  1525.                     {                
  1526.                         if($s['translation_url'] == $sTranslationUrl)
  1527.                         {
  1528.                             $aAllConcordance $aSearchedConcordance;
  1529.                             break;
  1530.                         }
  1531.                     }
  1532.                 }
  1533.                 if(empty($aAllConcordance))
  1534.                 {                    
  1535.                     $rval['category_prev_next'] = $this->getNextPrevCategoryUrl($nTransID$nLanguageID$this->CATEGORY_ID_CONCORDANCE$locale);
  1536.                 }
  1537.                 else
  1538.                 {
  1539.                     $rval['category_prev_next'] = $this->getPrevNextLinkFromList($nTransID$aAllConcordance);
  1540.                     $rval['concordance_has_searched_list'] = true;
  1541.                 }                
  1542.             }
  1543.         }
  1544.         
  1545.         if($rval['translation'] != null)
  1546.         {            
  1547.             $rval['text_style_override'] = $this->getTextStyleOverride($nLanguageID);            
  1548.             $rval['ref_column_spec'] = $columnDetails;
  1549.             $rval['text_to_speech'] = $this->getTextToSpeech($request$nLanguageID);
  1550.             $rval['language_for_speech'] = $this->getLanguageForSpeech($nLanguageID);
  1551.             
  1552.             if($bSwedenborgWork)        
  1553.                 $rval['biblio_info'] = $this->getBiblioForTranslation($rval['translation']->getId()); 
  1554.             else
  1555.             {
  1556.                 $nExplainChapterID $this->getExplainChapterID($rval['translation']->getId(), $this->getCurrUserID($request));        
  1557.                   if(!empty($nExplainChapterID))
  1558.                   {                  
  1559.                       if($request->getSession()->get('has_explanation_cchapter_id_temp_trans') == '1')
  1560.                     {
  1561.                         // For multi-column views, explain chapter icon is not shown 
  1562.                         // if there are more than 1 chapter column
  1563.                         $request->getSession()->set('current_explanation_cchapter_id_temp_trans''');
  1564.                         $request->getSession()->set('current_explanation_translation_id_temp_trans''');                    
  1565.                     }
  1566.                     else
  1567.                     {
  1568.                         $request->getSession()->set('has_explanation_cchapter_id_temp_trans''1'); 
  1569.                         $request->getSession()->set('current_explanation_cchapter_id_temp_trans'$nExplainChapterID); 
  1570.                           $request->getSession()->set('current_explanation_translation_id_temp_trans'$rval['translation']->getId());  
  1571.                     }       
  1572.                   } 
  1573.             }          
  1574.         }
  1575.       
  1576.         if($rval['translation'] != null && $rval['passage'] != null)
  1577.         {
  1578.             $nPassageID $rval['passage']->getId();            
  1579.             $nLanguageID $rval['translation']->getLanguage()->getId();
  1580.             $rval['previous_passage'] = $this->getPreviousPassageWithContent($rval['passage'], $rval['translation']);            
  1581.             $rval['next_passage'] = $this->getNextPassageWithContent($rval['passage'], $rval['translation']);
  1582.             
  1583.             $rval['translation_shortname'] = $this->getWorkTranslationShortName($nTransID);
  1584.                             
  1585.             if($bSwedenborgWork)
  1586.             {
  1587.                 $rval['related_bible_ref'] = $this->getRelatedBibleRefForWork($nPassageID,$nTransID$request);
  1588.                 $sPassageNum $rval['passage']->getSwedenborgSection();                 
  1589.                 if(intval($sPassageNum) == 0)
  1590.                 {
  1591.                     $sPassageText $this->getWorkPassageContents($nPassageID,$nTransID);
  1592.                     if(intval($sPassageNum) == && strlen($sPassageText) < 160)
  1593.                     {            
  1594.                         $aTOC $this->getWorkTranslationTOC($nTransID);        
  1595.                           if(!empty($aTOC))
  1596.                           {
  1597.                               $rval['work_toc'] = $aTOC;
  1598.                           }
  1599.                       }
  1600.                 }
  1601.             }
  1602.             else
  1603.             {
  1604.                 if(!$bOnMobile)
  1605.                     $rval['passage_ref'] = $this->getWorkPassageRefs($nPassageID,$nTransID$request);        
  1606.             }                    
  1607.             $rval['passage_footnote'] = $this->getPassageFootnotes($nPassageID,$nTransID);
  1608.             $rval['passage_multilink'] = $this->getWorkPassageMultiLink($nPassageID,$nTransID$request);
  1609.             
  1610.             if($bSwedenborgWork && $nLanguageID == $this->LANGUAGE_ID_LATIN)
  1611.             {                
  1612.                 $rval['passage_scanimage'] = $this->getWorkPassageScanImageFileName($nPassageID);
  1613.                 $rval['define_latin_icon'] = 1;
  1614.                 
  1615.                 if($this->userCanSeeHdpf($request))
  1616.                 {
  1617.                     $rval['passage_hdpf_info'] = $this->getHDPFInfo($nTransID$rval['passage']->getSwedenborgSection());
  1618.                 }
  1619.             }
  1620.             
  1621.             if($bSwedenborgWork)
  1622.               {
  1623.                   $bHasSliderItem $this->hasSliderItemForWork($nPassageID$nTransID$request$nLanguageID);
  1624.                   $rval['has_slider_item_for_work'] = $bHasSliderItem;
  1625.                 if($bHasSliderItem)
  1626.                 {
  1627.                     $rval['slider_url'] = $this->get('router')->generate('exposition_slider', array(
  1628.                         'translationId' => $nTransID,
  1629.                         'passageId' => $nPassageID
  1630.                     ));
  1631.                 }
  1632.                 
  1633.                 if($rval['passage']->emptyInTranslation($rval['translation']))
  1634.                 {    
  1635.                     $rval['last_passage_num'] = $this->getLastAvailablePassageNum($nTransID);
  1636.                 } 
  1637.             }
  1638.             $rval['translation_url'] = $rval['translation']->getUrl();
  1639.             
  1640.             if(!$bSwedenborgWork)
  1641.               {
  1642.                   if ($this->canEditExplanation($request))                  
  1643.                       $rval['explanation_translation_id_to_edit'] = $nTransID;
  1644.               }    
  1645.               else if ($this->canEditWork($request))
  1646.               {
  1647.                   $rval['work_translation_id_to_edit'] = $nTransID;
  1648.                   $rval['work_passage_num_to_edit'] = $rval['passage']->getSwedenborgSection();        
  1649.               }
  1650.               
  1651.               // check table of contents
  1652.               $aTOC $this->getWorkTranslationTOC($nTransIDtrue); 
  1653.               if(!empty($aTOC))
  1654.               {                  
  1655.                   $rval['has_work_toc'] = true;
  1656.               }
  1657.         } 
  1658.         
  1659.         return $rval;
  1660.     }
  1661. }