Passed
Branch feature/2.0 (2da243)
by Jonathan
05:05
created
src/Webtrees/Module/SosaModule.php 1 patch
Indentation   +164 added lines, -164 removed lines patch added patch discarded remove patch
@@ -32,116 +32,116 @@  discard block
 block discarded – undo
32 32
  * Sosa Module.
33 33
  */
34 34
 class SosaModule 
35
-    extends AbstractModule 
36
-    implements  ModuleMenuInterface, 
37
-                ModuleConfigInterface,
38
-                HookSubscriberInterface,
39
-                IndividualHeaderExtenderInterface,
40
-                RecordNameTextExtenderInterface
35
+	extends AbstractModule 
36
+	implements  ModuleMenuInterface, 
37
+				ModuleConfigInterface,
38
+				HookSubscriberInterface,
39
+				IndividualHeaderExtenderInterface,
40
+				RecordNameTextExtenderInterface
41 41
 {
42
-    // How to update the database schema for this module
43
-    const SCHEMA_TARGET_VERSION   = 2;
44
-    const SCHEMA_SETTING_NAME     = 'MAJ_SOSA_SCHEMA_VERSION';
45
-    const SCHEMA_MIGRATION_PREFIX = '\MyArtJaub\Webtrees\Module\Sosa\Schema';
42
+	// How to update the database schema for this module
43
+	const SCHEMA_TARGET_VERSION   = 2;
44
+	const SCHEMA_SETTING_NAME     = 'MAJ_SOSA_SCHEMA_VERSION';
45
+	const SCHEMA_MIGRATION_PREFIX = '\MyArtJaub\Webtrees\Module\Sosa\Schema';
46 46
 
47
-    /** @var string For custom modules - link for support, upgrades, etc. */
48
-    const CUSTOM_WEBSITE = 'https://github.com/jon48/webtrees-lib';
49
-    
50
-    /**
51
-     * {@inhericDoc}
52
-     */
53
-    public function getTitle() {
54
-        return /* I18N: Name of the “Sosa” module */ I18N::translate('Sosa');
55
-    }
56
-    
57
-    /**
58
-     * {@inhericDoc}
59
-     */
60
-    public function getDescription() {
61
-        return /* I18N: Description of the “Sosa” module */ I18N::translate('Calculate and display Sosa ancestors of the root person.');
62
-    }
63
-    
64
-    /**
65
-     * {@inhericDoc}
66
-     */
67
-    public function modAction($mod_action) {
68
-        Database::updateSchema(self::SCHEMA_MIGRATION_PREFIX, self::SCHEMA_SETTING_NAME, self::SCHEMA_TARGET_VERSION);
47
+	/** @var string For custom modules - link for support, upgrades, etc. */
48
+	const CUSTOM_WEBSITE = 'https://github.com/jon48/webtrees-lib';
49
+    
50
+	/**
51
+	 * {@inhericDoc}
52
+	 */
53
+	public function getTitle() {
54
+		return /* I18N: Name of the “Sosa” module */ I18N::translate('Sosa');
55
+	}
56
+    
57
+	/**
58
+	 * {@inhericDoc}
59
+	 */
60
+	public function getDescription() {
61
+		return /* I18N: Description of the “Sosa” module */ I18N::translate('Calculate and display Sosa ancestors of the root person.');
62
+	}
63
+    
64
+	/**
65
+	 * {@inhericDoc}
66
+	 */
67
+	public function modAction($mod_action) {
68
+		Database::updateSchema(self::SCHEMA_MIGRATION_PREFIX, self::SCHEMA_SETTING_NAME, self::SCHEMA_TARGET_VERSION);
69 69
         
70
-        \MyArtJaub\Webtrees\Mvc\Dispatcher::getInstance()->handle($this, $mod_action);
71
-    }
70
+		\MyArtJaub\Webtrees\Mvc\Dispatcher::getInstance()->handle($this, $mod_action);
71
+	}
72 72
     
73
-    /**********
73
+	/**********
74 74
      * ModuleConfigInterface
75 75
      **********/
76 76
     
77
-    /**
78
-     * {@inhericDoc}
79
-     * @see \Fisharebest\Webtrees\Module\ModuleConfigInterface::getConfigLink()
80
-     */
81
-    public function getConfigLink() {
82
-        Database::updateSchema(self::SCHEMA_MIGRATION_PREFIX, self::SCHEMA_SETTING_NAME, self::SCHEMA_TARGET_VERSION);
77
+	/**
78
+	 * {@inhericDoc}
79
+	 * @see \Fisharebest\Webtrees\Module\ModuleConfigInterface::getConfigLink()
80
+	 */
81
+	public function getConfigLink() {
82
+		Database::updateSchema(self::SCHEMA_MIGRATION_PREFIX, self::SCHEMA_SETTING_NAME, self::SCHEMA_TARGET_VERSION);
83 83
         
84
-        return 'module.php?mod=' . $this->getName() . '&mod_action=SosaConfig';
85
-    }
84
+		return 'module.php?mod=' . $this->getName() . '&mod_action=SosaConfig';
85
+	}
86 86
     
87
-    /**********
87
+	/**********
88 88
      * ModuleMenuInterface
89 89
      **********/
90 90
     
91
-    /**
92
-     * {@inhericDoc}
93
-     * @see \Fisharebest\Webtrees\Module\ModuleMenuInterface::defaultMenuOrder()
94
-     */
95
-    public function defaultMenuOrder() {
96
-        return 5;
97
-    }
98
-    
99
-    /**
100
-     * {@inhericDoc}
101
-     * @see \Fisharebest\Webtrees\Module\ModuleMenuInterface::getMenu()
102
-     */
103
-    public function getMenu() { 
104
-        $wt_tree = Globals::getTree();
105
-        $menu = null;
106
-        if(ModuleManager::getInstance()->isOperational($this->getName())) {
91
+	/**
92
+	 * {@inhericDoc}
93
+	 * @see \Fisharebest\Webtrees\Module\ModuleMenuInterface::defaultMenuOrder()
94
+	 */
95
+	public function defaultMenuOrder() {
96
+		return 5;
97
+	}
98
+    
99
+	/**
100
+	 * {@inhericDoc}
101
+	 * @see \Fisharebest\Webtrees\Module\ModuleMenuInterface::getMenu()
102
+	 */
103
+	public function getMenu() { 
104
+		$wt_tree = Globals::getTree();
105
+		$menu = null;
106
+		if(ModuleManager::getInstance()->isOperational($this->getName())) {
107 107
             
108
-            $root_url = 'module.php?mod=' . $this->getName() . '&ged=' . $wt_tree->getNameUrl() . '&';
109
-            $sosa_stat_menu = new Menu(I18N::translate('Sosa Statistics'), $root_url . 'mod_action=SosaStats', 'menu-maj-sosa-stats');
108
+			$root_url = 'module.php?mod=' . $this->getName() . '&ged=' . $wt_tree->getNameUrl() . '&';
109
+			$sosa_stat_menu = new Menu(I18N::translate('Sosa Statistics'), $root_url . 'mod_action=SosaStats', 'menu-maj-sosa-stats');
110 110
             
111
-            $menu = clone $sosa_stat_menu;
112
-            $menu->setClass('menu-maj-sosa');
111
+			$menu = clone $sosa_stat_menu;
112
+			$menu->setClass('menu-maj-sosa');
113 113
             
114
-            $submenus = array_filter(array(
115
-                new Menu(I18N::translate('Sosa Ancestors'), $root_url . 'mod_action=SosaList', 'menu-maj-sosa-list', array('rel' => 'nofollow')),
116
-                new Menu(I18N::translate('Missing Ancestors'), $root_url . 'mod_action=SosaList@missing', 'menu-maj-sosa-missing', array('rel' => 'nofollow')),
117
-                $sosa_stat_menu                
118
-            ));
114
+			$submenus = array_filter(array(
115
+				new Menu(I18N::translate('Sosa Ancestors'), $root_url . 'mod_action=SosaList', 'menu-maj-sosa-list', array('rel' => 'nofollow')),
116
+				new Menu(I18N::translate('Missing Ancestors'), $root_url . 'mod_action=SosaList@missing', 'menu-maj-sosa-missing', array('rel' => 'nofollow')),
117
+				$sosa_stat_menu                
118
+			));
119 119
             
120 120
 
121
-            if (ModuleManager::getInstance()->isOperational(Constants::MODULE_MAJ_GEODISP_NAME)
122
-                && $ga_list = Module::getModuleByName(Constants::MODULE_MAJ_GEODISP_NAME)->getProvider()->getGeoAnalysisList()
123
-                )
124
-            {
125
-                if(count($ga_list) > 0) {
126
-                    $submenus[] = new Menu(I18N::translate('Geographical Dispersion'), 'module.php?mod=' . Constants::MODULE_MAJ_GEODISP_NAME . '&ged=' . $wt_tree->getNameUrl() . '&mod_action=GeoAnalysis@listAll', 'menu-maj-sosa-geodispersion');
127
-                }
128
-            }
121
+			if (ModuleManager::getInstance()->isOperational(Constants::MODULE_MAJ_GEODISP_NAME)
122
+				&& $ga_list = Module::getModuleByName(Constants::MODULE_MAJ_GEODISP_NAME)->getProvider()->getGeoAnalysisList()
123
+				)
124
+			{
125
+				if(count($ga_list) > 0) {
126
+					$submenus[] = new Menu(I18N::translate('Geographical Dispersion'), 'module.php?mod=' . Constants::MODULE_MAJ_GEODISP_NAME . '&ged=' . $wt_tree->getNameUrl() . '&mod_action=GeoAnalysis@listAll', 'menu-maj-sosa-geodispersion');
127
+				}
128
+			}
129 129
             
130
-            if(Auth::check()) {
131
-                $submenus[] = new Menu(
132
-                    I18N::translate('Sosa Configuration'),
133
-                    $this->getConfigLink(),
134
-                    'menu-maj-sosa-configuration',
135
-                    array('rel' => 'nofollow'));
136
-            }
130
+			if(Auth::check()) {
131
+				$submenus[] = new Menu(
132
+					I18N::translate('Sosa Configuration'),
133
+					$this->getConfigLink(),
134
+					'menu-maj-sosa-configuration',
135
+					array('rel' => 'nofollow'));
136
+			}
137 137
                         
138
-            //-- recompute Sosa submenu
139
-            $controller = Globals::getController();
140
-            if (!empty($controller) && $controller instanceof IndividualController 
141
-                && Auth::check() && $wt_tree->getUserPreference(Auth::user(), 'MAJ_SOSA_ROOT_ID')
142
-                ) {
143
-                $controller
144
-                    ->addInlineJavascript('
138
+			//-- recompute Sosa submenu
139
+			$controller = Globals::getController();
140
+			if (!empty($controller) && $controller instanceof IndividualController 
141
+				&& Auth::check() && $wt_tree->getUserPreference(Auth::user(), 'MAJ_SOSA_ROOT_ID')
142
+				) {
143
+				$controller
144
+					->addInlineJavascript('
145 145
                         function majComputeSosaFromIndi(){
146 146
                             if($("#computesosadlg").length == 0) {
147 147
                                 $("body").append("<div id=\"computesosadlg\" title=\"'. I18N::translate('Sosas computation') .'\"><div id=\"sosaloadingarea\"></div></div>");
@@ -164,87 +164,87 @@  discard block
 block discarded – undo
164 164
 	                         });	
165 165
                         }');
166 166
                 	
167
-                $submenus[] = new Menu(
168
-                    I18N::translate('Complete Sosas'), 
169
-                    '#', 
170
-                    'menu-maj-sosa-recompute', 
171
-                    array(
172
-                        'rel' => 'nofollow',
173
-                        'onclick' => 'return majComputeSosaFromIndi();'
174
-                    ));
175
-            }
167
+				$submenus[] = new Menu(
168
+					I18N::translate('Complete Sosas'), 
169
+					'#', 
170
+					'menu-maj-sosa-recompute', 
171
+					array(
172
+						'rel' => 'nofollow',
173
+						'onclick' => 'return majComputeSosaFromIndi();'
174
+					));
175
+			}
176 176
             
177
-        }
177
+		}
178 178
         
179
-        $menu->setSubmenus($submenus);
179
+		$menu->setSubmenus($submenus);
180 180
         
181
-        return $menu;
181
+		return $menu;
182 182
         
183
-    }
183
+	}
184 184
     
185
-    /**********
185
+	/**********
186 186
      * Hooks
187 187
      **********/
188 188
     
189
-    /**
190
-     * {@inhericDoc}
191
-     * @see \MyArtJaub\Webtrees\Hook\HookSubscriberInterface::getSubscribedHooks()
192
-     */    
193
-    public function getSubscribedHooks() {
194
-        return array(
195
-            'hExtendIndiHeaderIcons' => 20,
196
-            'hExtendIndiHeaderRight' => 20,
197
-            'hRecordNameAppend' => 20
198
-        );
199
-    }
200
-    
201
-    /**
202
-     * {@inhericDoc}
203
-     * @see \MyArtJaub\Webtrees\Hook\HookInterfaces\IndividualHeaderExtenderInterface::hExtendIndiHeaderIcons()
204
-     */
205
-    public function hExtendIndiHeaderIcons(IndividualController $ctrlIndi) {
206
-        if($ctrlIndi){
207
-            $dindi = new Individual($ctrlIndi->getSignificantIndividual());
208
-            return FunctionsPrint::formatSosaNumbers($dindi->getSosaNumbers(), 1, 'large');
209
-        }
210
-        return '';
211
-    }
212
-    
213
-    /**
214
-     * {@inhericDoc}
215
-     * @see \MyArtJaub\Webtrees\Hook\HookInterfaces\IndividualHeaderExtenderInterface::hExtendIndiHeaderLeft()
216
-     */
217
-    public function hExtendIndiHeaderLeft(IndividualController $ctrlIndi) { }
218
-    
219
-    /**
220
-     * {@inhericDoc}
221
-     * @see \MyArtJaub\Webtrees\Hook\HookInterfaces\IndividualHeaderExtenderInterface::hExtendIndiHeaderRight()
222
-     */
223
-    public function hExtendIndiHeaderRight(IndividualController $ctrlIndi) {
224
-        if($ctrlIndi){
225
-            $dindi = new Individual($ctrlIndi->getSignificantIndividual());
226
-            return array('indi-header-sosa',  FunctionsPrint::formatSosaNumbers($dindi->getSosaNumbers(), 2, 'normal'));
227
-        }
228
-        return '';
229
-    }
230
-    
231
-    /**
232
-     * {@inhericDoc}
233
-     * @see \MyArtJaub\Webtrees\Hook\HookInterfaces\RecordNameTextExtenderInterface::hRecordNameAppend()
234
-     */
235
-    public function hRecordNameAppend(GedcomRecord $grec, $size = 'small') {
236
-        if($grec instanceof \Fisharebest\Webtrees\Individual){ // Only apply to individuals
237
-            $dindi = new Individual($grec);
238
-            return FunctionsPrint::formatSosaNumbers($dindi->getSosaNumbers(), 1, $size);
239
-        }
240
-        return '';
241
-    }
242
-    
243
-    /**
244
-     * {@inhericDoc}
245
-     * @see \MyArtJaub\Webtrees\Hook\HookInterfaces\RecordNameTextExtenderInterface::hRecordNamePrepend()
246
-     */
247
-    public function hRecordNamePrepend(GedcomRecord $grec, $size) {}
189
+	/**
190
+	 * {@inhericDoc}
191
+	 * @see \MyArtJaub\Webtrees\Hook\HookSubscriberInterface::getSubscribedHooks()
192
+	 */    
193
+	public function getSubscribedHooks() {
194
+		return array(
195
+			'hExtendIndiHeaderIcons' => 20,
196
+			'hExtendIndiHeaderRight' => 20,
197
+			'hRecordNameAppend' => 20
198
+		);
199
+	}
200
+    
201
+	/**
202
+	 * {@inhericDoc}
203
+	 * @see \MyArtJaub\Webtrees\Hook\HookInterfaces\IndividualHeaderExtenderInterface::hExtendIndiHeaderIcons()
204
+	 */
205
+	public function hExtendIndiHeaderIcons(IndividualController $ctrlIndi) {
206
+		if($ctrlIndi){
207
+			$dindi = new Individual($ctrlIndi->getSignificantIndividual());
208
+			return FunctionsPrint::formatSosaNumbers($dindi->getSosaNumbers(), 1, 'large');
209
+		}
210
+		return '';
211
+	}
212
+    
213
+	/**
214
+	 * {@inhericDoc}
215
+	 * @see \MyArtJaub\Webtrees\Hook\HookInterfaces\IndividualHeaderExtenderInterface::hExtendIndiHeaderLeft()
216
+	 */
217
+	public function hExtendIndiHeaderLeft(IndividualController $ctrlIndi) { }
218
+    
219
+	/**
220
+	 * {@inhericDoc}
221
+	 * @see \MyArtJaub\Webtrees\Hook\HookInterfaces\IndividualHeaderExtenderInterface::hExtendIndiHeaderRight()
222
+	 */
223
+	public function hExtendIndiHeaderRight(IndividualController $ctrlIndi) {
224
+		if($ctrlIndi){
225
+			$dindi = new Individual($ctrlIndi->getSignificantIndividual());
226
+			return array('indi-header-sosa',  FunctionsPrint::formatSosaNumbers($dindi->getSosaNumbers(), 2, 'normal'));
227
+		}
228
+		return '';
229
+	}
230
+    
231
+	/**
232
+	 * {@inhericDoc}
233
+	 * @see \MyArtJaub\Webtrees\Hook\HookInterfaces\RecordNameTextExtenderInterface::hRecordNameAppend()
234
+	 */
235
+	public function hRecordNameAppend(GedcomRecord $grec, $size = 'small') {
236
+		if($grec instanceof \Fisharebest\Webtrees\Individual){ // Only apply to individuals
237
+			$dindi = new Individual($grec);
238
+			return FunctionsPrint::formatSosaNumbers($dindi->getSosaNumbers(), 1, $size);
239
+		}
240
+		return '';
241
+	}
242
+    
243
+	/**
244
+	 * {@inhericDoc}
245
+	 * @see \MyArtJaub\Webtrees\Hook\HookInterfaces\RecordNameTextExtenderInterface::hRecordNamePrepend()
246
+	 */
247
+	public function hRecordNamePrepend(GedcomRecord $grec, $size) {}
248 248
     
249 249
     
250 250
     
Please login to merge, or discard this patch.
src/Webtrees/Module/Sosa/Model/SosaCalculator.php 1 patch
Indentation   +101 added lines, -101 removed lines patch added patch discarded remove patch
@@ -19,121 +19,121 @@
 block discarded – undo
19 19
  */
20 20
 class SosaCalculator {
21 21
     
22
-    /**
23
-     * Maximium size for the temporary Sosa table
24
-     * @var int TMP_SOSA_TABLE_LIMIT
25
-     */
26
-    const TMP_SOSA_TABLE_LIMIT = 1000;
22
+	/**
23
+	 * Maximium size for the temporary Sosa table
24
+	 * @var int TMP_SOSA_TABLE_LIMIT
25
+	 */
26
+	const TMP_SOSA_TABLE_LIMIT = 1000;
27 27
     
28
-    /**
29
-     * Reference user
30
-     * @var Fisharebest\Webtrees\User $user
31
-     */
32
-    protected $user;
28
+	/**
29
+	 * Reference user
30
+	 * @var Fisharebest\Webtrees\User $user
31
+	 */
32
+	protected $user;
33 33
     
34
-    /**
35
-     * Reference tree
36
-     * @var Fisharebest\Webtrees\Tree $tree
37
-     */
38
-    protected $tree;
34
+	/**
35
+	 * Reference tree
36
+	 * @var Fisharebest\Webtrees\Tree $tree
37
+	 */
38
+	protected $tree;
39 39
     
40
-    /**
41
-     * Sosa Provider for the calculator
42
-     * @var \MyArtJaub\Webtrees\Module\Sosa\Model\SosaCalculator $sosa_provider
43
-     */
44
-    protected $sosa_provider;
40
+	/**
41
+	 * Sosa Provider for the calculator
42
+	 * @var \MyArtJaub\Webtrees\Module\Sosa\Model\SosaCalculator $sosa_provider
43
+	 */
44
+	protected $sosa_provider;
45 45
     
46
-    /**
47
-     * Temporary Sosa table, used during construction
48
-     * @var array $tmp_sosa_table
49
-     */
50
-    protected $tmp_sosa_table;
46
+	/**
47
+	 * Temporary Sosa table, used during construction
48
+	 * @var array $tmp_sosa_table
49
+	 */
50
+	protected $tmp_sosa_table;
51 51
     
52
-    /**
53
-     * Constructor for the Sosa Calculator
54
-     * @param Tree $tree
55
-     * @param User $user
56
-     */
57
-    public function __construct(Tree $tree, User $user) {        
58
-        $this->tree = $tree;
59
-        $this->user = $user;
52
+	/**
53
+	 * Constructor for the Sosa Calculator
54
+	 * @param Tree $tree
55
+	 * @param User $user
56
+	 */
57
+	public function __construct(Tree $tree, User $user) {        
58
+		$this->tree = $tree;
59
+		$this->user = $user;
60 60
         
61
-        $this->sosa_provider = new SosaProvider($this->tree, $this->user);;
62
-    }
61
+		$this->sosa_provider = new SosaProvider($this->tree, $this->user);;
62
+	}
63 63
     
64
-    /**
65
-     * Compute all Sosa ancestors from the user's root individual.
66
-     * @return bool Result of the computation
67
-     */
68
-    public function computeAll() {
69
-        $root_id = $this->tree->getUserPreference($this->user, 'MAJ_SOSA_ROOT_ID');        
70
-        $indi = Individual::getInstance($root_id, $this->tree);
71
-        if($indi){
72
-            $this->sosa_provider->deleteAll();
73
-            $this->addNode($indi, 1);
74
-            $this->flushTmpSosaTable(true);
75
-            return true;
76
-        }
77
-        return false;
78
-    }
64
+	/**
65
+	 * Compute all Sosa ancestors from the user's root individual.
66
+	 * @return bool Result of the computation
67
+	 */
68
+	public function computeAll() {
69
+		$root_id = $this->tree->getUserPreference($this->user, 'MAJ_SOSA_ROOT_ID');        
70
+		$indi = Individual::getInstance($root_id, $this->tree);
71
+		if($indi){
72
+			$this->sosa_provider->deleteAll();
73
+			$this->addNode($indi, 1);
74
+			$this->flushTmpSosaTable(true);
75
+			return true;
76
+		}
77
+		return false;
78
+	}
79 79
     
80
-    /**
81
-     * Compute all Sosa Ancestors from a specified Individual
82
-     * @param Individual $indi
83
-     * @return bool Result of the computation
84
-     */
85
-    public function computeFromIndividual(Individual $indi) {
86
-        $dindi = new \MyArtJaub\Webtrees\Individual($indi);
87
-        $current_sosas = $dindi->getSosaNumbers();
88
-        foreach($current_sosas as $current_sosa => $gen) {
89
-            $this->sosa_provider->deleteAncestors($current_sosa);
90
-            $this->addNode($indi, $current_sosa);
91
-        }
92
-        $this->flushTmpSosaTable(true);
93
-        return true;
94
-    }
80
+	/**
81
+	 * Compute all Sosa Ancestors from a specified Individual
82
+	 * @param Individual $indi
83
+	 * @return bool Result of the computation
84
+	 */
85
+	public function computeFromIndividual(Individual $indi) {
86
+		$dindi = new \MyArtJaub\Webtrees\Individual($indi);
87
+		$current_sosas = $dindi->getSosaNumbers();
88
+		foreach($current_sosas as $current_sosa => $gen) {
89
+			$this->sosa_provider->deleteAncestors($current_sosa);
90
+			$this->addNode($indi, $current_sosa);
91
+		}
92
+		$this->flushTmpSosaTable(true);
93
+		return true;
94
+	}
95 95
     
96
-    /**
97
-     * Recursive method to add individual to the Sosa table, and flush it regularly
98
-     * @param Individual $indi Individual to add
99
-     * @param int $sosa Individual's sosa
100
-     */
101
-    protected function addNode(Individual $indi, $sosa) {                
102
-        $birth_year = $indi->getBirthDate()->gregorianYear();
103
-        $birth_year_est = $birth_year === 0 ? $indi->getEstimatedBirthDate()->gregorianYear() : $birth_year;
96
+	/**
97
+	 * Recursive method to add individual to the Sosa table, and flush it regularly
98
+	 * @param Individual $indi Individual to add
99
+	 * @param int $sosa Individual's sosa
100
+	 */
101
+	protected function addNode(Individual $indi, $sosa) {                
102
+		$birth_year = $indi->getBirthDate()->gregorianYear();
103
+		$birth_year_est = $birth_year === 0 ? $indi->getEstimatedBirthDate()->gregorianYear() : $birth_year;
104 104
         
105
-        $death_year = $indi->getDeathDate()->gregorianYear();
106
-        $death_year_est = $death_year === 0 ? $indi->getEstimatedDeathDate()->gregorianYear() : $death_year;
105
+		$death_year = $indi->getDeathDate()->gregorianYear();
106
+		$death_year_est = $death_year === 0 ? $indi->getEstimatedDeathDate()->gregorianYear() : $death_year;
107 107
         
108
-        $this->tmp_sosa_table[] = array(
109
-            'indi' => $indi->getXref(),
110
-            'sosa' => $sosa,
111
-            'birth_year' => $birth_year === 0 ? null : $birth_year,
112
-            'birth_year_est' => $birth_year_est === 0 ? null : $birth_year_est,
113
-            'death_year' => $death_year === 0 ? null : $death_year,
114
-            'death_year_est' => $death_year_est === 0 ? null : $death_year_est
115
-        );
108
+		$this->tmp_sosa_table[] = array(
109
+			'indi' => $indi->getXref(),
110
+			'sosa' => $sosa,
111
+			'birth_year' => $birth_year === 0 ? null : $birth_year,
112
+			'birth_year_est' => $birth_year_est === 0 ? null : $birth_year_est,
113
+			'death_year' => $death_year === 0 ? null : $death_year,
114
+			'death_year_est' => $death_year_est === 0 ? null : $death_year_est
115
+		);
116 116
         
117
-        $this->flushTmpSosaTable();
117
+		$this->flushTmpSosaTable();
118 118
         
119
-        if($fam = $indi->getPrimaryChildFamily()) {
120
-            if($husb = $fam->getHusband()) $this->addNode($husb, 2 * $sosa);
121
-            if($wife = $fam->getWife()) $this->addNode($wife, 2 * $sosa + 1);
122
-        }
123
-    }
119
+		if($fam = $indi->getPrimaryChildFamily()) {
120
+			if($husb = $fam->getHusband()) $this->addNode($husb, 2 * $sosa);
121
+			if($wife = $fam->getWife()) $this->addNode($wife, 2 * $sosa + 1);
122
+		}
123
+	}
124 124
     
125
-    /**
126
-     * Write sosas in the table, if the number of items is superior to the limit, or if forced.
127
-     *
128
-     * @param bool $force Should the flush be forced
129
-     */
130
-    protected function flushTmpSosaTable($force = false) {
131
-        if( count($this->tmp_sosa_table)> 0 && 
132
-            ($force ||  count($this->tmp_sosa_table) >= self::TMP_SOSA_TABLE_LIMIT)){            
133
-                $this->sosa_provider->insertOrUpdate($this->tmp_sosa_table);
134
-                $this->tmp_sosa_table = array();
135
-        }
136
-    }
125
+	/**
126
+	 * Write sosas in the table, if the number of items is superior to the limit, or if forced.
127
+	 *
128
+	 * @param bool $force Should the flush be forced
129
+	 */
130
+	protected function flushTmpSosaTable($force = false) {
131
+		if( count($this->tmp_sosa_table)> 0 && 
132
+			($force ||  count($this->tmp_sosa_table) >= self::TMP_SOSA_TABLE_LIMIT)){            
133
+				$this->sosa_provider->insertOrUpdate($this->tmp_sosa_table);
134
+				$this->tmp_sosa_table = array();
135
+		}
136
+	}
137 137
                
138 138
 }
139 139
  
140 140
\ No newline at end of file
Please login to merge, or discard this patch.
src/Webtrees/Module/Sosa/Views/SosaStatsView.php 1 patch
Indentation   +26 added lines, -26 removed lines patch added patch discarded remove patch
@@ -23,8 +23,8 @@  discard block
 block discarded – undo
23 23
 	 * {@inhericDoc}
24 24
 	 * @see \MyArtJaub\Webtrees\Mvc\View\AbstractView::renderContent()
25 25
 	 */
26
-    protected function renderContent() {      
27
-        ?>                
26
+	protected function renderContent() {      
27
+		?>                
28 28
         <div id="maj-sosa-stats-page">
29 29
 			<h2><?php echo $this->data->get('title'); ?></h2>
30 30
 			
@@ -36,7 +36,7 @@  discard block
 block discarded – undo
36 36
 			<?php } ?>
37 37
 			
38 38
 			<?php  if($this->data->get('is_setup')) {  
39
-			    $general_stats = $this->data->get('general_stats'); ?>
39
+				$general_stats = $this->data->get('general_stats'); ?>
40 40
 			<h3><?php echo I18N::translate('General statistics'); ?></h3>
41 41
 			<div class="maj-table">
42 42
 				<div class="maj-row">
@@ -126,23 +126,23 @@  discard block
 block discarded – undo
126 126
 						<td class="label" colspan="13">
127 127
 							<?php 
128 128
 							echo I18N::translate(
129
-							         'Mean generation depth: %s',
130
-							         I18N::plural(
131
-							             I18N::translate('%s generation'),
132
-							             I18N::translate('%s generations'),
133
-							             $this->data->get('mean_gen_depth'),
134
-							             I18N::number($this->data->get('mean_gen_depth'),2)
135
-							         )
136
-							    ).
129
+									 'Mean generation depth: %s',
130
+									 I18N::plural(
131
+										 I18N::translate('%s generation'),
132
+										 I18N::translate('%s generations'),
133
+										 $this->data->get('mean_gen_depth'),
134
+										 I18N::number($this->data->get('mean_gen_depth'),2)
135
+									 )
136
+								).
137 137
 								' &mdash; ' . 
138 138
 								I18N::translate(
139
-								    'Standard deviation: %s',
140
-								    I18N::plural(
141
-								        I18N::translate('%s generation'), 
142
-								        I18N::translate('%s generations'), 
143
-								        $this->data->get('stddev_gen_depth'), 
144
-								        I18N::number($this->data->get('stddev_gen_depth'),2)
145
-								    )
139
+									'Standard deviation: %s',
140
+									I18N::plural(
141
+										I18N::translate('%s generation'), 
142
+										I18N::translate('%s generations'), 
143
+										$this->data->get('stddev_gen_depth'), 
144
+										I18N::number($this->data->get('stddev_gen_depth'),2)
145
+									)
146 146
 								);
147 147
 							?>
148 148
 						</td>
@@ -160,13 +160,13 @@  discard block
 block discarded – undo
160 160
 			    <div class="maj-row">
161 161
 			    	<div class="label"><?= I18N::translate('%s times', I18N::number($count)); ?></div>
162 162
 			    	<div class="value"><?php 
163
-			    	echo implode(
164
-			    	    I18N::$list_separator, 
165
-			    	    array_map(function(Individual $indi) {
166
-			    	        return '<a href="'. $indi->getHtmlUrl(). '">'. $indi->getFullName() . '&nbsp;' . $indi->getSexImage() . '</a>';
167
-			    	    }, $indis)
168
-			    	);
169
-			    	?></div>
163
+					echo implode(
164
+						I18N::$list_separator, 
165
+						array_map(function(Individual $indi) {
166
+							return '<a href="'. $indi->getHtmlUrl(). '">'. $indi->getFullName() . '&nbsp;' . $indi->getSexImage() . '</a>';
167
+						}, $indis)
168
+					);
169
+					?></div>
170 170
 				</div>
171 171
 			<?php } ?>
172 172
 			</div>
@@ -187,6 +187,6 @@  discard block
 block discarded – undo
187 187
 			<?php   } else { ?>
188 188
 			<div class="center warning"><?php echo I18N::translate('No Sosa root individual has been defined.'); ?></div>
189 189
 			<?php }     
190
-    }
190
+	}
191 191
     
