From f324dbd9817468eda555639eb9c73ae6255728ed Mon Sep 17 00:00:00 2001
From: Matthew Juhl <mjuhl24@gmail.com>
Date: Wed, 5 Aug 2009 22:02:51 +0000
Subject: [PATCH] add modified flexprofile plugin...needs to be copied to your
 mod folder

---
 flexprofile_mj/README.txt                     |  67 +++++++
 flexprofile_mj/actions/edit.php               |  44 +++++
 flexprofile_mj/extended.php                   |  32 +++
 flexprofile_mj/manifest.xml                   |  10 +
 flexprofile_mj/models/model.php               | 129 ++++++++++++
 flexprofile_mj/start.php                      |  68 +++++++
 .../views/default/flexprofile/extended.php    |  29 +++
 .../default/flexprofile/menu/actions.php      |   3 +
 flexprofile_mj/views/default/profile/edit.php |  58 ++++++
 .../views/default/profile/userdetails.php     | 184 ++++++++++++++++++
 10 files changed, 624 insertions(+)
 create mode 100755 flexprofile_mj/README.txt
 create mode 100755 flexprofile_mj/actions/edit.php
 create mode 100755 flexprofile_mj/extended.php
 create mode 100755 flexprofile_mj/manifest.xml
 create mode 100755 flexprofile_mj/models/model.php
 create mode 100755 flexprofile_mj/start.php
 create mode 100755 flexprofile_mj/views/default/flexprofile/extended.php
 create mode 100755 flexprofile_mj/views/default/flexprofile/menu/actions.php
 create mode 100755 flexprofile_mj/views/default/profile/edit.php
 create mode 100755 flexprofile_mj/views/default/profile/userdetails.php