192 192
 }
193 193
\ No newline at end of file
Please login to merge, or discard this patch.
src/Webtrees/Module/Sosa/Schema/Migration1.php 1 patch
Indentation   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -22,13 +22,13 @@
 block discarded – undo
22 22
 	public function upgrade() {
23 23
 
24 24
 		Database::exec(
25
-		    'ALTER TABLE `##maj_sosa`' . 
26
-		    ' ADD COLUMN majs_birth_year_est SMALLINT NULL AFTER majs_birth_year,' .
27
-		    ' ADD COLUMN majs_death_year_est SMALLINT NULL AFTER majs_death_year'
25
+			'ALTER TABLE `##maj_sosa`' . 
26
+			' ADD COLUMN majs_birth_year_est SMALLINT NULL AFTER majs_birth_year,' .
27
+			' ADD COLUMN majs_death_year_est SMALLINT NULL AFTER majs_death_year'
28 28
 		);
29 29
 		
30 30
 		Database::exec(
31
-		    'DELETE FROM `##maj_sosa`'
31
+			'DELETE FROM `##maj_sosa`'
32 32
 		);
33 33
 	}
34 34
 }
Please login to merge, or discard this patch.
src/Webtrees/Module/Sosa/SosaStatsController.php 1 patch
Indentation   +236 added lines, -236 removed lines patch added patch discarded remove patch
@@ -28,279 +28,279 @@
 block discarded – undo
28 28
  */
29 29
 class SosaStatsController extends MvcController
30 30
 {
31
-    /**
32
-     * Sosa Provider for the controller
33
-     * @var SosaProvider $sosa_provider
34
-     */
35
-    protected $sosa_provider;
31
+	/**
32
+	 * Sosa Provider for the controller
33
+	 * @var SosaProvider $sosa_provider
34
+	 */
35
+	protected $sosa_provider;
36 36
     
37
-    /**
38
-     * Constructor for SosaStatsController
39
-     * @param AbstractModule $module
40
-     */
41
-    public function __construct(AbstractModule $module) {
42
-        parent::__construct($module);
37
+	/**
38
+	 * Constructor for SosaStatsController
39
+	 * @param AbstractModule $module
40
+	 */
41
+	public function __construct(AbstractModule $module) {
42
+		parent::__construct($module);
43 43
         
44
-        $this->sosa_provider = new SosaProvider(Globals::getTree(), Auth::user());
45
-    }
44
+		$this->sosa_provider = new SosaProvider(Globals::getTree(), Auth::user());
45
+	}
46 46
     
47
-    /**
48
-     * Pages
49
-     */
47
+	/**
48
+	 * Pages
49
+	 */
50 50
     
51
-    /**
52
-     * SosaStats@index
53
-     */
54
-    public function index() {
55
-        $wt_tree = Globals::getTree();
56
-        $controller = new PageController();
57
-        $controller
58
-            ->setPageTitle(I18N::translate('Sosa Statistics'))
59
-            ->addInlineJavascript('$(".help_tooltip").tooltip();')
60
-        ;
51
+	/**
52
+	 * SosaStats@index
53
+	 */
54
+	public function index() {
55
+		$wt_tree = Globals::getTree();
56
+		$controller = new PageController();
57
+		$controller
58
+			->setPageTitle(I18N::translate('Sosa Statistics'))
59
+			->addInlineJavascript('$(".help_tooltip").tooltip();')
60
+		;
61 61
 
62
-        $view_bag = new ViewBag();
63
-        $view_bag->set('title', $controller->getPageTitle());
64
-        $view_bag->set('is_setup', false);
62
+		$view_bag = new ViewBag();
63
+		$view_bag->set('title', $controller->getPageTitle());
64
+		$view_bag->set('is_setup', false);
65 65
         
66
-        if($this->sosa_provider->isSetup()) {
67
-            $view_bag->set('is_setup', true);
66
+		if($this->sosa_provider->isSetup()) {
67
+			$view_bag->set('is_setup', true);
68 68
             
69
-            $view_bag->set('root_indi', $this->sosa_provider->getRootIndi());
69
+			$view_bag->set('root_indi', $this->sosa_provider->getRootIndi());
70 70
             
71
-            $sosaCount = $this->sosa_provider->getSosaCount();
72
-            $diffSosaCount = $this->sosa_provider->getDifferentSosaCount();
71
+			$sosaCount = $this->sosa_provider->getSosaCount();
72
+			$diffSosaCount = $this->sosa_provider->getDifferentSosaCount();
73 73
             
74
-            $general_stats = array(
75
-                'sosa_count' => $sosaCount,
76
-                'distinct_count' => $diffSosaCount,
77
-                'sosa_rate' => Functions::safeDivision($diffSosaCount, $this->sosa_provider->getTotalIndividuals()),
78
-                'pedi_collapse' => 1 - Functions::safeDivision($diffSosaCount, $sosaCount),
79
-                'mean_gen_time' => $this->sosa_provider->getMeanGenerationTime()
80
-            );
81
-            $view_bag->set('general_stats', $general_stats);
74
+			$general_stats = array(
75
+				'sosa_count' => $sosaCount,
76
+				'distinct_count' => $diffSosaCount,
77
+				'sosa_rate' => Functions::safeDivision($diffSosaCount, $this->sosa_provider->getTotalIndividuals()),
78
+				'pedi_collapse' => 1 - Functions::safeDivision($diffSosaCount, $sosaCount),
79
+				'mean_gen_time' => $this->sosa_provider->getMeanGenerationTime()
80
+			);
81
+			$view_bag->set('general_stats', $general_stats);
82 82
             
83
-            $stats_gen = $this->sosa_provider->getStatisticsByGeneration();
84
-            $view_bag->set('missinganc_url', 'module.php?mod='.$this->module->getName().'&mod_action=SosaList@missing&ged='.$wt_tree->getNameUrl().'&gen=');
85
-            $view_bag->set('sosaanc_url', 'module.php?mod='.$this->module->getName().'&mod_action=SosaList&ged='.$wt_tree->getNameUrl().'&gen=');
83
+			$stats_gen = $this->sosa_provider->getStatisticsByGeneration();
84
+			$view_bag->set('missinganc_url', 'module.php?mod='.$this->module->getName().'&mod_action=SosaList@missing&ged='.$wt_tree->getNameUrl().'&gen=');
85
+			$view_bag->set('sosaanc_url', 'module.php?mod='.$this->module->getName().'&mod_action=SosaList&ged='.$wt_tree->getNameUrl().'&gen=');
86 86
             
87
-            $gen_theoretical=1;
88
-            $total_theoretical=0;
89
-            $prev_diff=0;
90
-            $prev_known=0.5;
91
-            $generation_stats = array();
87
+			$gen_theoretical=1;
88
+			$total_theoretical=0;
89
+			$prev_diff=0;
90
+			$prev_known=0.5;
91
+			$generation_stats = array();
92 92
             
93
-            foreach($stats_gen as $gen => $tab){
94
-                $genY1= I18N::translate('-');
95
-                $genY2= I18N::translate('-');
96
-                if($tab['firstBirth']>0) $genY1=$tab['firstEstimatedBirth'];
97
-                if($tab['lastBirth']>0) $genY2=$tab['lastEstimatedBirth'];
98
-                $total_theoretical += $gen_theoretical;
99
-                $perc_sosa_count_theor = Functions::safeDivision($tab['sosaCount'], $gen_theoretical);
100
-                $missing=2*$prev_known - $tab['sosaCount'];
101
-                $gen_diff=$tab['diffSosaTotalCount']-$prev_diff;
93
+			foreach($stats_gen as $gen => $tab){
94
+				$genY1= I18N::translate('-');
95
+				$genY2= I18N::translate('-');
96
+				if($tab['firstBirth']>0) $genY1=$tab['firstEstimatedBirth'];
97
+				if($tab['lastBirth']>0) $genY2=$tab['lastEstimatedBirth'];
98
+				$total_theoretical += $gen_theoretical;
99
+				$perc_sosa_count_theor = Functions::safeDivision($tab['sosaCount'], $gen_theoretical);
100
+				$missing=2*$prev_known - $tab['sosaCount'];
101
+				$gen_diff=$tab['diffSosaTotalCount']-$prev_diff;
102 102
                 
103
-                $generation_stats[$gen] = array(
104
-                    'gen_min_birth' => $genY1,
105
-                    'gen_max_birth' => $genY2,
106
-                    'theoretical' => $gen_theoretical,
107
-                    'known' => $tab['sosaCount'],
108
-                    'perc_known' => $perc_sosa_count_theor,
109
-                    'missing' => $missing,
110
-                    'perc_missing' => 1-Functions::safeDivision($tab['sosaCount'], 2*$prev_known),
111
-                    'total_known' => $tab['sosaTotalCount'],
112
-                    'perc_total_known' => Functions::safeDivision($tab['sosaTotalCount'], $total_theoretical),
113
-                    'different' => $gen_diff,
114
-                    'perc_different' => Functions::safeDivision($gen_diff, $tab['sosaCount']),
115
-                    'total_different' => $tab['diffSosaTotalCount'],
116
-                    'pedi_collapse' => 1 - Functions::safeDivision($tab['diffSosaTotalCount'], $tab['sosaTotalCount'])
117
-                );
103
+				$generation_stats[$gen] = array(
104
+					'gen_min_birth' => $genY1,
105
+					'gen_max_birth' => $genY2,
106
+					'theoretical' => $gen_theoretical,
107
+					'known' => $tab['sosaCount'],
108
+					'perc_known' => $perc_sosa_count_theor,
109
+					'missing' => $missing,
110
+					'perc_missing' => 1-Functions::safeDivision($tab['sosaCount'], 2*$prev_known),
111
+					'total_known' => $tab['sosaTotalCount'],
112
+					'perc_total_known' => Functions::safeDivision($tab['sosaTotalCount'], $total_theoretical),
113
+					'different' => $gen_diff,
114
+					'perc_different' => Functions::safeDivision($gen_diff, $tab['sosaCount']),
115
+					'total_different' => $tab['diffSosaTotalCount'],
116
+					'pedi_collapse' => 1 - Functions::safeDivision($tab['diffSosaTotalCount'], $tab['sosaTotalCount'])
117
+				);
118 118
                 
119
-                $gen_theoretical = $gen_theoretical * 2;
120
-                $prev_known=$tab['sosaCount'];
121
-                $prev_diff=$tab['diffSosaTotalCount'];
122
-            }
119
+				$gen_theoretical = $gen_theoretical * 2;
120
+				$prev_known=$tab['sosaCount'];
121
+				$prev_diff=$tab['diffSosaTotalCount'];
122
+			}
123 123
             
124
-            $view_bag->set('generation_stats', $generation_stats);
124
+			$view_bag->set('generation_stats', $generation_stats);
125 125
             
126
-            $gen_depth_stats = $this->sosa_provider->getGenerationDepthStatsAtGen(1);
127
-            $view_bag->set('mean_gen_depth', count($gen_depth_stats) > 0 ? $gen_depth_stats[1]['mean_gen_depth'] : 0);
128
-            $view_bag->set('stddev_gen_depth', count($gen_depth_stats) > 0 ? $gen_depth_stats[1]['stddev_gen_depth'] : 0);
126
+			$gen_depth_stats = $this->sosa_provider->getGenerationDepthStatsAtGen(1);
127
+			$view_bag->set('mean_gen_depth', count($gen_depth_stats) > 0 ? $gen_depth_stats[1]['mean_gen_depth'] : 0);
128
+			$view_bag->set('stddev_gen_depth', count($gen_depth_stats) > 0 ? $gen_depth_stats[1]['stddev_gen_depth'] : 0);
129 129
             
130
-            $view_bag->set('top10multiancestors', $this->getTop10Ancestors());
130
+			$view_bag->set('top10multiancestors', $this->getTop10Ancestors());
131 131
             
132
-            $view_bag->set('chart_img_g2', $this->htmlAncestorDispersionG2());
133
-            $view_bag->set('chart_img_g3', $this->htmlAncestorDispersionG3());
132
+			$view_bag->set('chart_img_g2', $this->htmlAncestorDispersionG2());
133
+			$view_bag->set('chart_img_g3', $this->htmlAncestorDispersionG3());
134 134
             
135
-            $view_bag->set('chart_img_gendepth3', $this->htmlAncestorGenDepthG3());
136
-            //$view_bag->set('mean_gen_depth_gen3_stats', $this->sosa_provider->getMeanGeneratuonDepthAndDeviationAtGen(3));
137
-        }
135
+			$view_bag->set('chart_img_gendepth3', $this->htmlAncestorGenDepthG3());
136
+			//$view_bag->set('mean_gen_depth_gen3_stats', $this->sosa_provider->getMeanGeneratuonDepthAndDeviationAtGen(3));
137
+		}
138 138
         
139
-        ViewFactory::make('SosaStats', $this, $controller, $view_bag)->render();   
140
-    }
139
+		ViewFactory::make('SosaStats', $this, $controller, $view_bag)->render();   
140
+	}
141 141
     
142
-    /**
143
-     * Return an array of the top 10 of ancestor appearing multiple times, grouped by the number of occurrences.
144
-     * The key is the number of appearance, and the value contains the list of Inidvidual
145
-     * 
146
-     * @return array Top 10 ancestors with count
147
-     */
148
-    private function getTop10Ancestors()
149
-    {
150
-        $top10multiancestors = $this->sosa_provider->getTopMultiSosaAncestorsNoTies(10);
151
-        $top10ancestors = array();
152
-        if($top10multiancestors !== null && count($top10multiancestors)) {
153
-            foreach($top10multiancestors as $pid => $count) {
154
-                $indi = Individual::getInstance($pid, $this->sosa_provider->getTree());
155
-                if($indi !== null && $indi->canShowName()) {
156
-                    array_key_exists($count, $top10ancestors) ?
157
-                        $top10ancestors[$count][] = $indi:
158
-                        $top10ancestors[$count] = array($count => $indi);
159
-                }
160
-            }
161
-        }
162
-        return $top10ancestors;
163
-    }
142
+	/**
143
+	 * Return an array of the top 10 of ancestor appearing multiple times, grouped by the number of occurrences.
144
+	 * The key is the number of appearance, and the value contains the list of Inidvidual
145
+	 * 
146
+	 * @return array Top 10 ancestors with count
147
+	 */
148
+	private function getTop10Ancestors()
149
+	{
150
+		$top10multiancestors = $this->sosa_provider->getTopMultiSosaAncestorsNoTies(10);
151
+		$top10ancestors = array();
152
+		if($top10multiancestors !== null && count($top10multiancestors)) {
153
+			foreach($top10multiancestors as $pid => $count) {
154
+				$indi = Individual::getInstance($pid, $this->sosa_provider->getTree());
155
+				if($indi !== null && $indi->canShowName()) {
156
+					array_key_exists($count, $top10ancestors) ?
157
+						$top10ancestors[$count][] = $indi:
158
+						$top10ancestors[$count] = array($count => $indi);
159
+				}
160
+			}
161
+		}
162
+		return $top10ancestors;
163
+	}
164 164
         
165
-    /**
166
-     * Returns HTML code for a graph showing the dispersion of ancestors across father & mother
167
-     * @return string HTML code
168
-     */
169
-     private function htmlAncestorDispersionG2()
170
-    {
171
-        $ancestorsDispGen2 = $this->sosa_provider->getAncestorDispersionForGen(2);
172
-        if(count($ancestorsDispGen2) == 0) return;
165
+	/**
166
+	 * Returns HTML code for a graph showing the dispersion of ancestors across father & mother
167
+	 * @return string HTML code
168
+	 */
169
+	 private function htmlAncestorDispersionG2()
170
+	{
171
+		$ancestorsDispGen2 = $this->sosa_provider->getAncestorDispersionForGen(2);
172
+		if(count($ancestorsDispGen2) == 0) return;
173 173
         
174
-        $size = '600x300';
174
+		$size = '600x300';
175 175
         
176
-        $total = array_sum($ancestorsDispGen2);
177
-        $father_count = array_key_exists(1, $ancestorsDispGen2) ? $ancestorsDispGen2[1] : 0;
178
-        $father = array (
179
-            'color' => '84beff', 
180
-            'count' => $father_count, 
181
-            'perc' => Functions::safeDivision($father_count, $total), 
182
-            'name' => \Fisharebest\Webtrees\Functions\Functions::getRelationshipNameFromPath('fat')            
183
-        );
184
-        $mother_count = array_key_exists(2, $ancestorsDispGen2) ? $ancestorsDispGen2[2] : 0;
185
-        $mother = array (
186
-            'color' => 'ffd1dc', 
187
-            'count' => $mother_count, 
188
-            'perc' => Functions::safeDivision($mother_count, $total),
189
-            'name' => \Fisharebest\Webtrees\Functions\Functions::getRelationshipNameFromPath('mot')
190
-        );
191
-        $shared_count = array_key_exists(-1, $ancestorsDispGen2) ? $ancestorsDispGen2[-1] : 0;
192
-        $shared = array (
193
-            'color' => '777777', 
194
-            'count' => $shared_count, 
195
-            'perc' => Functions::safeDivision($shared_count, $total),
196
-            'name' => I18N::translate('Shared')
197
-        );
176
+		$total = array_sum($ancestorsDispGen2);
177
+		$father_count = array_key_exists(1, $ancestorsDispGen2) ? $ancestorsDispGen2[1] : 0;
178
+		$father = array (
179
+			'color' => '84beff', 
180
+			'count' => $father_count, 
181
+			'perc' => Functions::safeDivision($father_count, $total), 
182
+			'name' => \Fisharebest\Webtrees\Functions\Functions::getRelationshipNameFromPath('fat')            
183
+		);
184
+		$mother_count = array_key_exists(2, $ancestorsDispGen2) ? $ancestorsDispGen2[2] : 0;
185
+		$mother = array (
186
+			'color' => 'ffd1dc', 
187
+			'count' => $mother_count, 
188
+			'perc' => Functions::safeDivision($mother_count, $total),
189
+			'name' => \Fisharebest\Webtrees\Functions\Functions::getRelationshipNameFromPath('mot')
190
+		);
191
+		$shared_count = array_key_exists(-1, $ancestorsDispGen2) ? $ancestorsDispGen2[-1] : 0;
192
+		$shared = array (
193
+			'color' => '777777', 
194
+			'count' => $shared_count, 
195
+			'perc' => Functions::safeDivision($shared_count, $total),
196
+			'name' => I18N::translate('Shared')
197
+		);
198 198
         
199
-        $chd = $this->arrayToExtendedEncoding(array(4095 * $father['perc'], 4095 * $shared['perc'], 4095 * $mother['perc']));
200
-        $chart_title = I18N::translate('Known Sosa ancestors\' dispersion');
201
-        $chl = 
202
-             $father['name'] . ' - ' . I18N::percentage($father['perc'], 1) . '|' .
203
-             $shared['name'] . ' - ' . I18N::percentage($shared['perc'], 1) . '|' .
204
-             $mother['name'] . ' - ' . I18N::percentage($mother['perc'], 1);
205
-        return "<img src=\"https://chart.googleapis.com/chart?cht=p&chp=1.5708&amp;chd=e:{$chd}&amp;chs={$size}&amp;chco={$father['color']},{$shared['color']},{$mother['color']}&amp;chf=bg,s,ffffff00&amp;chl={$chl}\" alt=\"" . $chart_title . "\" title=\"" . $chart_title . "\" />";
206
-    }
199
+		$chd = $this->arrayToExtendedEncoding(array(4095 * $father['perc'], 4095 * $shared['perc'], 4095 * $mother['perc']));
200
+		$chart_title = I18N::translate('Known Sosa ancestors\' dispersion');
201
+		$chl = 
202
+			 $father['name'] . ' - ' . I18N::percentage($father['perc'], 1) . '|' .
203
+			 $shared['name'] . ' - ' . I18N::percentage($shared['perc'], 1) . '|' .
204
+			 $mother['name'] . ' - ' . I18N::percentage($mother['perc'], 1);
205
+		return "<img src=\"https://chart.googleapis.com/chart?cht=p&chp=1.5708&amp;chd=e:{$chd}&amp;chs={$size}&amp;chco={$father['color']},{$shared['color']},{$mother['color']}&amp;chf=bg,s,ffffff00&amp;chl={$chl}\" alt=\"" . $chart_title . "\" title=\"" . $chart_title . "\" />";
206
+	}
207 207
     
208
-    /**
209
-     * Returns HTML code for a graph showing the dispersion of ancestors across grand-parents
210
-     * @return string HTML code
211
-     */
212
-    private function htmlAncestorDispersionG3()
213
-    {
214
-        $ancestorsDispGen2 = $this->sosa_provider->getAncestorDispersionForGen(3);
208
+	/**
209
+	 * Returns HTML code for a graph showing the dispersion of ancestors across grand-parents
210
+	 * @return string HTML code
211
+	 */
212
+	private function htmlAncestorDispersionG3()
213
+	{
214
+		$ancestorsDispGen2 = $this->sosa_provider->getAncestorDispersionForGen(3);
215 215
         
216
-        $size = '700x300';
216
+		$size = '700x300';
217 217
         
218
-        $color_motmot = 'ffd1dc';
219
-        $color_motfat = 'b998a0';
220
-        $color_fatfat = '577292';
221
-        $color_fatmot = '84beff';
222
-        $color_shared = '777777';
218
+		$color_motmot = 'ffd1dc';
219
+		$color_motfat = 'b998a0';
220
+		$color_fatfat = '577292';
221
+		$color_fatmot = '84beff';
222
+		$color_shared = '777777';
223 223
     
224
-        $total_fatfat = array_key_exists(1, $ancestorsDispGen2) ? $ancestorsDispGen2[1] : 0;
225
-        $total_fatmot = array_key_exists(2, $ancestorsDispGen2) ? $ancestorsDispGen2[2] : 0;
226
-        $total_motfat = array_key_exists(4, $ancestorsDispGen2) ? $ancestorsDispGen2[4] : 0;
227
-        $total_motmot = array_key_exists(8, $ancestorsDispGen2) ? $ancestorsDispGen2[8] : 0;
228
-        $total_sha = array_key_exists(-1, $ancestorsDispGen2) ? $ancestorsDispGen2[-1] : 0;
229
-        $total = $total_fatfat + $total_fatmot + $total_motfat+ $total_motmot + $total_sha;
224
+		$total_fatfat = array_key_exists(1, $ancestorsDispGen2) ? $ancestorsDispGen2[1] : 0;
225
+		$total_fatmot = array_key_exists(2, $ancestorsDispGen2) ? $ancestorsDispGen2[2] : 0;
226
+		$total_motfat = array_key_exists(4, $ancestorsDispGen2) ? $ancestorsDispGen2[4] : 0;
227
+		$total_motmot = array_key_exists(8, $ancestorsDispGen2) ? $ancestorsDispGen2[8] : 0;
228
+		$total_sha = array_key_exists(-1, $ancestorsDispGen2) ? $ancestorsDispGen2[-1] : 0;
229
+		$total = $total_fatfat + $total_fatmot + $total_motfat+ $total_motmot + $total_sha;
230 230
     
231
-        $chd = $this->arrayToExtendedEncoding(array(
232
-	    4095 * Functions::safeDivision($total_fatfat, $total), 
233
-            4095 * Functions::safeDivision($total_fatmot, $total),
234
-            4095 * Functions::safeDivision($total_sha, $total), 
235
-            4095 * Functions::safeDivision($total_motfat, $total),
236
-            4095 * Functions::safeDivision($total_motmot, $total)          
237
-        ));
238
-        $chart_title = I18N::translate('Known Sosa ancestors\' dispersion - G3');
239
-        $chl =
240
-            \Fisharebest\Webtrees\Functions\Functions::getRelationshipNameFromPath('fatfat') . ' - ' . I18N::percentage(Functions::safeDivision($total_fatfat, $total), 1) . '|' .
241
-            \Fisharebest\Webtrees\Functions\Functions::getRelationshipNameFromPath('fatmot') . ' - ' . I18N::percentage(Functions::safeDivision($total_fatmot, $total), 1) . '|' .
242
-            I18N::translate('Shared') . ' - ' . I18N::percentage(Functions::safeDivision($total_sha, $total), 1) . '|' .
243
-            \Fisharebest\Webtrees\Functions\Functions::getRelationshipNameFromPath('motfat') . ' - ' . I18N::percentage(Functions::safeDivision($total_motfat, $total), 1) . '|' .
244
-            \Fisharebest\Webtrees\Functions\Functions::getRelationshipNameFromPath('motmot') . ' - ' . I18N::percentage(Functions::safeDivision($total_motmot, $total), 1);
245
-         return "<img src=\"https://chart.googleapis.com/chart?cht=p&chp=1.5708&amp;chd=e:{$chd}&amp;chs={$size}&amp;chco={$color_fatfat},{$color_fatmot},{$color_shared},{$color_motfat},{$color_motmot}&amp;chf=bg,s,ffffff00&amp;chl={$chl}\" alt=\"" . $chart_title . "\" title=\"" . $chart_title . "\" />";
246
-    }    
231
+		$chd = $this->arrayToExtendedEncoding(array(
232
+		4095 * Functions::safeDivision($total_fatfat, $total), 
233
+			4095 * Functions::safeDivision($total_fatmot, $total),
234
+			4095 * Functions::safeDivision($total_sha, $total), 
235
+			4095 * Functions::safeDivision($total_motfat, $total),
236
+			4095 * Functions::safeDivision($total_motmot, $total)          
237
+		));
238
+		$chart_title = I18N::translate('Known Sosa ancestors\' dispersion - G3');
239
+		$chl =
240
+			\Fisharebest\Webtrees\Functions\Functions::getRelationshipNameFromPath('fatfat') . ' - ' . I18N::percentage(Functions::safeDivision($total_fatfat, $total), 1) . '|' .
241
+			\Fisharebest\Webtrees\Functions\Functions::getRelationshipNameFromPath('fatmot') . ' - ' . I18N::percentage(Functions::safeDivision($total_fatmot, $total), 1) . '|' .
242
+			I18N::translate('Shared') . ' - ' . I18N::percentage(Functions::safeDivision($total_sha, $total), 1) . '|' .
243
+			\Fisharebest\Webtrees\Functions\Functions::getRelationshipNameFromPath('motfat') . ' - ' . I18N::percentage(Functions::safeDivision($total_motfat, $total), 1) . '|' .
244
+			\Fisharebest\Webtrees\Functions\Functions::getRelationshipNameFromPath('motmot') . ' - ' . I18N::percentage(Functions::safeDivision($total_motmot, $total), 1);
245
+		 return "<img src=\"https://chart.googleapis.com/chart?cht=p&chp=1.5708&amp;chd=e:{$chd}&amp;chs={$size}&amp;chco={$color_fatfat},{$color_fatmot},{$color_shared},{$color_motfat},{$color_motmot}&amp;chf=bg,s,ffffff00&amp;chl={$chl}\" alt=\"" . $chart_title . "\" title=\"" . $chart_title . "\" />";
246
+	}    
247 247
     
248
-    /**
249
-     * Returns HTML code for a graph showing the grand-parents' mean generation depth and standard deviation
250
-     * @return string HTML code
251
-     */
252
-    private function htmlAncestorGenDepthG3() {
253
-        $ancestorsGenDepth3 = $this->sosa_provider->getGenerationDepthStatsAtGen(3);
254
-        if(count($ancestorsGenDepth3) == 0) return;
248
+	/**
249
+	 * Returns HTML code for a graph showing the grand-parents' mean generation depth and standard deviation
250
+	 * @return string HTML code
251
+	 */
252
+	private function htmlAncestorGenDepthG3() {
253
+		$ancestorsGenDepth3 = $this->sosa_provider->getGenerationDepthStatsAtGen(3);
254
+		if(count($ancestorsGenDepth3) == 0) return;
255 255
         
256
-        $ancestors = array();
257
-        $chd_mean = array();
258
-        $chd_error_low = array();
259
-        $chd_error_high = array();
260
-        foreach($ancestorsGenDepth3 as $sosa => $genDepthStat) {
261
-            $ancestor = Individual::getInstance($genDepthStat['root_ancestor_id'], $this->sosa_provider->getTree());
262
-            if($ancestor !== null && $ancestor->canShowName()) {
263
-                $tmp = $ancestor->getAllNames();
264
-                $ancestors[] = Filter::escapeUrl($tmp[$ancestor->getPrimaryName()]['fullNN']);
265
-            }
266
-            else {
267
-                $ancestors[] = I18N::translate('Sosa %s', I18N::number($sosa));
268
-            }
269
-            $chd_mean[] = $genDepthStat['mean_gen_depth'];
270
-            $chd_error_low[] = max(0, $genDepthStat['mean_gen_depth'] - $genDepthStat['stddev_gen_depth']);
271
-            $chd_error_high[] = $genDepthStat['mean_gen_depth'] + $genDepthStat['stddev_gen_depth'];
272
-        }
256
+		$ancestors = array();
257
+		$chd_mean = array();
258
+		$chd_error_low = array();
259
+		$chd_error_high = array();
260
+		foreach($ancestorsGenDepth3 as $sosa => $genDepthStat) {
261
+			$ancestor = Individual::getInstance($genDepthStat['root_ancestor_id'], $this->sosa_provider->getTree());
262
+			if($ancestor !== null && $ancestor->canShowName()) {
263
+				$tmp = $ancestor->getAllNames();
264
+				$ancestors[] = Filter::escapeUrl($tmp[$ancestor->getPrimaryName()]['fullNN']);
265
+			}
266
+			else {
267
+				$ancestors[] = I18N::translate('Sosa %s', I18N::number($sosa));
268
+			}
269
+			$chd_mean[] = $genDepthStat['mean_gen_depth'];
270
+			$chd_error_low[] = max(0, $genDepthStat['mean_gen_depth'] - $genDepthStat['stddev_gen_depth']);
271
+			$chd_error_high[] = $genDepthStat['mean_gen_depth'] + $genDepthStat['stddev_gen_depth'];
272
+		}
273 273
         
274
-        $maxChd = ceil(max($chd_error_high));
275
-        $chd = implode(',', $chd_mean) . '|' . implode(',', $chd_error_low) . '|' . implode(',', $chd_error_high);
276
-        $chxl = implode('|', array_reverse($ancestors));
277
-        $chbh = 30;
278
-        $chs = count($ancestors) * $chbh + 50;
279
-        $chxl_title = I18N::translate('Mean generation depth and standard deviation');
274
+		$maxChd = ceil(max($chd_error_high));
275
+		$chd = implode(',', $chd_mean) . '|' . implode(',', $chd_error_low) . '|' . implode(',', $chd_error_high);
276
+		$chxl = implode('|', array_reverse($ancestors));
277
+		$chbh = 30;
278
+		$chs = count($ancestors) * $chbh + 50;
279
+		$chxl_title = I18N::translate('Mean generation depth and standard deviation');
280 280
         
281
-        return "<img src=\"https://chart.googleapis.com/chart?cht=bhs&chco=84beff&chs=600x{$chs}&chbh={$chbh}&chd=t1:{$chd}&chds=0,{$maxChd}&chxt=x,x,y&chxl=1:|{$chxl_title}|2:|{$chxl}&chxp=1,50&chxr=0,0,{$maxChd},1&chm=E,577292,1:2,,2\" />";
282
-    }
281
+		return "<img src=\"https://chart.googleapis.com/chart?cht=bhs&chco=84beff&chs=600x{$chs}&chbh={$chbh}&chd=t1:{$chd}&chds=0,{$maxChd}&chxt=x,x,y&chxl=1:|{$chxl_title}|2:|{$chxl}&chxp=1,50&chxr=0,0,{$maxChd},1&chm=E,577292,1:2,,2\" />";
282
+	}
283 283
 
284
-    /**
285
-     * Convert an array to Google Chart encoding
286
-     * @param arrat $a Array to encode
287
-     * @return string
288
-     */
289
-    private function arrayToExtendedEncoding($a) {
290
-        $xencoding = WT_GOOGLE_CHART_ENCODING;
284
+	/**
285
+	 * Convert an array to Google Chart encoding
286
+	 * @param arrat $a Array to encode
287
+	 * @return string
288
+	 */
289
+	private function arrayToExtendedEncoding($a) {
290
+		$xencoding = WT_GOOGLE_CHART_ENCODING;
291 291
     
292
-        $encoding = '';
293
-        foreach ($a as $value) {
294
-            if ($value < 0) {
295
-                $value = 0;
296
-            }
297
-            $first  = (int) ($value / 64);
298
-            $second = $value % 64;
299
-            $encoding .= $xencoding[(int) $first] . $xencoding[(int) $second];
300
-        }
292
+		$encoding = '';
293
+		foreach ($a as $value) {
294
+			if ($value < 0) {
295
+				$value = 0;
296
+			}
297
+			$first  = (int) ($value / 64);
298
+			$second = $value % 64;
299
+			$encoding .= $xencoding[(int) $first] . $xencoding[(int) $second];
300
+		}
301 301
     
302
-        return $encoding;
303
-    }
302
+		return $encoding;
303
+	}
304 304
     
305 305
     
306 306
 }