diff --git a/flexprofile_mj/README.txt b/flexprofile_mj/README.txt
new file mode 100755
index 00000000..9a420190
--- /dev/null
+++ b/flexprofile_mj/README.txt
@@ -0,0 +1,67 @@
+/**
+ * Use form module to manage profile questions through the web
+ * 
+ * @package flexprofile
+ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html GNU Public License version 2
+ * @author Kevin Jardine <kevin@radagast.biz>
+ * @copyright Radagast Solutions 2008
+ * @link http://radagast.biz/
+ * 
+ */
+ 
+The Elgg 1.x flexprofile plugin requires the form plugin.
+
+Do not activate the flexprofile plugin without creating a profile form first -
+if you do, your profiles will be blank and there will be nothing to edit
+as no profile questions will be defined.
+
+You can use the "Add form" link on the Manage forms page provided by 
+the form module to manage your profile questions through the web. Specify a
+"user profile" form when creating your form.
+
+Field type restrictions
+
+Currently the invitation box field type does not work for
+profile forms.
+
+It is also not possible to make profile fields required.
+
+Some of these restrictions may be removed eventually.
+
+For profile forms, there are a few extra profile field definition options.
+
+You can specify whether the profile field should be displayed in the profile
+summary area on the left, right or bottom area of the profile (or not at all). 
+By default they are displayed on the right. Even if the field cannot be viewed
+in the profile summary area, it can still be viewed in the extended profile
+if the user has the correct permissions and you have activated the extended
+profile option (see below).
+
+You can also specify whether a profile field is invisible. This is a value that
+can be edited by the user but is never displayed.
+
+You can specify the profile format. Currently there are three formats. The
+default format is similar to the standard Elgg 1.1 summary profile with the
+addition of an extended profile (accessed by a link) that shows all the visible
+fields (separated by tabs if more than one tab was specified). The default 
+format (no extended profile) does not include the link to the extended profile.
+The tabbed format shows just the tabbed extended profile and no summary
+profile.
+
+You can also specify different user profiles for different user categories.
+There is currently no way to set user categories, however, so this feature
+is for future use.
+
+Activating the flexprofile plugin
+
+Create a profile form as described above. More documentation on creating forms
+is contained in the form plugin README.txt.
+
+Then extract the flexprofile plugin into the mod directory and activate it as
+usual using the Elgg 1.x tool administration.
+
+Once activated, the edit details link should show the fields that you have
+defined for your profile form.
+
+You can have multiple profile forms defined, but the flexprofile plugin will
+always use the one most recently created.
diff --git a/flexprofile_mj/actions/edit.php b/flexprofile_mj/actions/edit.php
new file mode 100755
index 00000000..6fe49c9c
--- /dev/null
+++ b/flexprofile_mj/actions/edit.php
@@ -0,0 +1,44 @@
+<?php
+/**
+	 * Elgg flex profile edit action
+	 * Allows user to edit profile
+	 * 
+	 * @package Elgg
+	 * @subpackage Form
+	 * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html GNU Public License version 2
+	 * @author Kevin Jardine <kevin@radagast.biz>
+	 * @copyright Radagast Solutions 2008
+	 * @link http://radagast.biz/
+	 */
+
+	 // Load flexprofile model
+require_once(dirname(dirname(__FILE__)) . "/models/model.php");
+
+if ($user = page_owner()) {
+	$user = page_owner_entity();			
+} else {
+	$user = $_SESSION['user'];
+	set_page_owner($user->getGUID());
+}
+
+if ($user && $user->canEdit()) {
+    $data = form_get_profile_data_from_form_post();
+    form_set_data($user,$data);
+    // Notify of profile update
+	trigger_elgg_event('profileupdate',$user->type,$user);
+	//add to river
+	add_to_river('river/user/default/profileupdate','update',$user->guid,$user->guid);
+	
+	system_message(elgg_echo("profile:saved"));
+
+	// Forward to the user's profile
+	forward($user->getUrl());
+
+} else {
+    // If we can't, display an error
+	
+	register_error(elgg_echo("profile:cantedit"));
+	forward();
+}
+
+?>
\ No newline at end of file
diff --git a/flexprofile_mj/extended.php b/flexprofile_mj/extended.php
new file mode 100755
index 00000000..66ca0d16
--- /dev/null
+++ b/flexprofile_mj/extended.php
@@ -0,0 +1,32 @@
+<?php
+
+/**
+ * Elgg flexprofile extended profile
+ * 
+ * @package FlexProfile
+ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html GNU Public License version 2
+ * @author Kevin Jardine <kevin@radagast.biz>
+ * @copyright Radagast Solutions 2008
+ * @link http://radagast.biz/
+ */
+ 
+// Load Elgg engine
+require_once(dirname(dirname(dirname(__FILE__))) . "/engine/start.php");
+
+global $CONFIG;
+
+// Define context
+set_context('profile');
+
+$user = page_owner_entity();
+
+add_submenu_item(elgg_echo('form:extended_profile_link_text'),$CONFIG->wwwroot.'pg/flexprofile/'.$user->username);
+add_submenu_item(elgg_echo('form:main_profile_link_text'),$user->getUrl());
+
+$body = elgg_view('flexprofile/extended',array('entity'=>$user));
+
+$title = sprintf(elgg_echo('form:extended_profile_title'),$user->name);
+
+page_draw($title,elgg_view_layout("two_column_left_sidebar", '', elgg_view_title($title) . $body));
+
+?>
\ No newline at end of file
diff --git a/flexprofile_mj/manifest.xml b/flexprofile_mj/manifest.xml
new file mode 100755
index 00000000..b673ac5c
--- /dev/null
+++ b/flexprofile_mj/manifest.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<plugin_manifest>
+        <field key="author" value="Kevin Jardine &lt;kevin@radagast.biz&gt;" />
+        <field key="version" value="0.8" />
+        <field key="description" value="Elgg flexible user profile plugin." />
+        <field key="website" value="http://radagast.biz/" />
+        <field key="copyright" value="(C) Radagast Solutions 2009" />
+		<field key="licence" value="GNU Public License version 2" />
+		<field key="elgg_version" value="2009030101" />
+</plugin_manifest>
diff --git a/flexprofile_mj/models/model.php b/flexprofile_mj/models/model.php
new file mode 100755
index 00000000..eb2aea18
--- /dev/null
+++ b/flexprofile_mj/models/model.php
@@ -0,0 +1,129 @@
+<?php
+/**
+	 * Elgg flex profile model
+	 * Functions to save and display profile data
+	 * 
+	 * @package Elgg
+	 * @subpackage Form
+	 * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html GNU Public License version 2
+	 * @author Kevin Jardine <kevin@radagast.biz>
+	 * @copyright Radagast Solutions 2008
+	 * @link http://radagast.biz/
+	 */
+
+// Load form model
+require_once(dirname(dirname(dirname(__FILE__))) . "/form/models/model.php");
+
+// Load form profile model
+require_once(dirname(dirname(dirname(__FILE__))) . "/form/models/profile.php");
+
+// Eventually this will be very flexible and return different forms for
+// different entities.
+// Right now it just returns the first public profile form available.
+
+function flexprofile_get_profile_form($user=null) {
+    return form_get_latest_public_profile_form(1);
+}    
+
+// use the specified profile form to return the data (indexed by summary area) from the specified user
+
+function flexprofile_get_data_for_summary_display($form, $user) {
+    $form_id = $form->getGUID();
+    $data = form_get_data_from_profile($form_id,$user);
+    $area_data = array();
+    $maps = form_get_maps($form_id);
+    if ($maps) {
+        foreach($maps as $map) {
+            $field = get_entity($map->field_id);
+            //print($field->internal_name.','.$field->field_type.','.$field->choice_type.','.$field->default_value.'<br />');
+            $internalname = $field->internal_name;
+            if (isset($data[$internalname]) && $data[$internalname]->value) {
+                $area = $field->area;
+                if ($area) {
+                    if (!isset($area_data[$area])) {
+                        $area_data[$area] = array();
+                    }
+                    $item = new StdClass();
+                    $item->internalname = $internalname;
+                    $item->title = form_field_t($form,$field,'title');
+                    $item->description = form_field_t($form,$field,'description');
+                    if ($field->field_type == 'choices') {
+                        $item->fieldtype = $field->choice_type;
+                        $choices = form_get_field_choices($field->getGUID());
+                        $this_choice = '';
+                        foreach($choices as $choice) {
+                            if ($choice->value == $data[$internalname]->value) {
+                                $this_choice = $choice;
+                                break;
+                            }
+                        }
+                        $item->value = form_choice_t($form,$field,$this_choice);
+                    } else {
+                        $item->fieldtype = $field->field_type;
+                        $item->value = $data[$internalname]->value;
+                    }
+                    
+                    $area_data[$area][] = $item;
+                }
+            }
+        }
+    }
+    return $area_data;
+}
+    
+
+// Return the form fields (indexed by tab), optionally prepopulated with data from the specified user.
+
+function flexprofile_get_data_for_edit_form($form, $user=null) {
+
+    if ($user) {
+        $data = form_get_data_from_profile($form->getGUID(),$user);
+    } else {
+        $data = array();
+    }
+    
+    $tab_data = array();
+    $tabs = form_display_by_tab($form,$data);
+    
+    // add access control pulldowns
+    if ($tabs) {
+        foreach ($tabs as $tab => $tab_items) {
+            $tab_data[$tab] = '';
+            foreach ($tab_items as $item) {
+                $internalname = $item->internalname;
+                $access_id = $item->default_access;
+                
+                $access_bit = '<p class="form-field-access">';
+                $access_bit .= elgg_view('input/access', array('internalname' => 'flexprofile_access['.$internalname.']','value'=>$access_id));
+                $access_bit .= '</p>';
+                $tab_data[$tab] .= $item->html.$access_bit;
+            }
+        }
+    }
+    return $tab_data;
+}
+    
+function flexprofile_set_data($entity,$data) {
+    global $CONFIG;
+    
+    $entity_guid = $entity->getGUID();
+    
+    foreach($data as $name => $item) {
+    	remove_metadata($entity_guid, $name);
+    	$value = $item->value;
+    	if (is_array($value)) {
+    		// currently tags are the only field_type returning multiple values
+			$i = 0;
+			foreach($value as $interval) {
+				$i++;
+				if ($i == 1) { $multiple = false; } else { $multiple = true; }
+				create_metadata($entity_guid, $name, $interval, 'text', $entity_guid, $item->access_id, $multiple);
+			}
+		} else {
+    		create_metadata($entity_guid, $name, $value, '', $entity_guid, $item->access_id);
+		}
+    }
+}
+
+
+?>
\ No newline at end of file
diff --git a/flexprofile_mj/start.php b/flexprofile_mj/start.php
new file mode 100755
index 00000000..b6616d00
--- /dev/null
+++ b/flexprofile_mj/start.php
@@ -0,0 +1,68 @@
+<?php
+
+/**
+ * Elgg flexprofile plugin
+ * 
+ * @package FlexProfile
+ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html GNU Public License version 2
+ * @author Kevin Jardine <kevin@radagast.biz>
+ * @copyright Radagast Solutions 2008
+ * @link http://radagast.biz/
+ */
+
+
+// Load flexprofile model
+    require_once(dirname(__FILE__)."/models/model.php");
+    
+/**
+ * Profile init function; sets up the profile functions
+ *
+ */
+	function flexprofile_init() {
+
+		// override profile views
+		set_view_location("profile/userdetails", dirname(__FILE__).'/views/');
+		set_view_location("profile/edit", dirname(__FILE__).'/views/');
+		
+		// Register a page handler, so we can have nice URLs
+		register_page_handler('flexprofile','flexprofile_page_handler');
+	}
+	
+	function flexprofile_pagesetup() {
+		global $CONFIG;
+		
+		if (get_context() == 'profile') {
+			$form = flexprofile_get_profile_form();
+			if (!$form->profile_format || ($form->profile_format == 'default')) {		
+				extend_view("profile/menu/actions","flexprofile/menu/actions");
+			}
+		}
+	}
+	
+	/* Flexprofile page handler; allows the use of fancy URLs
+	 *
+	 * @param array $page From the page_handler function
+	 * @return true|false Depending on success
+	 */
+	function flexprofile_page_handler($page) {
+		
+		// The first component of a flexprofile URL is the username
+		if (isset($page[0])) {
+			set_input('username',$page[0]);
+		}
+		
+		@include(dirname(__FILE__) . "/extended.php");
+		return true;
+		
+	}
+
+	register_elgg_event_handler('pagesetup','system','flexprofile_pagesetup');
+	
+// Make sure the profile initialisation function is called on initialisation
+	register_elgg_event_handler('init','system','flexprofile_init',2);
+	
+// Register actions
+	global $CONFIG;
+	register_action("flexprofile/edit",false,$CONFIG->pluginspath . "flexprofile/actions/edit.php");
+
+?>
\ No newline at end of file
diff --git a/flexprofile_mj/views/default/flexprofile/extended.php b/flexprofile_mj/views/default/flexprofile/extended.php
new file mode 100755
index 00000000..f40932be
--- /dev/null
+++ b/flexprofile_mj/views/default/flexprofile/extended.php
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Extended profile view
+ *
+ * @package Flexprofile
+ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html GNU Public License version 2
+ * @author Kevin Jardine <kevin@radagast.biz>
+ * @copyright Radagast Solutions 2008
+ * @link http://radagast.biz/
+ */
+
+// Load flexprofile model
+require_once(dirname(dirname(dirname(dirname(__FILE__)))) . "/models/model.php");
+
+$user = $vars['entity'];
+$form = flexprofile_get_profile_form($user);
+if (!$vars['embedded']) {
+	echo '<div class="contentWrapper">';
+}
+if ($form) {
+	$tab_data = form_get_data_for_profile_tabbed_display($form, $user);
+
+	echo elgg_view('form/forms/display_form_content',array('tab_data'=>$tab_data,'description'=>'','preview'=>0,'form'=>$form,'form_data_id'=>0,'embedded'=>$vars['embedded']));
+} else {
+	echo elgg_echo('form:error_no_profile_form');
+}
+if (!$vars['embedded']) {
+	echo '</div>';
+}
diff --git a/flexprofile_mj/views/default/flexprofile/menu/actions.php b/flexprofile_mj/views/default/flexprofile/menu/actions.php
new file mode 100755
index 00000000..f628c907
--- /dev/null
+++ b/flexprofile_mj/views/default/flexprofile/menu/actions.php
@@ -0,0 +1,3 @@
+<?php
+	echo "<p><a href=\"{$vars['url']}pg/flexprofile/{$vars['entity']->username}\">" . elgg_echo("form:extended_profile_link_text") . "</a></p>";
+?>
\ No newline at end of file
diff --git a/flexprofile_mj/views/default/profile/edit.php b/flexprofile_mj/views/default/profile/edit.php
new file mode 100755
index 00000000..f66e9f6b
--- /dev/null
+++ b/flexprofile_mj/views/default/profile/edit.php
@@ -0,0 +1,58 @@
+<?php
+/**
+	 * Elgg flex profile edit form
+	 * Allows user to edit profile
+	 * 
+	 * @package Elgg
+	 * @subpackage Form
+	 * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html GNU Public License version 2
+	 * @author Kevin Jardine <kevin@radagast.biz>
+	 * @copyright Radagast Solutions 2008
+	 * @link http://radagast.biz/
+	 */
+
+	 // Load flexprofile model
+require_once(dirname(dirname(dirname(dirname(__FILE__)))) . "/models/model.php");
+
+$user = $vars['entity'];
+$form = flexprofile_get_profile_form($user);
+if ($form) {
+	$tab_data = flexprofile_get_data_for_edit_form($form, $user);
+/* mjuhl: begin modification for UNL */
+// nope, remove this:
+//echo '<div class="contentWrapper">';
+
+
+/* import forms css */
+echo '<style type="text/css">@IMPORT url("/wdn/templates_3.0/css/content/forms.css");</style>';
+/* add 'cool' class to form */
+
+echo '<form action="'.$vars['url'].'action/flexprofile/edit" method="post" enctype="multipart/form-data" class="cool">';
+/* add fieldset and legend */
+echo '<fieldset><legend>Edit Profile</legend>';
+/* mjuhl: remove dynamic form by commenting out the following line: */
+echo '<!--------start copying here------------>';
+echo elgg_view('form/forms/display_form_content',array('tab_data'=>$tab_data,'description'=>'','preview'=>0,'form'=>$form,'form_data_id'=>0));
+echo '<!--------stop copying here------------>';
+?>
+
+<input type="hidden"  name="form_id"  value="104" /> <input type="hidden"  name="preview"  value="0" /> <input type="hidden"  name="form_data_id"  value="0" />
+<input type="hidden" name="username" value="<?php echo page_owner_entity()->username; ?>" />
+</fieldset>
+<?php 
+
+?>
+	<p class="submit">
+		
+		<input type="submit" value="<?php echo elgg_echo("save"); ?>" />
+	</p>
+
+</form>
+<?php
+} else {
+	echo elgg_echo('form:error_no_profile_form');
+}
+// once again, nope:
+//echo '</div>';
+/* mjuhl: end modification */
+?>
\ No newline at end of file
diff --git a/flexprofile_mj/views/default/profile/userdetails.php b/flexprofile_mj/views/default/profile/userdetails.php
new file mode 100755
index 00000000..e802191e
--- /dev/null
+++ b/flexprofile_mj/views/default/profile/userdetails.php
@@ -0,0 +1,184 @@
+<?php
+
+	/**
+	 * Elgg user display (details)
+	 * 
+	 * @package ElggProfile
+	 * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html GNU Public License version 2
+	 * @author Curverider Ltd <info@elgg.com>
+	 * @copyright Curverider Ltd 2008
+	 * @link http://elgg.com/
+	 * 
+	 * @uses $vars['entity'] The user entity
+	 */
+
+// Load flexprofile model
+require_once(dirname(dirname(dirname(dirname(__FILE__)))) . "/models/model.php");
+
+// Load form profile model
+require_once(dirname(dirname(dirname(dirname(dirname(__FILE__))))) . "/form/models/profile.php");
+
+if ($vars['full'] == true) {
+	$iconsize = "large";
+} else {
+	$iconsize = "medium";
+}
+
+// wrap all profile info
+echo "<div id=\"profile_info\">";
+
+?>
+
+<table cellspacing="0">
+<tr>
+<td>
+
+<?php	
+	
+	// wrap the icon and links in a div
+	echo "<div id=\"profile_info_column_left\">";
+	
+	echo "<div id=\"profile_icon_wrapper\">";
+	// get the user's main profile picture
+	echo elgg_view(
+						"profile/icon", array(
+												'entity' => $vars['entity'],
+												//'align' => "left",
+												'size' => $iconsize,
+												'override' => true,
+											  )
+					);
+
+
+    echo "</div>";
+    echo "<div class=\"clearfloat\"></div>";
+     // display relevant links			
+    echo elgg_view("profile/profilelinks", array("entity" => $vars['entity']));
+       
+    // close profile_info_column_left
+    
+    if ($vars['full'] == true) {
+
+        $form = flexprofile_get_profile_form($vars['entity']);
+  		if ($form) {
+	        if ($form->profile_format !== 'tabbed') {
+	        	$body = '';
+		        $data = form_get_data_for_profile_summary_display($form, $vars['entity']);
+		        // do left column
+				if ($data['left']) {
+					foreach($data['left'] as $item) {
+						$value = $item->value;
+						if (!empty($value)) {
+							
+						//This function controls the alternating class
+		                $even_odd = ( 'odd' != $even_odd ) ? 'odd' : 'even';
+			            $body .= "<p class=\"{$even_odd}\"><b>";	
+					    $body .= $item->title.':</b> ';	
+					    $body .= $item->value;
+				
+						}
+					}
+				}
+				print $body;
+	        }
+		}
+    }
+	
+    echo "</div>";
+
+?>
+</td>
+<td>
+	
+	<div id="profile_info_column_middle" >
+<?php
+    $editdetails = elgg_echo("profile:edit");
+    $body = '';
+	if ($vars['entity']->canEdit()) {
+        $body .= <<<END
+	<p class="profile_info_edit_buttons">
+		<a href="{$vars['url']}mod/profile/edit.php?username={$vars['entity']->username}">
+		$editdetails</a>
+	</p>
+END;
+
+	}
+	// Simple XFN
+	$rel = "";
+	if (page_owner() == $vars['entity']->guid)
+		$rel = 'me';
+	else if (check_entity_relationship(page_owner(), 'friend', $vars['entity']->guid))
+		$rel = 'friend';
+		
+	// display the users name
+	$body .= "<h2><a href=\"" . $vars['entity']->getUrl() . "\" rel=\"$rel\">" . $vars['entity']->name . "</a></h2>";
+
+	//insert a view that can be extended
+	$body .= elgg_view("profile/status", array("entity" => $vars['entity']));
+	// display the users name
+	//$body .= "<h2><a href=\"" . $vars['entity']->getUrl() . "\">" . $vars['entity']->name . "</a></h2>";
+
+	if ($vars['full'] == true) {
+		if ($form) {
+			if ($form->profile_format != 'tabbed') {		
+		        // do right column
+				if ($data['right']) {
+					foreach($data['right'] as $item) {
+						$value = $item->value;
+						if (!empty($value)) {
+							
+						//This function controls the alternating class
+		                $even_odd = ( 'odd' != $even_odd ) ? 'odd' : 'even';
+			            $body .= "<p class=\"{$even_odd}\"><b>";	
+					    $body .= $item->title.':</b> ';	
+					    $body .= $item->value;
+				
+						}
+					}
+				}
+			} else {
+				$body .= elgg_view('flexprofile/extended',array('entity'=>$vars['entity'],'embedded'=>true));
+			}
+		} else {
+			$body .= elgg_echo('form:error_no_profile_form');
+		}
+	}
+	
+	echo $body;
+			
+        
+	
+	?>
+	</div><!-- /#profile_info_column_middle -->
+
+</td>
+</tr>
+
+<tr>
+<td colspan="2">
+	<?php
+	if ($form) {
+		if ($form->profile_format != 'tabbed') {
+			if ($data['bottom']) {
+				echo '<div id="profile_info_column_right">';
+		    	foreach($data['bottom'] as $item) {		
+		    		echo '<b>'.$item->title.'</b>';
+		    		echo '<br /><br />';
+		    		echo $item->value;
+		    		echo '<br />';
+		        }
+		        echo '</div><!-- /#profile_info_column_right -->';
+		    }
+		}
+	}
+    ?>
+
+</td>
+</tr>
+
+
+</table>
+
+
+
+</div><!-- /#profile_info -->
\ No newline at end of file
-- 
GitLab