307 307
\ No newline at end of file
Please login to merge, or discard this patch.
src/Webtrees/Module/Sosa/Model/SosaProvider.php 1 patch
Indentation   +710 added lines, -710 removed lines patch added patch discarded remove patch
@@ -22,413 +22,413 @@  discard block
 block discarded – undo
22 22
  */
23 23
 class SosaProvider {
24 24
     
25
-    /**
26
-     * Maximum number of generation the database is able to hold.
27
-     * @var int MAX_DB_GENERATIONS
28
-     */
29
-    const MAX_DB_GENERATIONS = 64;
30
-    
31
-    /**
32
-     * System's default user (ID -1 in the database
33
-     * @var User $default_user
34
-     */
35
-    protected static $default_user;
36
-    
37
-    /**
38
-     * Reference user
39
-     * @var User $user
40
-     */
41
-    protected $user;
42
-    
43
-    /**
44
-     * Reference tree
45
-     * @var Tree $tree
46
-     */
47
-    protected $tree;
48
-    
49
-    /**
50
-     * Cached list of Sosa Individuals by generation
51
-     * Format: key = generation, value = array ( sosa => Individual ID)
52
-     * @var array $sosa_list_by_gen
53
-     */
54
-    protected $sosa_list_by_gen;
55
-    
56
-    /**
57
-     * Cached list of Sosa Families by generation
58
-     * Format: key = generation, value = array ( sosa => Family ID)
59
-     * @var unknown $sosa_fam_list_by_gen
60
-     */
61
-    protected $sosa_fam_list_by_gen;
62
-    
63
-    /**
64
-     * Cached array of statistics by generation
65
-     * Format:  key = generation, 
66
-     *          value = array(
67
-     *              sosaCount, sosaTotalCount, diffSosaTotalCount, firstBirth, lastBirth, avgBirth
68
-     *           )
69
-     * @var array $statistics_tab
70
-     */
71
-    protected $statistics_tab;
72
-    
73
-    /**
74
-     * Has the provider's initialisation completed
75
-     * @var bool $is_setup
76
-     */
77
-    protected $is_setup;
78
-    
79
-    /**
80
-     * Constructor for Sosa Provider.
81
-     * A provider is defined in relation to a specific tree and reference user.
82
-     * 
83
-     * @param Tree $tree
84
-     * @param User $user
85
-     */
86
-    public function __construct(Tree $tree, User $user = null) {
87
-        if(self::$default_user === null) 
88
-            self::$default_user = User::find(-1);
25
+	/**
26
+	 * Maximum number of generation the database is able to hold.
27
+	 * @var int MAX_DB_GENERATIONS
28
+	 */
29
+	const MAX_DB_GENERATIONS = 64;
30
+    
31
+	/**
32
+	 * System's default user (ID -1 in the database
33
+	 * @var User $default_user
34
+	 */
35
+	protected static $default_user;
36
+    
37
+	/**
38
+	 * Reference user
39
+	 * @var User $user
40
+	 */
41
+	protected $user;
42
+    
43
+	/**
44
+	 * Reference tree
45
+	 * @var Tree $tree
46
+	 */
47
+	protected $tree;
48
+    
49
+	/**
50
+	 * Cached list of Sosa Individuals by generation
51
+	 * Format: key = generation, value = array ( sosa => Individual ID)
52
+	 * @var array $sosa_list_by_gen
53
+	 */
54
+	protected $sosa_list_by_gen;
55
+    
56
+	/**
57
+	 * Cached list of Sosa Families by generation
58
+	 * Format: key = generation, value = array ( sosa => Family ID)
59
+	 * @var unknown $sosa_fam_list_by_gen
60
+	 */
61
+	protected $sosa_fam_list_by_gen;
62
+    
63
+	/**
64
+	 * Cached array of statistics by generation
65
+	 * Format:  key = generation, 
66
+	 *          value = array(
67
+	 *              sosaCount, sosaTotalCount, diffSosaTotalCount, firstBirth, lastBirth, avgBirth
68
+	 *           )
69
+	 * @var array $statistics_tab
70
+	 */
71
+	protected $statistics_tab;
72
+    
73
+	/**
74
+	 * Has the provider's initialisation completed
75
+	 * @var bool $is_setup
76
+	 */
77
+	protected $is_setup;
78
+    
79
+	/**
80
+	 * Constructor for Sosa Provider.
81
+	 * A provider is defined in relation to a specific tree and reference user.
82
+	 * 
83
+	 * @param Tree $tree
84
+	 * @param User $user
85
+	 */
86
+	public function __construct(Tree $tree, User $user = null) {
87
+		if(self::$default_user === null) 
88
+			self::$default_user = User::find(-1);
89 89
         
90
-        $this->tree = $tree;
91
-        $this->user = $user;
92
-        $this->is_setup = true;
93
-        if($this->user === null) $this->user = Auth::user();
94
-        if(strlen($this->user->getUserId()) == 0) $this->user = self::$default_user;
90
+		$this->tree = $tree;
91
+		$this->user = $user;
92
+		$this->is_setup = true;
93
+		if($this->user === null) $this->user = Auth::user();
94
+		if(strlen($this->user->getUserId()) == 0) $this->user = self::$default_user;
95 95
         
96
-        // Check if the user, or the default user, has a root already setup;
97
-        if(empty($this->getRootIndiId())) {
98
-            if($this->user == self::$default_user) {  // If the default user is not setup
99
-                $this->is_setup = false;
100
-            }
101
-            else {
102
-                $this->user = self::$default_user;
103
-                $this->is_setup = $this->getRootIndiId() === null;
104
-            }            
105
-        }
106
-    }
107
-    
108
-    /**
109
-     * Returns is the Provider has been successfully set up
110
-     * @return bool
111
-     */
112
-    public function isSetup() {
113
-        return $this->is_setup;
114
-    }
115
-    
116
-    /**
117
-     * Return the reference tree
118
-     * 
119
-     *  @return Tree Reference tree
120
-     */
121
-    public function getTree() {
122
-        return $this->tree;
123
-    }
124
-    
125
-    /**
126
-     * Return the reference user
127
-     * 
128
-     * @return User
129
-     */
130
-    public function getUser() {
131
-        return $this->user;
132
-    }
133
-    
134
-    /**
135
-     * Return the root individual ID for the reference tree and user.
136
-     * @return string Individual ID
137
-     */
138
-    public function getRootIndiId() {
139
-        return $this->tree->getUserPreference($this->user, 'MAJ_SOSA_ROOT_ID');
140
-    }
141
-    
142
-    /**
143
-     * Return the root individual for the reference tree and user.
144
-     * @return Individual Individual
145
-     */
146
-    public function getRootIndi() {
147
-        $root_indi_id = $this->getRootIndiId();
148
-        if(!empty($root_indi_id)) {
149
-            return Individual::getInstance($root_indi_id, $this->tree);
150
-        }
151
-        return null;
152
-    }
96
+		// Check if the user, or the default user, has a root already setup;
97
+		if(empty($this->getRootIndiId())) {
98
+			if($this->user == self::$default_user) {  // If the default user is not setup
99
+				$this->is_setup = false;
100
+			}
101
+			else {
102
+				$this->user = self::$default_user;
103
+				$this->is_setup = $this->getRootIndiId() === null;
104
+			}            
105
+		}
106
+	}
107
+    
108
+	/**
109
+	 * Returns is the Provider has been successfully set up
110
+	 * @return bool
111
+	 */
112
+	public function isSetup() {
113
+		return $this->is_setup;
114
+	}
115
+    
116
+	/**
117
+	 * Return the reference tree
118
+	 * 
119
+	 *  @return Tree Reference tree
120
+	 */
121
+	public function getTree() {
122
+		return $this->tree;
123
+	}
124
+    
125
+	/**
126
+	 * Return the reference user
127
+	 * 
128
+	 * @return User
129
+	 */
130
+	public function getUser() {
131
+		return $this->user;
132
+	}
133
+    
134
+	/**
135
+	 * Return the root individual ID for the reference tree and user.
136
+	 * @return string Individual ID
137
+	 */
138
+	public function getRootIndiId() {
139
+		return $this->tree->getUserPreference($this->user, 'MAJ_SOSA_ROOT_ID');
140
+	}
141
+    
142
+	/**
143
+	 * Return the root individual for the reference tree and user.
144
+	 * @return Individual Individual
145
+	 */
146
+	public function getRootIndi() {
147
+		$root_indi_id = $this->getRootIndiId();
148
+		if(!empty($root_indi_id)) {
149
+			return Individual::getInstance($root_indi_id, $this->tree);
150
+		}
151
+		return null;
152
+	}
153 153
        
154
-    /*****************
154
+	/*****************
155 155
      * DATA CRUD LAYER
156 156
      *****************/
157 157
     
158
-    /**
159
-     * Remove all Sosa entries related to the gedcom file and user
160
-     */
161
-    public function deleteAll() {
162
-        if(!$this->is_setup) return;
163
-        Database::prepare(
164
-            'DELETE FROM `##maj_sosa`'.
165
-            ' WHERE majs_gedcom_id= :tree_id and majs_user_id = :user_id ')
166
-            ->execute(array(
167
-                'tree_id' => $this->tree->getTreeId(), 
168
-                'user_id' => $this->user->getUserId()                
169
-            ));
170
-    }
171
-    
172
-    /**
173
-     * Remove all ancestors of a sosa number
174
-     * 
175
-     * @param int $sosa
176
-     */
177
-    public function deleteAncestors($sosa) {
178
-        if(!$this->is_setup) return;
179
-        $gen = Functions::getGeneration($sosa);
180
-        Database::prepare(
181
-            'DELETE FROM `##maj_sosa`'.
182
-            ' WHERE majs_gedcom_id=:tree_id and majs_user_id = :user_id' .
183
-            ' AND majs_gen >= :gen' .
184
-            ' AND FLOOR(majs_sosa / (POW(2, (majs_gen - :gen)))) = :sosa'
185
-        )->execute(array(
186
-            'tree_id' => $this->tree->getTreeId(), 
187
-            'user_id' => $this->user->getUserId(),
188
-            'gen' => $gen,
189
-            'sosa' => $sosa
190
-        ));
191
-    }    
192
-    
193
-    /**
194
-     * Insert (or update if already existing) a list of Sosa individuals
195
-     * @param array $sosa_records
196
-     */
197
-    public function insertOrUpdate($sosa_records) {
198
-        if(!$this->is_setup) return;
158
+	/**
159
+	 * Remove all Sosa entries related to the gedcom file and user
160
+	 */
161
+	public function deleteAll() {
162
+		if(!$this->is_setup) return;
163
+		Database::prepare(
164
+			'DELETE FROM `##maj_sosa`'.
165
+			' WHERE majs_gedcom_id= :tree_id and majs_user_id = :user_id ')
166
+			->execute(array(
167
+				'tree_id' => $this->tree->getTreeId(), 
168
+				'user_id' => $this->user->getUserId()                
169
+			));
170
+	}
171
+    
172
+	/**
173
+	 * Remove all ancestors of a sosa number
174
+	 * 
175
+	 * @param int $sosa
176
+	 */
177
+	public function deleteAncestors($sosa) {
178
+		if(!$this->is_setup) return;
179
+		$gen = Functions::getGeneration($sosa);
180
+		Database::prepare(
181
+			'DELETE FROM `##maj_sosa`'.
182
+			' WHERE majs_gedcom_id=:tree_id and majs_user_id = :user_id' .
183
+			' AND majs_gen >= :gen' .
184
+			' AND FLOOR(majs_sosa / (POW(2, (majs_gen - :gen)))) = :sosa'
185
+		)->execute(array(
186
+			'tree_id' => $this->tree->getTreeId(), 
187
+			'user_id' => $this->user->getUserId(),
188
+			'gen' => $gen,
189
+			'sosa' => $sosa
190
+		));
191
+	}    
192
+    
193
+	/**
194
+	 * Insert (or update if already existing) a list of Sosa individuals
195
+	 * @param array $sosa_records
196
+	 */
197
+	public function insertOrUpdate($sosa_records) {
198
+		if(!$this->is_setup) return;
199 199
         
200
-        $treeid = $this->tree->getTreeId();
201
-        $userid = $this->user->getUserId();
202
-        $questionmarks_table = array();
203
-        $values_table = array();
200
+		$treeid = $this->tree->getTreeId();
201
+		$userid = $this->user->getUserId();
202
+		$questionmarks_table = array();
203
+		$values_table = array();
204 204
         
205
-        $i = 0;
206
-        foreach  ($sosa_records as $row) {
207
-            $gen = Functions::getGeneration($row['sosa']);
208
-            if($gen <= self::MAX_DB_GENERATIONS) {
209
-                $questionmarks_table[] = 
210
-                    '(:tree_id'.$i.', :user_id'.$i.', :sosa'.$i.', :indi_id'.$i.', :gen'.$i.', :byear'.$i.', :byearest'.$i.', :dyear'.$i.', :dyearest'.$i.')';
211
-                $values_table = array_merge(
212
-                    $values_table, 
213
-                    array(
214
-                        'tree_id'.$i => $treeid, 
215
-                        'user_id'.$i => $userid, 
216
-                        'sosa'.$i => $row['sosa'], 
217
-                        'indi_id'.$i => $row['indi'], 
218
-                        'gen'.$i => Functions::getGeneration($row['sosa']),
219
-                        'byear'.$i => $row['birth_year'],
220
-                        'byearest'.$i => $row['birth_year_est'],
221
-                        'dyear'.$i => $row['death_year'],
222
-                        'dyearest'.$i => $row['death_year_est']
223
-                    )
224
-                );
225
-            }
226
-            $i++;
227
-        }
205
+		$i = 0;
206
+		foreach  ($sosa_records as $row) {
207
+			$gen = Functions::getGeneration($row['sosa']);
208
+			if($gen <= self::MAX_DB_GENERATIONS) {
209
+				$questionmarks_table[] = 
210
+					'(:tree_id'.$i.', :user_id'.$i.', :sosa'.$i.', :indi_id'.$i.', :gen'.$i.', :byear'.$i.', :byearest'.$i.', :dyear'.$i.', :dyearest'.$i.')';
211
+				$values_table = array_merge(
212
+					$values_table, 
213
+					array(
214
+						'tree_id'.$i => $treeid, 
215
+						'user_id'.$i => $userid, 
216
+						'sosa'.$i => $row['sosa'], 
217
+						'indi_id'.$i => $row['indi'], 
218
+						'gen'.$i => Functions::getGeneration($row['sosa']),
219
+						'byear'.$i => $row['birth_year'],
220
+						'byearest'.$i => $row['birth_year_est'],
221
+						'dyear'.$i => $row['death_year'],
222
+						'dyearest'.$i => $row['death_year_est']
223
+					)
224
+				);
225
+			}
226
+			$i++;
227
+		}
228 228
         
229
-        $sql = 'REPLACE INTO `##maj_sosa`' .
230
-            ' (majs_gedcom_id, majs_user_id, majs_sosa, majs_i_id, majs_gen, majs_birth_year, majs_birth_year_est, majs_death_year, majs_death_year_est)' .
231
-            ' VALUES '. implode(',', $questionmarks_table);
232
-        Database::prepare($sql)->execute($values_table);
233
-    }
229
+		$sql = 'REPLACE INTO `##maj_sosa`' .
230
+			' (majs_gedcom_id, majs_user_id, majs_sosa, majs_i_id, majs_gen, majs_birth_year, majs_birth_year_est, majs_death_year, majs_death_year_est)' .
231
+			' VALUES '. implode(',', $questionmarks_table);
232
+		Database::prepare($sql)->execute($values_table);
233
+	}
234 234
     
235
-    /****************
235
+	/****************
236 236
      * SIMPLE QUERIES
237 237
      ****************/
238 238
     
239
-    /**
240
-     * Returns the list of Sosa numbers to which an individual is related.
241
-     * Format: key = sosa number, value = generation for the Sosa number
242
-     * 
243
-     * @param Individual $indi
244
-     * @return array Array of sosa numbers
245
-     */
246
-    public function getSosaNumbers(Individual $indi) {
247
-        if(!$this->is_setup) return array();
248
-        return Database::prepare(
249
-                'SELECT majs_sosa, majs_gen FROM `##maj_sosa`'.
250
-                ' WHERE majs_i_id=:indi_id AND majs_gedcom_id=:tree_id AND majs_user_id=:user_id'
251
-            )->execute(array(
252
-                'indi_id' => $indi->getXref(), 
253
-                'tree_id' => $this->tree->getTreeId(), 
254
-                'user_id' => $this->user->getUserId()
255
-            ))->fetchAssoc();
256
-    }
257
-    
258
-    /**
259
-     * Get the last generation of Sosa ancestors
260
-     *
261
-     * @return number Last generation if found, 1 otherwise
262
-     */
263
-    public function getLastGeneration() {
264
-        if(!$this->is_setup) return;
265
-        return Database::prepare(
266
-                'SELECT MAX(majs_gen) FROM `##maj_sosa`'.
267
-                ' WHERE majs_gedcom_id=:tree_id AND majs_user_id=:user_id'
268
-            )->execute(array(
269
-                'tree_id' => $this->tree->getTreeId(), 
270
-                'user_id' => $this->user->getUserId()                
271
-            ))->fetchOne() ?: 1;
272
-    }
273
-    
274
-    /*************
239
+	/**
240
+	 * Returns the list of Sosa numbers to which an individual is related.
241
+	 * Format: key = sosa number, value = generation for the Sosa number
242
+	 * 
243
+	 * @param Individual $indi
244
+	 * @return array Array of sosa numbers
245
+	 */
246
+	public function getSosaNumbers(Individual $indi) {
247
+		if(!$this->is_setup) return array();
248
+		return Database::prepare(
249
+				'SELECT majs_sosa, majs_gen FROM `##maj_sosa`'.
250
+				' WHERE majs_i_id=:indi_id AND majs_gedcom_id=:tree_id AND majs_user_id=:user_id'
251
+			)->execute(array(
252
+				'indi_id' => $indi->getXref(), 
253
+				'tree_id' => $this->tree->getTreeId(), 
254
+				'user_id' => $this->user->getUserId()
255
+			))->fetchAssoc();
256
+	}
257
+    
258
+	/**
259
+	 * Get the last generation of Sosa ancestors
260
+	 *
261
+	 * @return number Last generation if found, 1 otherwise
262
+	 */
263
+	public function getLastGeneration() {
264
+		if(!$this->is_setup) return;
265
+		return Database::prepare(
266
+				'SELECT MAX(majs_gen) FROM `##maj_sosa`'.
267
+				' WHERE majs_gedcom_id=:tree_id AND majs_user_id=:user_id'
268
+			)->execute(array(
269
+				'tree_id' => $this->tree->getTreeId(), 
270
+				'user_id' => $this->user->getUserId()                
271
+			))->fetchOne() ?: 1;
272
+	}
273
+    
274
+	/*************
275 275
      * SOSA LISTS
276 276
      *************/
277 277
     
278
-    /**
279
-     * Return the list of all sosas, with the generations it belongs to
280
-     *
281
-     * @return array Associative array of Sosa ancestors, with their generation, comma separated
282
-     */
283
-    public function getAllSosaWithGenerations(){
284
-        if(!$this->is_setup) return array();
285
-        return Database::prepare(
286
-            'SELECT majs_i_id AS indi,' .
287
-            ' GROUP_CONCAT(DISTINCT majs_gen ORDER BY majs_gen ASC SEPARATOR ",") AS generations' .
288
-            ' FROM `##maj_sosa`' .
289
-            ' WHERE majs_gedcom_id=:tree_id AND majs_user_id=:user_id' .
290
-            ' GROUP BY majs_i_id'
291
-        )->execute(array(
292
-            'tree_id' => $this->tree->getTreeId(),
293
-            'user_id' => $this->user->getUserId()
294
-        ))->fetchAssoc();
295
-    }
296
-    
297
-    /**
298
-     * Get an associative array of Sosa individuals in generation G. Keys are Sosa numbers, values individuals.
299
-     *
300
-     * @param number $gen Generation
301
-     * @return array Array of Sosa individuals
302
-     */
303
-    public function getSosaListAtGeneration($gen){
304
-        if(!$this->is_setup) return array();
305
-        if(!$this->sosa_list_by_gen)
306
-            $this->sosa_list_by_gen = array();
278
+	/**
279
+	 * Return the list of all sosas, with the generations it belongs to
280
+	 *
281
+	 * @return array Associative array of Sosa ancestors, with their generation, comma separated
282
+	 */
283
+	public function getAllSosaWithGenerations(){
284
+		if(!$this->is_setup) return array();
285
+		return Database::prepare(
286
+			'SELECT majs_i_id AS indi,' .
287
+			' GROUP_CONCAT(DISTINCT majs_gen ORDER BY majs_gen ASC SEPARATOR ",") AS generations' .
288
+			' FROM `##maj_sosa`' .
289
+			' WHERE majs_gedcom_id=:tree_id AND majs_user_id=:user_id' .
290
+			' GROUP BY majs_i_id'
291
+		)->execute(array(
292
+			'tree_id' => $this->tree->getTreeId(),
293
+			'user_id' => $this->user->getUserId()
294
+		))->fetchAssoc();
295
+	}
296
+    
297
+	/**
298
+	 * Get an associative array of Sosa individuals in generation G. Keys are Sosa numbers, values individuals.
299
+	 *
300
+	 * @param number $gen Generation
301
+	 * @return array Array of Sosa individuals
302
+	 */
303
+	public function getSosaListAtGeneration($gen){
304
+		if(!$this->is_setup) return array();
305
+		if(!$this->sosa_list_by_gen)
306
+			$this->sosa_list_by_gen = array();
307 307
         
308
-        if($gen){
309
-            if(!isset($this->sosa_list_by_gen[$gen])){
310
-                $this->sosa_list_by_gen[$gen] = Database::prepare(
311
-                    'SELECT majs_sosa AS sosa, majs_i_id AS indi'.
312
-                    ' FROM `##maj_sosa`'.
313
-                    ' WHERE majs_gedcom_id=:tree_id AND majs_user_id=:user_id'.
314
-                    ' AND majs_gen = :gen'.
315
-                    ' ORDER BY majs_sosa ASC')
316
-                ->execute(array(
317
-                    'tree_id' => $this->tree->getTreeId(),
318
-                    'user_id' => $this->user->getUserId(),
319
-                    'gen' => $gen
320
-                ))
321
-                ->fetchAssoc();
322
-            }
323
-            return $this->sosa_list_by_gen[$gen];
324
-        }
325
-        return array();
326
-    }
327
-    
328
-    /**
329
-     * Get an associative array of Sosa families in generation G. Keys are Sosa numbers for the husband, values families.
330
-     *
331
-     * @param number $gen Generation
332
-     * @return array Array of Sosa families
333
-     */
334
-    public function getFamilySosaListAtGeneration($gen){
335
-        if(!$this->is_setup) return array();
336
-        if(!$this->sosa_fam_list_by_gen)
337
-            $this->sosa_fam_list_by_gen = array();
308
+		if($gen){
309
+			if(!isset($this->sosa_list_by_gen[$gen])){
310
+				$this->sosa_list_by_gen[$gen] = Database::prepare(
311
+					'SELECT majs_sosa AS sosa, majs_i_id AS indi'.
312
+					' FROM `##maj_sosa`'.
313
+					' WHERE majs_gedcom_id=:tree_id AND majs_user_id=:user_id'.
314
+					' AND majs_gen = :gen'.
315
+					' ORDER BY majs_sosa ASC')
316
+				->execute(array(
317
+					'tree_id' => $this->tree->getTreeId(),
318
+					'user_id' => $this->user->getUserId(),
319
+					'gen' => $gen
320
+				))
321
+				->fetchAssoc();
322
+			}
323
+			return $this->sosa_list_by_gen[$gen];
324
+		}
325
+		return array();
326
+	}
327
+    
328
+	/**
329
+	 * Get an associative array of Sosa families in generation G. Keys are Sosa numbers for the husband, values families.
330
+	 *
331
+	 * @param number $gen Generation
332
+	 * @return array Array of Sosa families
333
+	 */
334
+	public function getFamilySosaListAtGeneration($gen){
335
+		if(!$this->is_setup) return array();
336
+		if(!$this->sosa_fam_list_by_gen)
337
+			$this->sosa_fam_list_by_gen = array();
338 338
         
339
-        if($gen){
340
-            if(!isset($this->sosa_fam_list_by_gen[$gen])){
341
-                $this->sosa_fam_list_by_gen[$gen] = Database::prepare(
342
-                    'SELECT s1.majs_sosa AS sosa, f_id AS fam'.
343
-                    ' FROM `##families`'.
344
-                    ' INNER JOIN `##maj_sosa` AS s1 ON (`##families`.f_husb = s1.majs_i_id AND `##families`.f_file = s1.majs_gedcom_id)'.
345
-                    ' INNER JOIN `##maj_sosa` AS s2 ON (`##families`.f_wife = s2.majs_i_id AND `##families`.f_file = s2.majs_gedcom_id)'.
346
-                    ' WHERE s1.majs_sosa + 1 = s2.majs_sosa'.
347
-                    ' AND s1.majs_gedcom_id= :tree_id AND s1.majs_user_id=:user_id'.
348
-                    ' AND s2.majs_gedcom_id= :tree_id AND s2.majs_user_id=:user_id'.
349
-                    ' AND s1.majs_gen = :gen'.
350
-                    ' ORDER BY s1.majs_sosa ASC'
351
-                    )
352
-                    ->execute(array(
353
-                        'tree_id' => $this->tree->getTreeId(),
354
-                        'user_id' => $this->user->getUserId(),
355
-                        'gen' => $gen
356
-                    ))
357
-                    ->fetchAssoc();
358
-            }
359
-            return $this->sosa_fam_list_by_gen[$gen];
360
-        }
361
-        return array();
362
-    }
363
-    
364
-    /**
365
-     * Get an associative array of Sosa individuals in generation G who are missing parents. Keys are Sosa numbers, values individuals.
366
-     *
367
-     * @param number $gen Generation
368
-     * @return array Array of Sosa individuals
369
-     */
370
-    public function getMissingSosaListAtGeneration($gen){
371
-        if(!$this->is_setup) return array();    
372
-        if($gen){
373
-            return $this->sosa_list_by_gen[$gen] = Database::prepare(
374
-                'SELECT schild.majs_sosa sosa, schild.majs_i_id indi, sfat.majs_sosa IS NOT NULL has_father, smot.majs_sosa IS NOT NULL has_mother'.
375
-                ' FROM `##maj_sosa` schild'.
376
-                ' LEFT JOIN `##maj_sosa` sfat ON ((schild.majs_sosa * 2) = sfat.majs_sosa AND schild.majs_gedcom_id = sfat.majs_gedcom_id AND schild.majs_user_id = sfat.majs_user_id)'.
377
-                ' LEFT JOIN `##maj_sosa` smot ON ((schild.majs_sosa * 2 + 1) = smot.majs_sosa AND schild.majs_gedcom_id = smot.majs_gedcom_id AND schild.majs_user_id = smot.majs_user_id)'.
378
-                ' WHERE schild.majs_gedcom_id = :tree_id AND schild.majs_user_id = :user_id'.
379
-                ' AND schild.majs_gen = :gen'.
380
-                ' AND (sfat.majs_sosa IS NULL OR smot.majs_sosa IS NULL)'.
381
-                ' ORDER BY schild.majs_sosa ASC')
382
-                ->execute(array(
383
-                    'tree_id' => $this->tree->getTreeId(),
384
-                    'user_id' => $this->user->getUserId(),
385
-                    'gen' => $gen - 1
386
-                ))->fetchAll(\PDO::FETCH_ASSOC);
387
-        }
388
-        return array();
389
-    }
390
-    
391
-    
392
-    
393
-    /*************
339
+		if($gen){
340
+			if(!isset($this->sosa_fam_list_by_gen[$gen])){
341
+				$this->sosa_fam_list_by_gen[$gen] = Database::prepare(
342
+					'SELECT s1.majs_sosa AS sosa, f_id AS fam'.
343
+					' FROM `##families`'.
344
+					' INNER JOIN `##maj_sosa` AS s1 ON (`##families`.f_husb = s1.majs_i_id AND `##families`.f_file = s1.majs_gedcom_id)'.
345
+					' INNER JOIN `##maj_sosa` AS s2 ON (`##families`.f_wife = s2.majs_i_id AND `##families`.f_file = s2.majs_gedcom_id)'.
346
+					' WHERE s1.majs_sosa + 1 = s2.majs_sosa'.
347
+					' AND s1.majs_gedcom_id= :tree_id AND s1.majs_user_id=:user_id'.
348
+					' AND s2.majs_gedcom_id= :tree_id AND s2.majs_user_id=:user_id'.
349
+					' AND s1.majs_gen = :gen'.
350
+					' ORDER BY s1.majs_sosa ASC'
351
+					)
352
+					->execute(array(
353
+						'tree_id' => $this->tree->getTreeId(),
354
+						'user_id' => $this->user->getUserId(),
355
+						'gen' => $gen
356
+					))
357
+					->fetchAssoc();
358
+			}
359
+			return $this->sosa_fam_list_by_gen[$gen];
360
+		}
361
+		return array();
362
+	}
363
+    
364
+	/**
365
+	 * Get an associative array of Sosa individuals in generation G who are missing parents. Keys are Sosa numbers, values individuals.
366
+	 *
367
+	 * @param number $gen Generation
368
+	 * @return array Array of Sosa individuals
369
+	 */
370
+	public function getMissingSosaListAtGeneration($gen){
371
+		if(!$this->is_setup) return array();    
372
+		if($gen){
373
+			return $this->sosa_list_by_gen[$gen] = Database::prepare(
374
+				'SELECT schild.majs_sosa sosa, schild.majs_i_id indi, sfat.majs_sosa IS NOT NULL has_father, smot.majs_sosa IS NOT NULL has_mother'.
375
+				' FROM `##maj_sosa` schild'.
376
+				' LEFT JOIN `##maj_sosa` sfat ON ((schild.majs_sosa * 2) = sfat.majs_sosa AND schild.majs_gedcom_id = sfat.majs_gedcom_id AND schild.majs_user_id = sfat.majs_user_id)'.
377
+				' LEFT JOIN `##maj_sosa` smot ON ((schild.majs_sosa * 2 + 1) = smot.majs_sosa AND schild.majs_gedcom_id = smot.majs_gedcom_id AND schild.majs_user_id = smot.majs_user_id)'.
378
+				' WHERE schild.majs_gedcom_id = :tree_id AND schild.majs_user_id = :user_id'.
379
+				' AND schild.majs_gen = :gen'.
380
+				' AND (sfat.majs_sosa IS NULL OR smot.majs_sosa IS NULL)'.
381
+				' ORDER BY schild.majs_sosa ASC')
382
+				->execute(array(
383
+					'tree_id' => $this->tree->getTreeId(),
384
+					'user_id' => $this->user->getUserId(),
385
+					'gen' => $gen - 1
386
+				))->fetchAll(\PDO::FETCH_ASSOC);
387
+		}
388
+		return array();
389
+	}
390
+    
391
+    
392
+    
393
+	/*************
394 394
      * STATISTICS
395 395
      *************/
396
-    /**
397
-     * Get the statistic array detailed by generation.
398
-     * Statistics for each generation are:
399
-     * 	- The number of Sosa in generation
400
-     * 	- The number of Sosa up to generation
401
-     *  - The number of distinct Sosa up to generation
402
-     *  - The year of the first birth in generation
403
-     *  - The year of the first estimated birth in generation
404
-     *  - The year of the last birth in generation
405
-     *  - The year of the last estimated birth in generation
406
-     *  - The average year of birth in generation
407
-     *
408
-     * @return array Statistics array
409
-     */
410
-    public function getStatisticsByGeneration() {
411
-        if(!$this->is_setup) return array();
412
-        if(!$this->statistics_tab) {
413
-            $this->statistics_tab = array();
414
-            if($maxGeneration = $this->getLastGeneration()) {
415
-                for ($gen = 1; $gen <= $maxGeneration; $gen++) {
416
-                    $birthStats = $this->getStatsBirthYearInGeneration($gen);
417
-                    $this->statistics_tab[$gen] = array(
418
-                        'sosaCount'				=>	$this->getSosaCountAtGeneration($gen),
419
-                        'sosaTotalCount'		=>	$this->getSosaCountUpToGeneration($gen),
420
-                        'diffSosaTotalCount'	=>	$this->getDifferentSosaCountUpToGeneration($gen),
421
-                        'firstBirth'			=>	$birthStats['first'],
422
-                        'firstEstimatedBirth'	=>	$birthStats['first_est'],
423
-                        'lastBirth'				=>	$birthStats['last'],
424
-                        'lastEstimatedBirth'	=>	$birthStats['last_est'],
425
-                        'avgBirth'				=>	$birthStats['avg']
426
-                    );
427
-                }
428
-            }
429
-        }
430
-        return $this->statistics_tab;        
431
-    }
396
+	/**
397
+	 * Get the statistic array detailed by generation.
398
+	 * Statistics for each generation are:
399
+	 * 	- The number of Sosa in generation
400
+	 * 	- The number of Sosa up to generation
401
+	 *  - The number of distinct Sosa up to generation
402
+	 *  - The year of the first birth in generation
403
+	 *  - The year of the first estimated birth in generation
404
+	 *  - The year of the last birth in generation
405
+	 *  - The year of the last estimated birth in generation
406
+	 *  - The average year of birth in generation
407
+	 *
408
+	 * @return array Statistics array
409
+	 */
410
+	public function getStatisticsByGeneration() {
411
+		if(!$this->is_setup) return array();
412
+		if(!$this->statistics_tab) {
413
+			$this->statistics_tab = array();
414
+			if($maxGeneration = $this->getLastGeneration()) {
415
+				for ($gen = 1; $gen <= $maxGeneration; $gen++) {
416
+					$birthStats = $this->getStatsBirthYearInGeneration($gen);
417
+					$this->statistics_tab[$gen] = array(
418
+						'sosaCount'				=>	$this->getSosaCountAtGeneration($gen),
419
+						'sosaTotalCount'		=>	$this->getSosaCountUpToGeneration($gen),
420
+						'diffSosaTotalCount'	=>	$this->getDifferentSosaCountUpToGeneration($gen),
421
+						'firstBirth'			=>	$birthStats['first'],
422
+						'firstEstimatedBirth'	=>	$birthStats['first_est'],
423
+						'lastBirth'				=>	$birthStats['last'],
424
+						'lastEstimatedBirth'	=>	$birthStats['last_est'],
425
+						'avgBirth'				=>	$birthStats['avg']
426
+					);
427
+				}
428
+			}
429
+		}
430
+		return $this->statistics_tab;        
431
+	}
432 432
     
433 433
 	/**
434 434
 	 * How many individuals exist in the tree.
@@ -436,332 +436,332 @@  discard block
 block discarded – undo
436 436
 	 * @return int
437 437
 	 */
438 438
 	public function getTotalIndividuals() {
439
-	    if(!$this->is_setup) return 0;
440
-	    return Database::prepare(
441
-	        'SELECT COUNT(*) FROM `##individuals`' .
442
-	        ' WHERE i_file = :tree_id')
443
-	        ->execute(array('tree_id' => $this->tree->getTreeId()))
444
-	        ->fetchOne() ?: 0;
439
+		if(!$this->is_setup) return 0;
440
+		return Database::prepare(
441
+			'SELECT COUNT(*) FROM `##individuals`' .
442
+			' WHERE i_file = :tree_id')
443
+			->execute(array('tree_id' => $this->tree->getTreeId()))
444
+			->fetchOne() ?: 0;
445 445
 	}
446 446
     
447
-    /**
448
-     * Get the total Sosa count for all generations
449
-     *
450
-     * @return number Number of Sosas
451
-     */
452
-    public function getSosaCount(){
453
-        if(!$this->is_setup) return 0;
454
-        return Database::prepare(
455
-            'SELECT COUNT(majs_sosa) FROM `##maj_sosa`' .
456
-            ' WHERE majs_gedcom_id=:tree_id AND majs_user_id=:user_id')
457
-            ->execute(array(
458
-                'tree_id' => $this->tree->getTreeId(), 
459
-                'user_id' => $this->user->getUserId() 
460
-            ))->fetchOne() ?: 0;
461
-    }
462
-    
463
-    /**
464
-     * Get the number of Sosa in a specific generation.
465
-     *
466
-     * @param number $gen Generation
467
-     * @return number Number of Sosas in generation
468
-     */
469
-    public function getSosaCountAtGeneration($gen){
470
-        if(!$this->is_setup) return 0;
471
-        return Database::prepare(
472
-            'SELECT COUNT(majs_sosa) FROM `##maj_sosa`' .
473
-            ' WHERE majs_gedcom_id=:tree_id AND majs_user_id=:user_id'.
474
-            ' AND majs_gen= :gen')
475
-        ->execute(array(
476
-                'tree_id' => $this->tree->getTreeId(), 
477
-                'user_id' => $this->user->getUserId(),
478
-                'gen' => $gen            
479
-        ))->fetchOne() ?: 0;
480
-    }
481
-    
482
-    /**
483
-     * Get the total number of Sosa up to a specific generation.
484
-     *
485
-     * @param number $gen Generation
486
-     * @return number Total number of Sosas up to generation
487
-     */
488
-    public function getSosaCountUpToGeneration($gen){
489
-        if(!$this->is_setup) return 0;
490
-        return Database::prepare(
491
-            'SELECT COUNT(majs_sosa) FROM `##maj_sosa`' .
492
-            ' WHERE majs_gedcom_id=:tree_id AND majs_user_id=:user_id'.
493
-            ' AND majs_gen <= :gen')
494
-        ->execute(array(
495
-                'tree_id' => $this->tree->getTreeId(), 
496
-                'user_id' => $this->user->getUserId(),
497
-                'gen' => $gen 
498
-        ))->fetchOne() ?: 0;
499
-    }
500
-    
501
-    /**
502
-     * Get the total number of distinct Sosa individual for all generations.
503
-     *
504
-     * @return number Total number of distinct individual
505
-     */
506
-    public function getDifferentSosaCount(){
507
-        if(!$this->is_setup) return 0;
508
-        return Database::prepare(
509
-            'SELECT COUNT(DISTINCT majs_i_id) FROM `##maj_sosa`' .
510
-            ' WHERE majs_gedcom_id=:tree_id AND majs_user_id=:user_id')
511
-        ->execute(array(
512
-                'tree_id' => $this->tree->getTreeId(), 
513
-                'user_id' => $this->user->getUserId()
514
-        ))->fetchOne() ?: 0;
515
-    }
516
-    
517
-    /**
518
-     * Get the number of distinct Sosa individual up to a specific generation.
519
-     *
520
-     * @param number $gen Generation
521
-     * @return number Number of distinct Sosa individuals up to generation
522
-     */
523
-    public function getDifferentSosaCountUpToGeneration($gen){
524
-        if(!$this->is_setup) return 0;
525
-        return Database::prepare(
526
-            'SELECT COUNT(DISTINCT majs_i_id) FROM `##maj_sosa`' .
527
-            ' WHERE majs_gedcom_id=:tree_id AND majs_user_id=:user_id'.
528
-            ' AND majs_gen <= :gen')
529
-        ->execute(array(
530
-                'tree_id' => $this->tree->getTreeId(), 
531
-                'user_id' => $this->user->getUserId(),
532
-                'gen' => $gen 
533
-        ))->fetchOne() ?: 0;
534
-    }
535
-    
536
-    /**
537
-     * Get an array of birth statistics for a specific generation
538
-     * Statistics are :
539
-     * 	- first : First birth year in generation
540
-     *  - first_est: First estimated birth year in generation
541
-     *  - last : Last birth year in generation
542
-     *  - last_est : Last estimated birth year in generation
543
-     *  - avg : Average birth year (based on non-estimated birth date)
544
-     *
545
-     * @param number $gen Generation
546
-     * @return array Birth statistics array
547
-     */
548
-    public function getStatsBirthYearInGeneration($gen){
549
-        if(!$this->is_setup) return array('first' => 0, 'first_est' => 0, 'avg' => 0, 'last' => 0, 'last_est' => 0);
550
-        return Database::prepare(
551
-            'SELECT'.
552
-            ' MIN(majs_birth_year) AS first, MIN(majs_birth_year_est) AS first_est,'.
553
-            ' AVG(majs_birth_year) AS avg,'.
554
-            ' MAX(majs_birth_year) AS last, MAX(majs_birth_year_est) AS last_est'.
555
-            ' FROM `##maj_sosa`'.
556
-            ' WHERE majs_gedcom_id=:tree_id AND majs_user_id=:user_id'.
557
-            ' AND majs_gen=:gen')
558
-            ->execute(array(
559
-                'tree_id' => $this->tree->getTreeId(), 
560
-                'user_id' => $this->user->getUserId(),
561
-                'gen' => $gen))
562
-            ->fetchOneRow(\PDO::FETCH_ASSOC) ?: array('first' => 0, 'first_est' => 0, 'avg' => 0, 'last' => 0, 'last_est' => 0);
563
-    }
564
-    
565
-    /**
566
-     * Get the mean generation time, based on a linear regression of birth years and generations
567
-     *
568
-     * @return number|NULL Mean generation time
569
-     */
570
-    public function getMeanGenerationTime(){
571
-        if(!$this->is_setup) return;
572
-        if(!$this->statistics_tab){
573
-            $this->getStatisticsByGeneration();
574
-        }
575
-        //Linear regression on x=generation and y=birthdate
576
-        $sum_xy = $sum_x = $sum_y= $sum_x2 = $n = 0;
577
-        foreach($this->statistics_tab as $gen=>$stats){
578
-            if(!is_null($stats['avgBirth'])) {
579
-                $n++;
580
-                $sum_xy+=$gen*$stats['avgBirth'];
581
-                $sum_x+=$gen;
582
-                $sum_y+=$stats['avgBirth'];
583
-                $sum_x2+=$gen*$gen;
584
-            }
585
-        }
586
-        $denom=($n*$sum_x2)-($sum_x*$sum_x);
587
-        if($denom!=0){
588
-            return -(($n*$sum_xy)-($sum_x*$sum_y))/($denom);
589
-        }
590
-        return null;
591
-    }
592
-    
593
-    /**
594
-     * Return an array of the mean generation depth and standard deviation for all Sosa ancestors at a given generation.
595
-     * Sosa 1 is of generation 1.
596
-     * 
597
-     * Mean generation depth and deviation are calculated based on the works of Marie-Héléne Cazes and Pierre Cazes,
598
-     * published in Population (French Edition), Vol. 51, No. 1 (Jan. - Feb., 1996), pp. 117-140
599
-     * http://kintip.net/index.php?option=com_jdownloads&task=download.send&id=9&catid=4&m=0
600
-     * 
601
-     * Format: 
602
-     *  - key : sosa number of the ancestor
603
-     *  - values: array
604
-     *      - root_ancestor_id : ID of the ancestor
605
-     *      - mean_gen_depth : Mean generation depth
606
-     *      - stddev_gen_depth : Standard deviation of generation depth
607
-     *  
608
-     * @param number $gen Sosa generation
609
-     * @return array
610
-     */
611
-    public function getGenerationDepthStatsAtGen($gen) {
612
-        if(!$this->is_setup) return array();
613
-        $gen_depth_stats_raw = Database::prepare(
614
-            'SELECT stats_by_gen.root_ancestor AS root_ancestor_sosa,'.
615
-            '   sosa_list.majs_i_id as root_ancestor_id,'.
616
-            '   1 + SUM( (majs_gen_norm) * ( 2 * full_root_count + semi_root_count) /  (2 * POWER(2, majs_gen_norm))) AS mean_gen_depth,'.
617
-            '   SQRT('. 
618
-            '       SUM(POWER(majs_gen_norm, 2) * ( 2 * full_root_count + semi_root_count) /  (2 * POWER(2, majs_gen_norm)))'.
619
-            '       - POWER( SUM( (majs_gen_norm) * ( 2 * full_root_count + semi_root_count) /  (2 * POWER(2, majs_gen_norm))), 2)'.
620
-            '   ) AS stddev_gen_depth'.
621
-            ' FROM('.
622
-            '   SELECT'.
623
-            '       sosa.majs_gedcom_id,'.
624
-            '       sosa.majs_user_id,'.
625
-            '       sosa.majs_gen - :gen AS majs_gen_norm,'.
626
-            '       FLOOR(((sosa.majs_sosa / POW(2, sosa.majs_gen -1 )) - 1) * POWER(2, :gen - 1)) + POWER(2, :gen - 1) AS root_ancestor,'.
627
-            '       SUM(case when sosa_fat.majs_i_id IS NULL AND sosa_mot.majs_i_id IS NULL THEN 1 ELSE 0 END) AS full_root_count,'.
628
-            '       SUM(case when sosa_fat.majs_i_id IS NULL AND sosa_mot.majs_i_id IS NULL THEN 0 ELSE 1 END) As semi_root_count'.
629
-            '   FROM `##maj_sosa` AS sosa'.
630
-            '   LEFT JOIN `##maj_sosa` AS sosa_fat ON sosa_fat.majs_sosa = 2 * sosa.majs_sosa'.
631
-            '       AND sosa_fat.majs_gedcom_id = sosa.majs_gedcom_id'.
632
-            '       AND sosa_fat.majs_user_id = sosa.majs_user_id'.
633
-            '   LEFT JOIN `##maj_sosa` AS sosa_mot ON sosa_mot.majs_sosa = 2 * sosa.majs_sosa + 1'.
634
-            '       AND sosa_mot.majs_gedcom_id = sosa.majs_gedcom_id'.
635
-            '       AND sosa_mot.majs_user_id = sosa.majs_user_id'.
636
-            '   WHERE sosa.majs_gedcom_id = :tree_id'.
637
-            '       AND sosa.majs_user_id = :user_id'.
638
-            '       AND sosa.majs_gen >=  :gen'.
639
-            '       AND (sosa_fat.majs_i_id IS NULL OR sosa_mot.majs_i_id IS NULL)'.
640
-            '   GROUP BY sosa.majs_gen, root_ancestor'.
641
-            ' ) AS stats_by_gen'.
642
-            ' INNER JOIN `##maj_sosa` sosa_list ON sosa_list.majs_gedcom_id = stats_by_gen.majs_gedcom_id'.
643
-            '   AND sosa_list.majs_user_id = stats_by_gen.majs_user_id'.
644
-            '   AND sosa_list.majs_sosa = stats_by_gen.root_ancestor'.
645
-            ' GROUP BY stats_by_gen.root_ancestor, sosa_list.majs_i_id'.
646
-            ' ORDER BY stats_by_gen.root_ancestor')
647
-        ->execute(array(
648
-            'tree_id' => $this->tree->getTreeId(),
649
-            'user_id' => $this->user->getUserId(),
650
-            'gen' => $gen
651
-        ))->fetchAll() ?: array();
447
+	/**
448
+	 * Get the total Sosa count for all generations
449
+	 *
450
+	 * @return number Number of Sosas
451
+	 */
452
+	public function getSosaCount(){
453
+		if(!$this->is_setup) return 0;
454
+		return Database::prepare(
455
+			'SELECT COUNT(majs_sosa) FROM `##maj_sosa`' .
456
+			' WHERE majs_gedcom_id=:tree_id AND majs_user_id=:user_id')
457
+			->execute(array(
458
+				'tree_id' => $this->tree->getTreeId(), 
459
+				'user_id' => $this->user->getUserId() 
460
+			))->fetchOne() ?: 0;
461
+	}
462
+    
463
+	/**
464
+	 * Get the number of Sosa in a specific generation.
465
+	 *
466
+	 * @param number $gen Generation
467
+	 * @return number Number of Sosas in generation
468
+	 */
469
+	public function getSosaCountAtGeneration($gen){
470
+		if(!$this->is_setup) return 0;
471
+		return Database::prepare(
472
+			'SELECT COUNT(majs_sosa) FROM `##maj_sosa`' .
473
+			' WHERE majs_gedcom_id=:tree_id AND majs_user_id=:user_id'.
474
+			' AND majs_gen= :gen')
475
+		->execute(array(
476
+				'tree_id' => $this->tree->getTreeId(), 
477
+				'user_id' => $this->user->getUserId(),
478
+				'gen' => $gen            
479
+		))->fetchOne() ?: 0;
480
+	}
481
+    
482
+	/**
483
+	 * Get the total number of Sosa up to a specific generation.
484
+	 *
485
+	 * @param number $gen Generation
486
+	 * @return number Total number of Sosas up to generation
487
+	 */
488
+	public function getSosaCountUpToGeneration($gen){
489
+		if(!$this->is_setup) return 0;
490
+		return Database::prepare(
491
+			'SELECT COUNT(majs_sosa) FROM `##maj_sosa`' .
492
+			' WHERE majs_gedcom_id=:tree_id AND majs_user_id=:user_id'.
493
+			' AND majs_gen <= :gen')
494
+		->execute(array(
495
+				'tree_id' => $this->tree->getTreeId(), 
496
+				'user_id' => $this->user->getUserId(),
497
+				'gen' => $gen 
498
+		))->fetchOne() ?: 0;
499
+	}
500
+    
501
+	/**
502
+	 * Get the total number of distinct Sosa individual for all generations.
503
+	 *
504
+	 * @return number Total number of distinct individual
505
+	 */
506
+	public function getDifferentSosaCount(){
507
+		if(!$this->is_setup) return 0;
508
+		return Database::prepare(
509
+			'SELECT COUNT(DISTINCT majs_i_id) FROM `##maj_sosa`' .
510
+			' WHERE majs_gedcom_id=:tree_id AND majs_user_id=:user_id')
511
+		->execute(array(
512
+				'tree_id' => $this->tree->getTreeId(), 
513
+				'user_id' => $this->user->getUserId()
514
+		))->fetchOne() ?: 0;
515
+	}
516
+    
517
+	/**
518
+	 * Get the number of distinct Sosa individual up to a specific generation.
519
+	 *
520
+	 * @param number $gen Generation
521
+	 * @return number Number of distinct Sosa individuals up to generation
522
+	 */
523
+	public function getDifferentSosaCountUpToGeneration($gen){
524
+		if(!$this->is_setup) return 0;
525
+		return Database::prepare(
526
+			'SELECT COUNT(DISTINCT majs_i_id) FROM `##maj_sosa`' .
527
+			' WHERE majs_gedcom_id=:tree_id AND majs_user_id=:user_id'.
528
+			' AND majs_gen <= :gen')
529
+		->execute(array(
530
+				'tree_id' => $this->tree->getTreeId(), 
531
+				'user_id' => $this->user->getUserId(),
532
+				'gen' => $gen 
533
+		))->fetchOne() ?: 0;
534
+	}
535
+    
536
+	/**
537
+	 * Get an array of birth statistics for a specific generation
538
+	 * Statistics are :
539
+	 * 	- first : First birth year in generation
540
+	 *  - first_est: First estimated birth year in generation
541
+	 *  - last : Last birth year in generation
542
+	 *  - last_est : Last estimated birth year in generation
543
+	 *  - avg : Average birth year (based on non-estimated birth date)
544
+	 *
545
+	 * @param number $gen Generation
546
+	 * @return array Birth statistics array
547
+	 */
548
+	public function getStatsBirthYearInGeneration($gen){
549
+		if(!$this->is_setup) return array('first' => 0, 'first_est' => 0, 'avg' => 0, 'last' => 0, 'last_est' => 0);
550
+		return Database::prepare(
551
+			'SELECT'.
552
+			' MIN(majs_birth_year) AS first, MIN(majs_birth_year_est) AS first_est,'.
553
+			' AVG(majs_birth_year) AS avg,'.
554
+			' MAX(majs_birth_year) AS last, MAX(majs_birth_year_est) AS last_est'.
555
+			' FROM `##maj_sosa`'.
556
+			' WHERE majs_gedcom_id=:tree_id AND majs_user_id=:user_id'.
557
+			' AND majs_gen=:gen')
558
+			->execute(array(
559
+				'tree_id' => $this->tree->getTreeId(), 
560
+				'user_id' => $this->user->getUserId(),
561
+				'gen' => $gen))
562
+			->fetchOneRow(\PDO::FETCH_ASSOC) ?: array('first' => 0, 'first_est' => 0, 'avg' => 0, 'last' => 0, 'last_est' => 0);
563
+	}
564
+    
565
+	/**
566
+	 * Get the mean generation time, based on a linear regression of birth years and generations
567
+	 *
568
+	 * @return number|NULL Mean generation time
569
+	 */
570
+	public function getMeanGenerationTime(){
571
+		if(!$this->is_setup) return;
572
+		if(!$this->statistics_tab){
573
+			$this->getStatisticsByGeneration();
574
+		}
575
+		//Linear regression on x=generation and y=birthdate
576
+		$sum_xy = $sum_x = $sum_y= $sum_x2 = $n = 0;
577
+		foreach($this->statistics_tab as $gen=>$stats){
578
+			if(!is_null($stats['avgBirth'])) {
579
+				$n++;
580
+				$sum_xy+=$gen*$stats['avgBirth'];
581
+				$sum_x+=$gen;
582
+				$sum_y+=$stats['avgBirth'];
583
+				$sum_x2+=$gen*$gen;
584
+			}
585
+		}
586
+		$denom=($n*$sum_x2)-($sum_x*$sum_x);
587
+		if($denom!=0){
588
+			return -(($n*$sum_xy)-($sum_x*$sum_y))/($denom);
589
+		}
590
+		return null;
591
+	}
592
+    
593
+	/**
594
+	 * Return an array of the mean generation depth and standard deviation for all Sosa ancestors at a given generation.
595
+	 * Sosa 1 is of generation 1.
596
+	 * 
597
+	 * Mean generation depth and deviation are calculated based on the works of Marie-Héléne Cazes and Pierre Cazes,
598
+	 * published in Population (French Edition), Vol. 51, No. 1 (Jan. - Feb., 1996), pp. 117-140
599
+	 * http://kintip.net/index.php?option=com_jdownloads&task=download.send&id=9&catid=4&m=0
600
+	 * 
601
+	 * Format: 
602
+	 *  - key : sosa number of the ancestor
603
+	 *  - values: array
604
+	 *      - root_ancestor_id : ID of the ancestor
605
+	 *      - mean_gen_depth : Mean generation depth
606
+	 *      - stddev_gen_depth : Standard deviation of generation depth
607
+	 *  
608
+	 * @param number $gen Sosa generation
609
+	 * @return array
610
+	 */
611
+	public function getGenerationDepthStatsAtGen($gen) {
612
+		if(!$this->is_setup) return array();
613
+		$gen_depth_stats_raw = Database::prepare(
614
+			'SELECT stats_by_gen.root_ancestor AS root_ancestor_sosa,'.
615
+			'   sosa_list.majs_i_id as root_ancestor_id,'.
616
+			'   1 + SUM( (majs_gen_norm) * ( 2 * full_root_count + semi_root_count) /  (2 * POWER(2, majs_gen_norm))) AS mean_gen_depth,'.
617
+			'   SQRT('. 
618
+			'       SUM(POWER(majs_gen_norm, 2) * ( 2 * full_root_count + semi_root_count) /  (2 * POWER(2, majs_gen_norm)))'.
619
+			'       - POWER( SUM( (majs_gen_norm) * ( 2 * full_root_count + semi_root_count) /  (2 * POWER(2, majs_gen_norm))), 2)'.
620
+			'   ) AS stddev_gen_depth'.
621
+			' FROM('.
622
+			'   SELECT'.
623
+			'       sosa.majs_gedcom_id,'.
624
+			'       sosa.majs_user_id,'.
625
+			'       sosa.majs_gen - :gen AS majs_gen_norm,'.
626
+			'       FLOOR(((sosa.majs_sosa / POW(2, sosa.majs_gen -1 )) - 1) * POWER(2, :gen - 1)) + POWER(2, :gen - 1) AS root_ancestor,'.
627
+			'       SUM(case when sosa_fat.majs_i_id IS NULL AND sosa_mot.majs_i_id IS NULL THEN 1 ELSE 0 END) AS full_root_count,'.
628
+			'       SUM(case when sosa_fat.majs_i_id IS NULL AND sosa_mot.majs_i_id IS NULL THEN 0 ELSE 1 END) As semi_root_count'.
629
+			'   FROM `##maj_sosa` AS sosa'.
630
+			'   LEFT JOIN `##maj_sosa` AS sosa_fat ON sosa_fat.majs_sosa = 2 * sosa.majs_sosa'.
631
+			'       AND sosa_fat.majs_gedcom_id = sosa.majs_gedcom_id'.
632
+			'       AND sosa_fat.majs_user_id = sosa.majs_user_id'.
633
+			'   LEFT JOIN `##maj_sosa` AS sosa_mot ON sosa_mot.majs_sosa = 2 * sosa.majs_sosa + 1'.
634
+			'       AND sosa_mot.majs_gedcom_id = sosa.majs_gedcom_id'.
635
+			'       AND sosa_mot.majs_user_id = sosa.majs_user_id'.
636
+			'   WHERE sosa.majs_gedcom_id = :tree_id'.
637
+			'       AND sosa.majs_user_id = :user_id'.
638
+			'       AND sosa.majs_gen >=  :gen'.
639
+			'       AND (sosa_fat.majs_i_id IS NULL OR sosa_mot.majs_i_id IS NULL)'.
640
+			'   GROUP BY sosa.majs_gen, root_ancestor'.
641
+			' ) AS stats_by_gen'.
642
+			' INNER JOIN `##maj_sosa` sosa_list ON sosa_list.majs_gedcom_id = stats_by_gen.majs_gedcom_id'.
643
+			'   AND sosa_list.majs_user_id = stats_by_gen.majs_user_id'.
644
+			'   AND sosa_list.majs_sosa = stats_by_gen.root_ancestor'.
645
+			' GROUP BY stats_by_gen.root_ancestor, sosa_list.majs_i_id'.
646
+			' ORDER BY stats_by_gen.root_ancestor')
647
+		->execute(array(
648
+			'tree_id' => $this->tree->getTreeId(),
649
+			'user_id' => $this->user->getUserId(),
650
+			'gen' => $gen
651
+		))->fetchAll() ?: array();
652 652
         
653
-        $gen_depth_stats = array();
654
-        foreach ($gen_depth_stats_raw as $gen_depth_stat) {
655
-            $gen_depth_stats[$gen_depth_stat->root_ancestor_sosa] = array(
656
-                'root_ancestor_id' => $gen_depth_stat->root_ancestor_id,
657
-                'mean_gen_depth' => $gen_depth_stat->mean_gen_depth,
658
-                'stddev_gen_depth' => $gen_depth_stat->stddev_gen_depth
659
-            );
660
-        }
661
-        return $gen_depth_stats;
662
-    }
663
-    
664
-    /**
665
-     * Return a computed array of statistics about the dispersion of ancestors across the ancestors
666
-     * at a specified generation.
667
-     * This statistics cannot be used for generations above 11, as it would cause a out of range in MySQL
668
-     * 
669
-     * Format: 
670
-     *  - key : a base-2 representation of the ancestor at generation G for which exclusive ancestors have been found,
671
-     *          -1 is used for shared ancestors
672
-     *          For instance base2(0100) = base10(4) represent the maternal grand father
673
-     *  - values: number of ancestors exclusively in the ancestors of the ancestor in key
674
-     *  
675
-     *  For instance a result at generation 3 could be :
676
-     *      array (   -1        =>  12      -> 12 ancestors are shared by the grand-parents
677
-     *                base10(1) =>  32      -> 32 ancestors are exclusive to the paternal grand-father
678
-     *                base10(2) =>  25      -> 25 ancestors are exclusive to the paternal grand-mother
679
-     *                base10(4) =>  12      -> 12 ancestors are exclusive to the maternal grand-father
680
-     *                base10(8) =>  30      -> 30 ancestors are exclusive to the maternal grand-mother
681
-     *            )
682
-     *  
683
-     * @param int $gen Reference generation
684
-     * @return array
685
-     */
686
-    public function getAncestorDispersionForGen($gen) {
687
-        if(!$this->is_setup || $gen > 11) return array();  // Going further than 11 gen will be out of range in the query
688
-        return Database::prepare(
689
-            'SELECT branches, count(i_id)'.
690
-            ' FROM ('.
691
-            '   SELECT i_id,'.
692
-            '       CASE'.
693
-            '           WHEN CEIL(LOG2(SUM(branch))) = LOG2(SUM(branch)) THEN SUM(branch)'.
694
-            '           ELSE -1'.   // We put all ancestors shared between some branches in the same bucket
695
-            '       END branches'.
696
-            '   FROM ('.
697
-            '       SELECT DISTINCT majs_i_id i_id,'.
698
-            '           POW(2, FLOOR(majs_sosa / POW(2, (majs_gen - :gen))) - POW(2, :gen -1)) branch'.
699
-            '       FROM `##maj_sosa`'.
700
-            '       WHERE majs_gedcom_id = :tree_id AND majs_user_id = :user_id'.
701
-            '           AND majs_gen >= :gen'.
702
-            '   ) indistat'.
703
-            '   GROUP BY i_id'.
704
-            ') grouped'.
705
-            ' GROUP BY branches')
706
-            ->execute(array(
707
-                'tree_id' => $this->tree->getTreeId(), 
708
-                'user_id' => $this->user->getUserId(),
709
-                'gen' => $gen
710
-            ))->fetchAssoc() ?: array();
711
-    }
712
-    
713
-    /**
714
-     * Return an array of the most duplicated root Sosa ancestors.
715
-     * The number of ancestors to return is limited by the parameter $limit.
716
-     * If several individuals are tied when reaching the limit, none of them are returned,
717
-     * which means that there can be less individuals returned than requested.
718
-     * 
719
-     * Format: 
720
-     *  - key : root Sosa individual
721
-     *  - value: number of duplications of the ancestor (e.g. 3 if it appears 3 times)
722
-     * 
723
-     * @param number $limit Maximum number of individuals to return
724
-     * @return array 
725
-     */
726
-    public function getTopMultiSosaAncestorsNoTies($limit) {
727
-        if(!$this->is_setup) return array();
728
-        return Database::prepare(
729
-            'SELECT sosa_i_id, sosa_count FROM ('.
730
-            '   SELECT'.
731
-            '       top_sosa.sosa_i_id, top_sosa.sosa_count, top_sosa.sosa_min,'.
732
-            '       @keep := IF(@prev_count = 0 OR sosa_count = @prev_count, @keep, 1) AS keep,'.
733
-            '       @prev_count := top_sosa.sosa_count AS prev_count'.
734
-            '   FROM ('.
735
-            '       SELECT'.
736
-            '           sosa.majs_i_id sosa_i_id,'.
737
-            '           COUNT(sosa.majs_sosa) sosa_count,'.
738
-            '           MIN(sosa.majs_sosa) sosa_min'.
739
-            '       FROM ##maj_sosa AS sosa'.
740
-            '       LEFT JOIN ##maj_sosa AS sosa_fat ON sosa_fat.majs_sosa = 2 * sosa.majs_sosa'.   // Link to sosa's father
741
-            '           AND sosa.majs_gedcom_id = sosa_fat.majs_gedcom_id'.
742
-            '           AND sosa.majs_user_id = sosa_fat.majs_user_id'.
743
-            '       LEFT JOIN ##maj_sosa AS sosa_mot on sosa_mot.majs_sosa = (2 * sosa.majs_sosa + 1)'.  // Link to sosa's mother
744
-            '           AND sosa.majs_gedcom_id = sosa_fat.majs_gedcom_id'.
745
-            '           AND sosa.majs_user_id = sosa_fat.majs_user_id'.
746
-            '       WHERE sosa.majs_gedcom_id = :tree_id'.
747
-            '       AND sosa.majs_user_id = :user_id'.
748
-            '       AND sosa_fat.majs_sosa IS NULL'.    // We keep only root individuals, i.e. those with no father or mother
749
-            '       AND sosa_mot.majs_sosa IS NULL'. 
750
-            '       GROUP BY sosa.majs_i_id'.
751
-            '       HAVING COUNT(sosa.majs_sosa) > 1'.   // Limit to the duplicate sosas.
752
-            '       ORDER BY COUNT(sosa.majs_sosa) DESC'.
753
-            '       LIMIT ' . ($limit + 1) . // We want to select one more than required
754
-            '   ) AS top_sosa,'.
755
-            '   (SELECT @prev_count := 0, @keep := 0) x'.
756
-            '   ORDER BY top_sosa.sosa_count ASC'.
757
-            ' ) top_sosa_list'.
758
-            ' WHERE keep = 1'.
759
-            ' ORDER BY sosa_count DESC, sosa_min ASC'
760
-            )->execute(array(
761
-                'tree_id' => $this->tree->getTreeId(),
762
-                'user_id' => $this->user->getUserId()
763
-            ))->fetchAssoc() ?: array();
764
-    }
653
+		$gen_depth_stats = array();
654
+		foreach ($gen_depth_stats_raw as $gen_depth_stat) {
655
+			$gen_depth_stats[$gen_depth_stat->root_ancestor_sosa] = array(
656
+				'root_ancestor_id' => $gen_depth_stat->root_ancestor_id,
657
+				'mean_gen_depth' => $gen_depth_stat->mean_gen_depth,
658
+				'stddev_gen_depth' => $gen_depth_stat->stddev_gen_depth
659
+			);
660
+		}
661
+		return $gen_depth_stats;
662
+	}
663
+    
664
+	/**
665
+	 * Return a computed array of statistics about the dispersion of ancestors across the ancestors
666
+	 * at a specified generation.
667
+	 * This statistics cannot be used for generations above 11, as it would cause a out of range in MySQL
668
+	 * 
669
+	 * Format: 
670
+	 *  - key : a base-2 representation of the ancestor at generation G for which exclusive ancestors have been found,
671
+	 *          -1 is used for shared ancestors
672
+	 *          For instance base2(0100) = base10(4) represent the maternal grand father
673
+	 *  - values: number of ancestors exclusively in the ancestors of the ancestor in key
674
+	 *  
675
+	 *  For instance a result at generation 3 could be :
676
+	 *      array (   -1        =>  12      -> 12 ancestors are shared by the grand-parents
677
+	 *                base10(1) =>  32      -> 32 ancestors are exclusive to the paternal grand-father
678
+	 *                base10(2) =>  25      -> 25 ancestors are exclusive to the paternal grand-mother
679
+	 *                base10(4) =>  12      -> 12 ancestors are exclusive to the maternal grand-father
680
+	 *                base10(8) =>  30      -> 30 ancestors are exclusive to the maternal grand-mother
681
+	 *            )
682
+	 *  
683
+	 * @param int $gen Reference generation
684
+	 * @return array
685
+	 */
686
+	public function getAncestorDispersionForGen($gen) {
687
+		if(!$this->is_setup || $gen > 11) return array();  // Going further than 11 gen will be out of range in the query
688
+		return Database::prepare(
689
+			'SELECT branches, count(i_id)'.
690
+			' FROM ('.
691
+			'   SELECT i_id,'.
692
+			'       CASE'.
693
+			'           WHEN CEIL(LOG2(SUM(branch))) = LOG2(SUM(branch)) THEN SUM(branch)'.
694
+			'           ELSE -1'.   // We put all ancestors shared between some branches in the same bucket
695
+			'       END branches'.
696
+			'   FROM ('.
697
+			'       SELECT DISTINCT majs_i_id i_id,'.
698
+			'           POW(2, FLOOR(majs_sosa / POW(2, (majs_gen - :gen))) - POW(2, :gen -1)) branch'.
699
+			'       FROM `##maj_sosa`'.
700
+			'       WHERE majs_gedcom_id = :tree_id AND majs_user_id = :user_id'.
701
+			'           AND majs_gen >= :gen'.
702
+			'   ) indistat'.
703
+			'   GROUP BY i_id'.
704
+			') grouped'.
705
+			' GROUP BY branches')
706
+			->execute(array(
707
+				'tree_id' => $this->tree->getTreeId(), 
708
+				'user_id' => $this->user->getUserId(),
709
+				'gen' => $gen
710
+			))->fetchAssoc() ?: array();
711
+	}
712
+    
713
+	/**
714
+	 * Return an array of the most duplicated root Sosa ancestors.
715
+	 * The number of ancestors to return is limited by the parameter $limit.
716
+	 * If several individuals are tied when reaching the limit, none of them are returned,
717
+	 * which means that there can be less individuals returned than requested.
718
+	 * 
719
+	 * Format: 
720
+	 *  - key : root Sosa individual
721
+	 *  - value: number of duplications of the ancestor (e.g. 3 if it appears 3 times)
722
+	 * 
723
+	 * @param number $limit Maximum number of individuals to return
724
+	 * @return array 
725
+	 */
726
+	public function getTopMultiSosaAncestorsNoTies($limit) {
727
+		if(!$this->is_setup) return array();
728
+		return Database::prepare(
729
+			'SELECT sosa_i_id, sosa_count FROM ('.
730
+			'   SELECT'.
731
+			'       top_sosa.sosa_i_id, top_sosa.sosa_count, top_sosa.sosa_min,'.
732
+			'       @keep := IF(@prev_count = 0 OR sosa_count = @prev_count, @keep, 1) AS keep,'.
733
+			'       @prev_count := top_sosa.sosa_count AS prev_count'.
734
+			'   FROM ('.
735
+			'       SELECT'.
736
+			'           sosa.majs_i_id sosa_i_id,'.
737
+			'           COUNT(sosa.majs_sosa) sosa_count,'.
738
+			'           MIN(sosa.majs_sosa) sosa_min'.
739
+			'       FROM ##maj_sosa AS sosa'.
740
+			'       LEFT JOIN ##maj_sosa AS sosa_fat ON sosa_fat.majs_sosa = 2 * sosa.majs_sosa'.   // Link to sosa's father
741
+			'           AND sosa.majs_gedcom_id = sosa_fat.majs_gedcom_id'.
742
+			'           AND sosa.majs_user_id = sosa_fat.majs_user_id'.
743
+			'       LEFT JOIN ##maj_sosa AS sosa_mot on sosa_mot.majs_sosa = (2 * sosa.majs_sosa + 1)'.  // Link to sosa's mother
744
+			'           AND sosa.majs_gedcom_id = sosa_fat.majs_gedcom_id'.
745
+			'           AND sosa.majs_user_id = sosa_fat.majs_user_id'.
746
+			'       WHERE sosa.majs_gedcom_id = :tree_id'.
747
+			'       AND sosa.majs_user_id = :user_id'.
748
+			'       AND sosa_fat.majs_sosa IS NULL'.    // We keep only root individuals, i.e. those with no father or mother
749
+			'       AND sosa_mot.majs_sosa IS NULL'. 
750
+			'       GROUP BY sosa.majs_i_id'.
751
+			'       HAVING COUNT(sosa.majs_sosa) > 1'.   // Limit to the duplicate sosas.
752
+			'       ORDER BY COUNT(sosa.majs_sosa) DESC'.
753
+			'       LIMIT ' . ($limit + 1) . // We want to select one more than required
754
+			'   ) AS top_sosa,'.
755
+			'   (SELECT @prev_count := 0, @keep := 0) x'.
756
+			'   ORDER BY top_sosa.sosa_count ASC'.
757
+			' ) top_sosa_list'.
758
+			' WHERE keep = 1'.
759
+			' ORDER BY sosa_count DESC, sosa_min ASC'
760
+			)->execute(array(
761
+				'tree_id' => $this->tree->getTreeId(),
762
+				'user_id' => $this->user->getUserId()
763
+			))->fetchAssoc() ?: array();
764
+	}
765 765
     
766 766
                
767 767
 }
Please login to merge, or discard this patch.
src/Webtrees/Module/GeoDispersion/Model/GeoAnalysisProvider.php 1 patch
Indentation   +329 added lines, -329 removed lines patch added patch discarded remove patch
@@ -21,130 +21,130 @@  discard block
 block discarded – undo
21 21
  */
22 22
 class GeoAnalysisProvider {
23 23
     
24
-    /**
25
-     * Reference tree
26
-     * @var Tree $tree
27
-     */
28
-    protected $tree;
24
+	/**
25
+	 * Reference tree
26
+	 * @var Tree $tree
27
+	 */
28
+	protected $tree;
29 29
     
30
-    /**
31
-     * Cached hierarchy of places in the Gedcom file.
32
-     * 
33
-     * @var (array|null) $place_hierarchy
34
-     */
35
-    protected $place_hierarchy;
30
+	/**
31
+	 * Cached hierarchy of places in the Gedcom file.
32
+	 * 
33
+	 * @var (array|null) $place_hierarchy
34
+	 */
35
+	protected $place_hierarchy;
36 36
     
37
-    /**
38
-     * Constructor for GeoAnalysis Provider.
39
-     * A provider is defined in relation to a specific tree.
40
-     *
41
-     * @param Tree $tree
42
-     */
43
-    public function __construct(Tree $tree) {
44
-        $this->tree = $tree;
45
-        $this->place_hierarchy = null;
46
-    }
37
+	/**
38
+	 * Constructor for GeoAnalysis Provider.
39
+	 * A provider is defined in relation to a specific tree.
40
+	 *
41
+	 * @param Tree $tree
42
+	 */
43
+	public function __construct(Tree $tree) {
44
+		$this->tree = $tree;
45
+		$this->place_hierarchy = null;
46
+	}
47 47
     
48
-    /**
49
-     * Creates and returns a GeoAnalysis object from a data row.
50
-     * The row data is expected to be an array with the indexes:
51
-     *  - majgd_id: geodispersion analysis ID
52
-     *  - majgd_descr: geodispersion analysis description/title
53
-     *  - majgd_sublevel: Analysis level
54
-     *  - majgd_useflagsgen: Use flags in places display
55
-     *  - majgd_detailsgen: Number of top places
56
-     *  - majgd_map: file name of the map
57
-     *  - majgd_toplevel: parent level for the map
58
-     * 
59
-     * @param array $row
60
-     * @return GeoAnalysis
61
-     */
62
-    protected function loadGeoAnalysisFromRow($row) {
63
-        $options = new GeoDisplayOptions();
64
-        $options
65
-        ->setUsingFlags($row['majgd_useflagsgen'] == 'yes')
66
-        ->setMaxDetailsInGen($row['majgd_detailsgen']);
48
+	/**
49
+	 * Creates and returns a GeoAnalysis object from a data row.
50
+	 * The row data is expected to be an array with the indexes:
51
+	 *  - majgd_id: geodispersion analysis ID
52
+	 *  - majgd_descr: geodispersion analysis description/title
53
+	 *  - majgd_sublevel: Analysis level
54
+	 *  - majgd_useflagsgen: Use flags in places display
55
+	 *  - majgd_detailsgen: Number of top places
56
+	 *  - majgd_map: file name of the map
57
+	 *  - majgd_toplevel: parent level for the map
58
+	 * 
59
+	 * @param array $row
60
+	 * @return GeoAnalysis
61
+	 */
62
+	protected function loadGeoAnalysisFromRow($row) {
63
+		$options = new GeoDisplayOptions();
64
+		$options
65
+		->setUsingFlags($row['majgd_useflagsgen'] == 'yes')
66
+		->setMaxDetailsInGen($row['majgd_detailsgen']);
67 67
         
68
-        if($row['majgd_map']) {
69
-            $options
70
-            ->setMap(new OutlineMap($row['majgd_map']))
71
-            ->setMapLevel($row['majgd_toplevel']);
72
-        }
68
+		if($row['majgd_map']) {
69
+			$options
70
+			->setMap(new OutlineMap($row['majgd_map']))
71
+			->setMapLevel($row['majgd_toplevel']);
72
+		}
73 73
         
74
-        $enabled = true;
75
-        if(isset($row['majgd_status']) && $row['majgd_status'] == 'disabled') {
76
-            $enabled = false;
77
-        }
74
+		$enabled = true;
75
+		if(isset($row['majgd_status']) && $row['majgd_status'] == 'disabled') {
76
+			$enabled = false;
77
+		}
78 78
         
79
-        return new GeoAnalysis(
80
-            $this->tree,
81
-            $row['majgd_id'],
82
-            $row['majgd_descr'],
83
-            $row['majgd_sublevel'],
84
-            $options,
85
-            $enabled
86
-            );
87
-    }
79
+		return new GeoAnalysis(
80
+			$this->tree,
81
+			$row['majgd_id'],
82
+			$row['majgd_descr'],
83
+			$row['majgd_sublevel'],
84
+			$options,
85
+			$enabled
86
+			);
87
+	}
88 88
     
89
-    /**
90
-     * Returns the number of geographical analysis (active and inactive). 
91
-     * 
92
-     * @return int
93
-     */
94
-    public function getGeoAnalysisCount() {
95
-        return Database::prepare(
96
-            'SELECT COUNT(majgd_id)' .
97
-            ' FROM `##maj_geodispersion`' .
98
-            ' WHERE majgd_file = :gedcom_id'
99
-            )->execute(array(
100
-                'gedcom_id' => $this->tree->getTreeId()
101
-            ))->fetchOne();
102
-    }
89
+	/**
90
+	 * Returns the number of geographical analysis (active and inactive). 
91
+	 * 
92
+	 * @return int
93
+	 */
94
+	public function getGeoAnalysisCount() {
95
+		return Database::prepare(
96
+			'SELECT COUNT(majgd_id)' .
97
+			' FROM `##maj_geodispersion`' .
98
+			' WHERE majgd_file = :gedcom_id'
99
+			)->execute(array(
100
+				'gedcom_id' => $this->tree->getTreeId()
101
+			))->fetchOne();
102
+	}
103 103
     
104
-    /**
105
-     * Get a geographical analysis by its ID.
106
-     * The function can only search for only enabled analysis, or all.
107
-     * 
108
-     * @param int $id geodispersion analysis ID
109
-     * @param bool $only_enabled Search for only enabled geodispersion analysis
110
-     * @return \MyArtJaub\Webtrees\Module\GeoDispersion\Model\GeoAnalysis|NULL
111
-     */
112
-    public function getGeoAnalysis($id, $only_enabled = true) {
113
-        $args = array (
114
-            'gedcom_id' => $this->tree->getTreeId(),
115
-            'ga_id' => $id
116
-        );
104
+	/**
105
+	 * Get a geographical analysis by its ID.
106
+	 * The function can only search for only enabled analysis, or all.
107
+	 * 
108
+	 * @param int $id geodispersion analysis ID
109
+	 * @param bool $only_enabled Search for only enabled geodispersion analysis
110
+	 * @return \MyArtJaub\Webtrees\Module\GeoDispersion\Model\GeoAnalysis|NULL
111
+	 */
112
+	public function getGeoAnalysis($id, $only_enabled = true) {
113
+		$args = array (
114
+			'gedcom_id' => $this->tree->getTreeId(),
115
+			'ga_id' => $id
116
+		);
117 117
         
118
-        $sql = 'SELECT majgd_id, majgd_descr, majgd_sublevel, majgd_map, majgd_toplevel, majgd_useflagsgen, majgd_detailsgen, majgd_status' .
119
-            ' FROM `##maj_geodispersion`' .
120
-            ' WHERE majgd_file = :gedcom_id AND majgd_id=:ga_id';
121
-        if($only_enabled) {
122
-            $sql .= ' AND majgd_status = :status';
123
-            $args['status'] = 'enabled';
124
-        }
125
-        $sql .= ' ORDER BY majgd_descr';
118
+		$sql = 'SELECT majgd_id, majgd_descr, majgd_sublevel, majgd_map, majgd_toplevel, majgd_useflagsgen, majgd_detailsgen, majgd_status' .
119
+			' FROM `##maj_geodispersion`' .
120
+			' WHERE majgd_file = :gedcom_id AND majgd_id=:ga_id';
121
+		if($only_enabled) {
122
+			$sql .= ' AND majgd_status = :status';
123
+			$args['status'] = 'enabled';
124
+		}
125
+		$sql .= ' ORDER BY majgd_descr';
126 126
         
127
-        $ga_array = Database::prepare($sql)->execute($args)->fetchOneRow(\PDO::FETCH_ASSOC);
127
+		$ga_array = Database::prepare($sql)->execute($args)->fetchOneRow(\PDO::FETCH_ASSOC);
128 128
         
129
-        if($ga_array) {
130
-            return $this->loadGeoAnalysisFromRow($ga_array);
131
-        }
129
+		if($ga_array) {
130
+			return $this->loadGeoAnalysisFromRow($ga_array);
131
+		}
132 132
         
133
-        return null;            
134
-    }
133
+		return null;            
134
+	}
135 135
     
136
-    /**
137
-     * Add a new geodispersion analysis in the database, in a transactional manner.
138
-     * When successful, eturns the newly created GeoAnalysis object.
139
-     * 
140
-     * @param string $description geodispersion analysis title
141
-     * @param int $analysis_level Analysis level
142
-     * @param string $map_file Filename of the map
143
-     * @param int $map_top_level Parent level of the map
144
-     * @param bool $use_flags Use flag in the place display
145
-     * @param int $gen_details Number of top places to display
146
-     * @return GeoAnalysis
147
-     */
136
+	/**
137
+	 * Add a new geodispersion analysis in the database, in a transactional manner.
138
+	 * When successful, eturns the newly created GeoAnalysis object.
139
+	 * 
140
+	 * @param string $description geodispersion analysis title
141
+	 * @param int $analysis_level Analysis level
142
+	 * @param string $map_file Filename of the map
143
+	 * @param int $map_top_level Parent level of the map
144
+	 * @param bool $use_flags Use flag in the place display
145
+	 * @param int $gen_details Number of top places to display
146
+	 * @return GeoAnalysis
147
+	 */
148 148
 	public function createGeoAnalysis($description, $analysis_level, $map_file, $map_top_level, $use_flags, $gen_details) {
149 149
 		try{
150 150
 			Database::beginTransaction();
@@ -174,17 +174,17 @@  discard block
 block discarded – undo
174 174
 			Log::addErrorLog('A new Geo Analysis failed to be created. Transaction rollbacked. Parameters ['.$description.', '.$analysis_level.','.$map_file.','.$map_top_level.','.$use_flags.', '.$gen_details.']. Exception: '.$ex->getMessage());
175 175
 		}
176 176
 		return $ga;
177
-    }
177
+	}
178 178
 	
179
-    /**
180
-     * Update a geodispersion analysis in the database, in transactional manner.
181
-     * When successful, returns the updated GeoAnalysis object
182
-     *  
183
-     * @param GeoAnalysis $ga
184
-     * @return GeoAnalysis
185
-     */
186
-    public function updateGeoAnalysis(GeoAnalysis $ga) {
187
-        try {
179
+	/**
180
+	 * Update a geodispersion analysis in the database, in transactional manner.
181
+	 * When successful, returns the updated GeoAnalysis object
182
+	 *  
183
+	 * @param GeoAnalysis $ga
184
+	 * @return GeoAnalysis
185
+	 */
186
+	public function updateGeoAnalysis(GeoAnalysis $ga) {
187
+		try {
188 188
 			Database::beginTransaction();
189 189
 		
190 190
 			Database::prepare(
@@ -217,239 +217,239 @@  discard block
 block discarded – undo
217 217
 			$ga = null;
218 218
 		}
219 219
 		return $ga;
220
-    }
220
+	}
221 221
     
222
-    /**
223
-     * Set the status of a specific analysis.
224
-     * The status can be enabled (true), or disabled (false).
225
-     * 
226
-     * @param GeoAnalysis $ga
227
-     * @param bool $status
228
-     */
229
-    public function setGeoAnalysisStatus(GeoAnalysis $ga, $status) {
230
-        Database::prepare(
231
-            'UPDATE `##maj_geodispersion`'.
232
-            ' SET majgd_status = :status'.
233
-            ' WHERE majgd_file = :gedcom_id AND majgd_id=:ga_id'
234
-        )->execute(array(
235
-                'gedcom_id' => $this->tree->getTreeId(),
236
-                'status' => $status ? 'enabled' : 'disabled',
237
-                'ga_id' => $ga->getId()
238
-        ));
239
-    }
222
+	/**
223
+	 * Set the status of a specific analysis.
224
+	 * The status can be enabled (true), or disabled (false).
225
+	 * 
226
+	 * @param GeoAnalysis $ga
227
+	 * @param bool $status
228
+	 */
229
+	public function setGeoAnalysisStatus(GeoAnalysis $ga, $status) {
230
+		Database::prepare(
231
+			'UPDATE `##maj_geodispersion`'.
232
+			' SET majgd_status = :status'.
233
+			' WHERE majgd_file = :gedcom_id AND majgd_id=:ga_id'
234
+		)->execute(array(
235
+				'gedcom_id' => $this->tree->getTreeId(),
236
+				'status' => $status ? 'enabled' : 'disabled',
237
+				'ga_id' => $ga->getId()
238
+		));
239
+	}
240 240
     
241
-    /**
242
-     * Delete a geodispersion analysis from the database.
243
-     * 
244
-     * @param GeoAnalysis $ga
245
-     */
246
-    public function deleteGeoAnalysis(GeoAnalysis $ga) {
247
-        Database::prepare(
248
-            'DELETE FROM `##maj_geodispersion`'.
249
-            ' WHERE majgd_file = :gedcom_id AND majgd_id=:ga_id'
250
-            )->execute(array(
251
-                'gedcom_id' => $this->tree->getTreeId(),
252
-                'ga_id' => $ga->getId()
253
-            ));
254
-    }
241
+	/**
242
+	 * Delete a geodispersion analysis from the database.
243
+	 * 
244
+	 * @param GeoAnalysis $ga
245
+	 */
246
+	public function deleteGeoAnalysis(GeoAnalysis $ga) {
247
+		Database::prepare(
248
+			'DELETE FROM `##maj_geodispersion`'.
249
+			' WHERE majgd_file = :gedcom_id AND majgd_id=:ga_id'
250
+			)->execute(array(
251
+				'gedcom_id' => $this->tree->getTreeId(),
252
+				'ga_id' => $ga->getId()
253
+			));
254
+	}
255 255
         
256
-    /**
257
-     * Return the list of geodispersion analysis recorded and enabled for a specific GEDCOM
258
-     *
259
-     * @return array List of enabled maps
260
-     */
261
-    public function getGeoAnalysisList(){
262
-        $res = array();
256
+	/**
257
+	 * Return the list of geodispersion analysis recorded and enabled for a specific GEDCOM
258
+	 *
259
+	 * @return array List of enabled maps
260
+	 */
261
+	public function getGeoAnalysisList(){
262
+		$res = array();
263 263
         
264
-        $list = Database::prepare(
265
-            'SELECT majgd_id, majgd_descr, majgd_sublevel, majgd_map, majgd_toplevel, majgd_useflagsgen, majgd_detailsgen' .
266
-            ' FROM `##maj_geodispersion`' .
267
-            ' WHERE majgd_file = :gedcom_id AND majgd_status = :status'.
268
-            ' ORDER BY majgd_descr'
269
-        )->execute(array(
270
-            'gedcom_id' => $this->tree->getTreeId(),
271
-            'status' => 'enabled'
272
-        ))->fetchAll(\PDO::FETCH_ASSOC);
264
+		$list = Database::prepare(
265
+			'SELECT majgd_id, majgd_descr, majgd_sublevel, majgd_map, majgd_toplevel, majgd_useflagsgen, majgd_detailsgen' .
266
+			' FROM `##maj_geodispersion`' .
267
+			' WHERE majgd_file = :gedcom_id AND majgd_status = :status'.
268
+			' ORDER BY majgd_descr'
269
+		)->execute(array(
270
+			'gedcom_id' => $this->tree->getTreeId(),
271
+			'status' => 'enabled'
272
+		))->fetchAll(\PDO::FETCH_ASSOC);
273 273
         
274
-        foreach($list as $ga) {
275
-           $res[] = $this->loadGeoAnalysisFromRow($ga);
276
-        }
274
+		foreach($list as $ga) {
275
+		   $res[] = $this->loadGeoAnalysisFromRow($ga);
276
+		}
277 277
         
278
-        return $res;
279
-    }
278
+		return $res;
279
+	}
280 280
     
281
-    /**
282
-     * Return the list of geodispersion analysis matching specified criterias.
283
-     * 
284
-     * @param string $search Search criteria in analysis description
285
-     * @param array $order_by Columns to order by
286
-     * @param int $start Offset to start with (for pagination)
287
-     * @param int|null $limit Max number of items to return (for pagination)
288
-     * @return \MyArtJaub\Webtrees\Module\GeoDispersion\Model\GeoAnalysis[]
289
-     */
290
-    public function getFilteredGeoAnalysisList($search = null, $order_by = null, $start = 0, $limit = null){
291
-        $res = array();
281
+	/**
282
+	 * Return the list of geodispersion analysis matching specified criterias.
283
+	 * 
284
+	 * @param string $search Search criteria in analysis description
285
+	 * @param array $order_by Columns to order by
286
+	 * @param int $start Offset to start with (for pagination)
287
+	 * @param int|null $limit Max number of items to return (for pagination)
288
+	 * @return \MyArtJaub\Webtrees\Module\GeoDispersion\Model\GeoAnalysis[]
289
+	 */
290
+	public function getFilteredGeoAnalysisList($search = null, $order_by = null, $start = 0, $limit = null){
291
+		$res = array();
292 292
             
293
-        $sql = 
294
-            'SELECT majgd_id, majgd_descr, majgd_sublevel, majgd_map, majgd_toplevel, majgd_useflagsgen, majgd_detailsgen, majgd_status' .
295
-            ' FROM `##maj_geodispersion`' .
296
-            ' WHERE majgd_file = :gedcom_id';
293
+		$sql = 
294
+			'SELECT majgd_id, majgd_descr, majgd_sublevel, majgd_map, majgd_toplevel, majgd_useflagsgen, majgd_detailsgen, majgd_status' .
295
+			' FROM `##maj_geodispersion`' .
296
+			' WHERE majgd_file = :gedcom_id';
297 297
         
298
-        $args = array('gedcom_id'=> $this->tree->getTreeId());
298
+		$args = array('gedcom_id'=> $this->tree->getTreeId());
299 299
         
300
-        if($search) {
301
-            $sql .= ' AND majgd_descr LIKE CONCAT(\'%\', :search, \'%\')';
302
-            $args['search'] = $search;
303
-        }
300
+		if($search) {
301
+			$sql .= ' AND majgd_descr LIKE CONCAT(\'%\', :search, \'%\')';
302
+			$args['search'] = $search;
303
+		}
304 304
         
305
-        if ($order_by) {
306
-            $sql .= ' ORDER BY ';
307
-            foreach ($order_by as $key => $value) {
308
-                if ($key > 0) {
309
-                    $sql .= ',';
310
-                }
305
+		if ($order_by) {
306
+			$sql .= ' ORDER BY ';
307
+			foreach ($order_by as $key => $value) {
308
+				if ($key > 0) {
309
+					$sql .= ',';
310
+				}
311 311
                 
312
-                switch ($value['dir']) {
313
-                    case 'asc':
314
-                        $sql .= $value['column'] . ' ASC ';
315
-                        break;
316
-                    case 'desc':
317
-                        $sql .= $value['column'] . ' DESC ';
318
-                        break;
319
-                }
320
-            }
321
-        } else {
322
-            $sql .= ' ORDER BY majgd_descr ASC';
323
-        }
312
+				switch ($value['dir']) {
313
+					case 'asc':
314
+						$sql .= $value['column'] . ' ASC ';
315
+						break;
316
+					case 'desc':
317
+						$sql .= $value['column'] . ' DESC ';
318
+						break;
319
+				}
320
+			}
321
+		} else {
322
+			$sql .= ' ORDER BY majgd_descr ASC';
323
+		}
324 324
         
325
-        if ($limit) {
326
-            $sql .= " LIMIT :limit OFFSET :offset";
327
-            $args['limit']  = $limit;
328
-            $args['offset'] = $start;
329
-        }
325
+		if ($limit) {
326
+			$sql .= " LIMIT :limit OFFSET :offset";
327
+			$args['limit']  = $limit;
328
+			$args['offset'] = $start;
329
+		}
330 330
             
331
-        $data = Database::prepare($sql)->execute($args)->fetchAll(\PDO::FETCH_ASSOC);
331
+		$data = Database::prepare($sql)->execute($args)->fetchAll(\PDO::FETCH_ASSOC);
332 332
 
333
-        foreach($data as $ga) {
334
-            $res[] = $this->loadGeoAnalysisFromRow($ga);
335
-        }
333
+		foreach($data as $ga) {
334
+			$res[] = $this->loadGeoAnalysisFromRow($ga);
335
+		}
336 336
         
337
-        return $res;
338
-    }
337
+		return $res;
338
+	}
339 339
             
340
-    /**
341
-     * Returns the infered place hierarchy, determined from the Gedcom data.
342
-     * Depending on the data, it can be based on the Gedcom Header description, or from a place example.
343
-     * This is returned as an associative array:
344
-     *      - type:    describe the source of the data (<em>header<em> / <em>data</em> / <em>none</em>)
345
-     *      - hierarchy: an array of the place hierarchy (in reverse order of the gedcom)
346
-     *      
347
-     * @return array
348
-     */
349
-    public function getPlacesHierarchy() {
350
-        if(!$this->place_hierarchy) {
351
-            if($place_structure = $this->getPlacesHierarchyFromHeader()) {
352
-                $this->place_hierarchy = array('type' => 'header', 'hierarchy' => $place_structure);
353
-            }
354
-            elseif ($place_structure = $this->getPlacesHierarchyFromData()){
355
-                $this->place_hierarchy = array('type' => 'data', 'hierarchy' => $place_structure);
356
-            }
357
-            else {
358
-                $this->place_hierarchy = array('type' => 'none', 'hierarchy' => null);
359
-            }
360
-        }
361
-        return $this->place_hierarchy;        
362
-    }
340
+	/**
341
+	 * Returns the infered place hierarchy, determined from the Gedcom data.
342
+	 * Depending on the data, it can be based on the Gedcom Header description, or from a place example.
343
+	 * This is returned as an associative array:
344
+	 *      - type:    describe the source of the data (<em>header<em> / <em>data</em> / <em>none</em>)
345
+	 *      - hierarchy: an array of the place hierarchy (in reverse order of the gedcom)
346
+	 *      
347
+	 * @return array
348
+	 */
349
+	public function getPlacesHierarchy() {
350
+		if(!$this->place_hierarchy) {
351
+			if($place_structure = $this->getPlacesHierarchyFromHeader()) {
352
+				$this->place_hierarchy = array('type' => 'header', 'hierarchy' => $place_structure);
353
+			}
354
+			elseif ($place_structure = $this->getPlacesHierarchyFromData()){
355
+				$this->place_hierarchy = array('type' => 'data', 'hierarchy' => $place_structure);
356
+			}
357
+			else {
358
+				$this->place_hierarchy = array('type' => 'none', 'hierarchy' => null);
359
+			}
360
+		}
361
+		return $this->place_hierarchy;        
362
+	}
363 363
     
364
-    /**
365
-     * Returns an array of the place hierarchy, as defined in the GEDCOM header.
366
-     * The places are reversed compared to normal GEDCOM structure.
367
-     * 
368
-     * @return array|null
369
-     */
370
-    protected function getPlacesHierarchyFromHeader() {
371
-        $head = GedcomRecord::getInstance('HEAD', $this->tree);
372
-        $head_place = $head->getFirstFact('PLAC');
373
-        if($head_place && $head_place_value = $head_place->getAttribute('FORM')){
374
-            return array_reverse(array_map('trim',explode(',', $head_place_value)));
375
-        }
376
-        return null;
377
-    }
364
+	/**
365
+	 * Returns an array of the place hierarchy, as defined in the GEDCOM header.
366
+	 * The places are reversed compared to normal GEDCOM structure.
367
+	 * 
368
+	 * @return array|null
369
+	 */
370
+	protected function getPlacesHierarchyFromHeader() {
371
+		$head = GedcomRecord::getInstance('HEAD', $this->tree);
372
+		$head_place = $head->getFirstFact('PLAC');
373
+		if($head_place && $head_place_value = $head_place->getAttribute('FORM')){
374
+			return array_reverse(array_map('trim',explode(',', $head_place_value)));
375
+		}
376
+		return null;
377
+	}
378 378
     
379
-    /**
380
-     * Returns an array of the place hierarchy, based on a random example of place within the GEDCOM.
381
-     * It will look for the longest hierarchy in the tree.
382
-     * The places are reversed compared to normal GEDCOM structure.
383
-     * 
384
-     * @return array
385
-     */
386
-    protected function getPlacesHierarchyFromData() {
387
-        $nb_levels = 0;
379
+	/**
380
+	 * Returns an array of the place hierarchy, based on a random example of place within the GEDCOM.
381
+	 * It will look for the longest hierarchy in the tree.
382
+	 * The places are reversed compared to normal GEDCOM structure.
383
+	 * 
384
+	 * @return array
385
+	 */
386
+	protected function getPlacesHierarchyFromData() {
387
+		$nb_levels = 0;
388 388
         
389
-        //Select all '2 PLAC ' tags in the file and create array
390
-        $places_list=array();
391
-        $ged_data = Database::prepare(
392
-            'SELECT i_gedcom AS gedcom'.
393
-            ' FROM `##individuals`'.
394
-            ' WHERE i_gedcom LIKE :gedcom AND i_file = :gedcom_id'.
395
-            ' UNION ALL'.
396
-            ' SELECT f_gedcom AS gedcom'.
397
-            ' FROM `##families`'.
398
-            ' WHERE f_gedcom LIKE :gedcom AND f_file = :gedcom_id'
399
-        )->execute(array(
400
-            'gedcom' => '%2 PLAC %',
401
-            'gedcom_id' => $this->tree->getTreeId()
402
-        ))->fetchOneColumn();
403
-        foreach ($ged_data as $ged_datum) {
404
-            $matches = null;
405
-            preg_match_all('/\n2 PLAC (.+)/', $ged_datum, $matches);
406
-            foreach ($matches[1] as $match) {
407
-                $places_list[$match]=true;
408
-            }
409
-        }
389
+		//Select all '2 PLAC ' tags in the file and create array
390
+		$places_list=array();
391
+		$ged_data = Database::prepare(
392
+			'SELECT i_gedcom AS gedcom'.
393
+			' FROM `##individuals`'.
394
+			' WHERE i_gedcom LIKE :gedcom AND i_file = :gedcom_id'.
395
+			' UNION ALL'.
396
+			' SELECT f_gedcom AS gedcom'.
397
+			' FROM `##families`'.
398
+			' WHERE f_gedcom LIKE :gedcom AND f_file = :gedcom_id'
399
+		)->execute(array(
400
+			'gedcom' => '%2 PLAC %',
401
+			'gedcom_id' => $this->tree->getTreeId()
402
+		))->fetchOneColumn();
403
+		foreach ($ged_data as $ged_datum) {
404
+			$matches = null;
405
+			preg_match_all('/\n2 PLAC (.+)/', $ged_datum, $matches);
406
+			foreach ($matches[1] as $match) {
407
+				$places_list[$match]=true;
408
+			}
409
+		}
410 410
         
411
-        // Get the places with higest numbers of levels
412
-        $places_with_high_level = array();
413
-        $max_level = 0;
411
+		// Get the places with higest numbers of levels
412
+		$places_with_high_level = array();
413
+		$max_level = 0;
414 414
         
415
-        foreach ($places_list as $place => $value) {
416
-            $levels = array_filter(array_map('trim', explode(",", $place)));
417
-            $parts = count($levels);
418
-            if($parts > $max_level) {
419
-                $max_level = $parts;
420
-                $places_with_high_level = array($place);
421
-            }
422
-            else if ($parts == $max_level) {
423
-                $places_with_high_level[] = $place;
424
-            }
425
-        }
415
+		foreach ($places_list as $place => $value) {
416
+			$levels = array_filter(array_map('trim', explode(",", $place)));
417
+			$parts = count($levels);
418
+			if($parts > $max_level) {
419
+				$max_level = $parts;
420
+				$places_with_high_level = array($place);
421
+			}
422
+			else if ($parts == $max_level) {
423
+				$places_with_high_level[] = $place;
424
+			}
425
+		}
426 426
         
427
-        // If empty array, then return null
428
-        if($max_level == 0) return null;
427
+		// If empty array, then return null
428
+		if($max_level == 0) return null;
429 429
                 
430
-        // Else, return the first alphabetical element -- cannot return random to ensure always the same example if used
431
-        usort($places_with_high_level, array('Fisharebest\\Webtrees\\I18N', 'strcasecmp'));        
432
-        return array_reverse(array_map('trim',explode(',', $places_with_high_level[0])));
430
+		// Else, return the first alphabetical element -- cannot return random to ensure always the same example if used
431
+		usort($places_with_high_level, array('Fisharebest\\Webtrees\\I18N', 'strcasecmp'));        
432
+		return array_reverse(array_map('trim',explode(',', $places_with_high_level[0])));
433 433
         
434
-    }
434
+	}
435 435
     
436
-    /**
437
-     * Returns the list of geodispersion maps available within the maps folder.
438
-     * 
439
-     * @return \MyArtJaub\Webtrees\Module\GeoDispersion\Model\OutlineMap[]
440
-     */
441
-    public function getOutlineMapsList() {
442
-        $res = array();
443
-        $root_path = WT_ROOT.WT_MODULES_DIR.Constants::MODULE_MAJ_GEODISP_NAME.'/maps/';
444
-        if(is_dir($root_path)){
445
-            $dir = opendir($root_path);
446
-            while (($file=readdir($dir))!== false) {
447
-                if (preg_match('/^[a-zA-Z0-9_]+.xml$/', $file)) {
448
-                    $res[base64_encode($file)] = new OutlineMap($file, true);
449
-                }
450
-            }
451
-        }
452
-        return $res;
453
-    }
436
+	/**
437
+	 * Returns the list of geodispersion maps available within the maps folder.
438
+	 * 
439
+	 * @return \MyArtJaub\Webtrees\Module\GeoDispersion\Model\OutlineMap[]
440
+	 */
441
+	public function getOutlineMapsList() {
442
+		$res = array();
443
+		$root_path = WT_ROOT.WT_MODULES_DIR.Constants::MODULE_MAJ_GEODISP_NAME.'/maps/';
444
+		if(is_dir($root_path)){
445
+			$dir = opendir($root_path);
446
+			while (($file=readdir($dir))!== false) {
447
+				if (preg_match('/^[a-zA-Z0-9_]+.xml$/', $file)) {
448
+					$res[base64_encode($file)] = new OutlineMap($file, true);
449
+				}
450
+			}
451
+		}
452
+		return $res;
453
+	}
454 454
 }
455 455
  
456 456
\ No newline at end of file
Please login to merge, or discard this patch.
src/Webtrees/Module/GeoDispersion/Views/GeoAnalysisEditView.php 1 patch
Indentation   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -25,14 +25,14 @@  discard block
 block discarded – undo
25 25
 	 * {@inhericDoc}
26 26
 	 * @see \MyArtJaub\Webtrees\Mvc\View\AbstractView::renderContent()
27 27
 	 */
28
-    protected function renderContent() {
28
+	protected function renderContent() {
29 29
         
30
-        /** @var GeoAnalysis $ga */
31
-        $ga = $this->data->get('geo_analysis');
32
-        $is_new = is_null($ga);
30
+		/** @var GeoAnalysis $ga */
31
+		$ga = $this->data->get('geo_analysis');
32
+		$is_new = is_null($ga);
33 33
         
34
-        $places_hierarchy = $this->data->get('places_hierarchy');
35
-        ?>        
34
+		$places_hierarchy = $this->data->get('places_hierarchy');
35
+		?>        
36 36
         <ol class="breadcrumb small">
37 37
         	<li><a href="admin.php"><?php echo I18N::translate('Control panel'); ?></a></li>
38 38
 			<li><a href="admin_modules.php"><?php echo I18N::translate('Module administration'); ?></a></li>
@@ -159,7 +159,7 @@  discard block
 block discarded – undo
159 159
     	</form>
160 160
 		
161 161
 		<?php }
162
-    }
162
+	}
163 163
     
164 164
 }
165 165
  
166 166
\ No newline at end of file
Please login to merge, or discard this patch.
src/Webtrees/Module/GeoDispersion/Views/AdminConfigView.php 1 patch
Indentation   +25 added lines, -25 removed lines patch added patch discarded remove patch
@@ -23,14 +23,14 @@  discard block
 block discarded – undo
23 23
 	 * {@inhericDoc}
24 24
 	 * @see \MyArtJaub\Webtrees\Mvc\View\AbstractView::renderContent()
25 25
 	 */
26
-    protected function renderContent() {
26
+	protected function renderContent() {
27 27
         
28
-        /** @var Tree $tree  */
29
-        $tree = $this->data->get('tree');
30
-        $root_url = $this->data->get('root_url');
31
-        $other_trees = $this->data->get('other_trees');
32
-        $table_id = $this->data->get('table_id');
33
-        ?>        
28
+		/** @var Tree $tree  */
29
+		$tree = $this->data->get('tree');
30
+		$root_url = $this->data->get('root_url');
31
+		$other_trees = $this->data->get('other_trees');
32
+		$table_id = $this->data->get('table_id');
33
+		?>        
34 34
         <ol class="breadcrumb small">
35 35
         	<li><a href="admin.php"><?php echo I18N::translate('Control panel'); ?></a></li>
36 36
 			<li><a href="admin_modules.php"><?php echo I18N::translate('Module administration'); ?></a></li>
@@ -63,23 +63,23 @@  discard block
 block discarded – undo
63 63
 		<p>
64 64
 		<?php $places_hierarchy = $this->data->get('places_hierarchy'); 
65 65
 		if($places_hierarchy && $places_hierarchy['type'] != 'none') {
66
-		    switch ($places_hierarchy['type']) {
67
-		        case 'header':
68
-		            echo I18N::translate('According to the GEDCOM header, the places within your file follows the structure: ');
69
-		            break;
70
-		        case 'data':
71
-		            echo I18N::translate('Your GEDCOM header does not contain any indication of place structure.').
72
-		            '<br/>'.
73
-		            I18N::translate('Here is an example of your place data: ');
74
-		            break;
75
-		        default:
76
-		            break;
77
-		    }
78
-		    $str_hierarchy = array();
79
-		    foreach($places_hierarchy['hierarchy'] as $key => $level) {
80
-		        $str_hierarchy[] = I18N::translate('(%d) %s', $key + 1, $level);
81
-		    }
82
-		    echo '<strong>' . implode(I18N::$list_separator, $str_hierarchy) . '</strong>';
66
+			switch ($places_hierarchy['type']) {
67
+				case 'header':
68
+					echo I18N::translate('According to the GEDCOM header, the places within your file follows the structure: ');
69
+					break;
70
+				case 'data':
71
+					echo I18N::translate('Your GEDCOM header does not contain any indication of place structure.').
72
+					'<br/>'.
73
+					I18N::translate('Here is an example of your place data: ');
74
+					break;
75
+				default:
76
+					break;
77
+			}
78
+			$str_hierarchy = array();
79
+			foreach($places_hierarchy['hierarchy'] as $key => $level) {
80
+				$str_hierarchy[] = I18N::translate('(%d) %s', $key + 1, $level);
81
+			}
82
+			echo '<strong>' . implode(I18N::$list_separator, $str_hierarchy) . '</strong>';
83 83
 		}
84 84
 		?>
85 85
 		</p>
@@ -109,7 +109,7 @@  discard block
 block discarded – undo
109 109
         </a>
110 110
 		
111 111
 		<?php        
112
-    }
112
+	}
113 113
     
114 114
 }
115 115
  
116 116
\ No newline at end of file
Please login to merge, or discard this patch.