fmsystem-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Fmsystem-commits] [15765] Stable: Merge 15713:15764 from trunk


From: sigurdne
Subject: [Fmsystem-commits] [15765] Stable: Merge 15713:15764 from trunk
Date: Fri, 30 Sep 2016 07:11:26 +0000 (UTC)

Revision: 15765
          http://svn.sv.gnu.org/viewvc/?view=rev&root=fmsystem&revision=15765
Author:   sigurdne
Date:     2016-09-30 07:11:26 +0000 (Fri, 30 Sep 2016)
Log Message:
-----------
Stable: Merge 15713:15764 from trunk

Modified Paths:
--------------
    branches/Version-2_0-branch/activitycalendar/templates/base/css/base.css
    branches/Version-2_0-branch/booking/js/booking/schedule.js
    branches/Version-2_0-branch/booking/templates/base/css/base.css
    branches/Version-2_0-branch/booking/templates/base/season_wtemplate.xsl
    branches/Version-2_0-branch/bookingfrontend/css/bookingfrontend.css
    branches/Version-2_0-branch/bookingfrontend/js/bookingfrontend/schedule.js
    branches/Version-2_0-branch/controller/inc/class.uicomponent.inc.php
    branches/Version-2_0-branch/controller/setup/phpgw_no.lang
    branches/Version-2_0-branch/controller/templates/base/component.xsl
    branches/Version-2_0-branch/helpdesk/inc/class.uitts.inc.php
    branches/Version-2_0-branch/phpgwapi/inc/class.jquery.inc.php
    branches/Version-2_0-branch/phpgwapi/inc/class.uicommon_jquery.inc.php
    branches/Version-2_0-branch/phpgwapi/js/jquery/common.js
    branches/Version-2_0-branch/property/inc/class.bolocation.inc.php
    branches/Version-2_0-branch/property/inc/class.menu.inc.php
    branches/Version-2_0-branch/property/inc/class.soinvoice.inc.php
    branches/Version-2_0-branch/property/inc/class.solocation.inc.php
    branches/Version-2_0-branch/property/inc/class.sotts.inc.php
    branches/Version-2_0-branch/property/inc/class.uiimport.inc.php
    branches/Version-2_0-branch/property/inc/class.uitts.inc.php
    branches/Version-2_0-branch/property/inc/class.uiworkorder.inc.php
    
branches/Version-2_0-branch/property/inc/custom/default/BkBygg_exporter_varemottak_til_Agresso.php
    branches/Version-2_0-branch/property/setup/setup.inc.php
    branches/Version-2_0-branch/property/setup/tables_current.inc.php
    branches/Version-2_0-branch/property/setup/tables_update.inc.php
    branches/Version-2_0-branch/property/templates/base/tts.xsl
    branches/Version-2_0-branch/property/templates/base/workorder.xsl
    branches/Version-2_0-branch/registration/templates/base/css/base.css
    branches/Version-2_0-branch/rental/inc/class.boapplication.inc.php
    branches/Version-2_0-branch/rental/inc/class.menu.inc.php
    branches/Version-2_0-branch/rental/inc/class.soapplication.inc.php
    branches/Version-2_0-branch/rental/inc/class.socomposite.inc.php
    branches/Version-2_0-branch/rental/inc/class.socontract.inc.php
    branches/Version-2_0-branch/rental/inc/class.uiapplication.inc.php
    branches/Version-2_0-branch/rental/inc/class.uicomposite.inc.php
    branches/Version-2_0-branch/rental/inc/class.uicontract.inc.php
    branches/Version-2_0-branch/rental/inc/model/class.application.inc.php
    branches/Version-2_0-branch/rental/js/rental/application.edit.js
    branches/Version-2_0-branch/rental/js/rental/composite.edit.js
    branches/Version-2_0-branch/rental/js/rental/composite.view.js
    branches/Version-2_0-branch/rental/templates/base/application.xsl
    branches/Version-2_0-branch/rental/templates/base/composite.xsl
    branches/Version-2_0-branch/rental/templates/base/css/base.css

Added Paths:
-----------
    branches/Version-2_0-branch/controller/js/controller/component.index.js
    branches/Version-2_0-branch/phpgwapi/js/jquery/file-upload/
    branches/Version-2_0-branch/property/inc/class.uiimport_components.inc.php
    branches/Version-2_0-branch/property/inc/import/UploadHandler.php
    
branches/Version-2_0-branch/property/inc/import/class.import_component_files.inc.php
    
branches/Version-2_0-branch/property/inc/import/class.import_components.inc.php
    
branches/Version-2_0-branch/property/inc/import/class.import_entity_categories.inc.php
    
branches/Version-2_0-branch/property/inc/import/class.import_update_components.inc.php
    branches/Version-2_0-branch/property/js/portico/import_components.js
    branches/Version-2_0-branch/property/templates/base/images/ajax-loader.gif
    branches/Version-2_0-branch/property/templates/base/import_components.xsl
    branches/Version-2_0-branch/rental/js/rental/schedule.js
    branches/Version-2_0-branch/rental/templates/base/rental_schedule.xsl
    branches/Version-2_0-branch/rental/templates/base/schedule.xsl

Property Changed:
----------------
    branches/Version-2_0-branch/
    branches/Version-2_0-branch/booking/
    branches/Version-2_0-branch/bookingfrontend/


Property changes on: branches/Version-2_0-branch
___________________________________________________________________
Modified: svn:mergeinfo
   - /branches/dev-syncromind:13653
/branches/dev-syncromind-2:14937-15027,15165-15215,15223-15228,15230-15243,15245-15250,15254-15257
/branches/stavangerkommune:12743-12875,12986
/trunk:14721-14732,14734-14735,14737,14739,14741,14743-14744,14746-14749,14751,14753,14755-14757,14759,14761-14764,14766-14768,14770-14783,14785-14792,14794-14813,14815-14816,14818,14820-14822,14824-14825,14827-14829,14831-14834,14836,14838,14840-14842,14844-14845,14847,14849-14866,14868-14869,14871,14873-14875,14877-14878,14880-14884,14886-14896,14898,14900-14902,14904,14906-14909,14911-14915,14917-14919,14921-14922,14924-14978,14980-15258,15260-15261,15263-15264,15266-15285,15287-15288,15290-15291,15293,15295,15297,15299-15305,15307-15310,15312-15335,15337-15352,15354,15356,15358,15360-15541,15543-15566,15568-15569,15571,15573-15581,15583,15585-15617,15619,15621-15630,15632-15635,15637-15639,15641-15643,15645,15647-15665,15667-15668,15670-15671,15673-15693,15695-15712
   + /branches/dev-syncromind:13653
/branches/dev-syncromind-2:14933-15747
/branches/stavangerkommune:12743-12875,12986
/trunk:14721-14732,14734-14735,14737,14739,14741,14743-14744,14746-14749,14751,14753,14755-14757,14759,14761-14764,14766-14768,14770-14783,14785-14792,14794-14813,14815-14816,14818,14820-14822,14824-14825,14827-14829,14831-14834,14836,14838,14840-14842,14844-14845,14847,14849-14866,14868-14869,14871,14873-14875,14877-14878,14880-14884,14886-14896,14898,14900-14902,14904,14906-14909,14911-14915,14917-14919,14921-14922,14924-14978,14980-15258,15260-15261,15263-15264,15266-15285,15287-15288,15290-15291,15293,15295,15297,15299-15305,15307-15310,15312-15335,15337-15352,15354,15356,15358,15360-15541,15543-15566,15568-15569,15571,15573-15581,15583,15585-15617,15619,15621-15630,15632-15635,15637-15639,15641-15643,15645,15647-15665,15667-15668,15670-15671,15673-15693,15695-15712,15714-15764

Modified: 
branches/Version-2_0-branch/activitycalendar/templates/base/css/base.css
===================================================================
--- branches/Version-2_0-branch/activitycalendar/templates/base/css/base.css    
2016-09-30 07:03:33 UTC (rev 15764)
+++ branches/Version-2_0-branch/activitycalendar/templates/base/css/base.css    
2016-09-30 07:11:26 UTC (rev 15765)
@@ -265,7 +265,7 @@
 #week-selector li { display: inline; padding-right: .5em;}
 
 #schedule_container tr td { border-top: 1px solid #ccc; background: white; 
white-space: nowrap; }
-#schedule_container tr td:first-child { background: #eee; }
+#schedule_container tbody tr th:first-child { background: #eee; }
 #schedule_container tr.time td { border-top: 1px solid #444;}
 #schedule_container .color1 { background: #ccf;}
 #schedule_container .color2 { background: #cfc;}


Property changes on: branches/Version-2_0-branch/booking
___________________________________________________________________
Modified: svn:mergeinfo
   - /branches/stavangerkommune/booking:9468-12740,12743-12875,12986
/trunk/booking:14721-14732,14824-14825,14827-14829,14831-14834,14836,14838,14840-14842,14844-14845,14871,14886-14896,14900-14902,14917-14919,14924-14978,14980-15258,15266-15285,15287-15288,15297,15299-15305,15307-15310,15312-15335,15337-15352,15354,15360-15541,15543-15566,15568-15569,15585-15617,15621-15630,15637-15639,15641-15643,15645,15647-15665,15667-15668,15695-15712
   + /branches/dev-syncromind-2/booking:14933-15747
/branches/stavangerkommune/booking:9468-12740,12743-12875,12986
/trunk/booking:14721-14732,14824-14825,14827-14829,14831-14834,14836,14838,14840-14842,14844-14845,14871,14886-14896,14900-14902,14917-14919,14924-14978,14980-15258,15266-15285,15287-15288,15297,15299-15305,15307-15310,15312-15335,15337-15352,15354,15360-15541,15543-15566,15568-15569,15585-15617,15621-15630,15637-15639,15641-15643,15645,15647-15665,15667-15668,15695-15712,15714-15764

Modified: branches/Version-2_0-branch/booking/js/booking/schedule.js
===================================================================
--- branches/Version-2_0-branch/booking/js/booking/schedule.js  2016-09-30 
07:03:33 UTC (rev 15764)
+++ branches/Version-2_0-branch/booking/js/booking/schedule.js  2016-09-30 
07:11:26 UTC (rev 15765)
@@ -1,4 +1,5 @@
 var schedule = new Array();
+schedule.params = {};
 
 schedule.renderSchedule = function (container, url, date, colFormatter, 
includeResource, classTable)
 {
@@ -11,6 +12,7 @@
 //    container.innerHTML = '';
        var datestr = date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + 
date.getDate();
        url += '&date=' + datestr;
+       schedule.params.date = datestr;
 
        var detected_lang = navigator.language || navigator.userLanguage;
        var lang = {};
@@ -46,7 +48,7 @@
        }
 
        var colDefs = [
-               {key: 'time', label: date.getFullYear() + '<br/>' + 
lang['LBL_TIME']}];
+               {key: 'time', label: date.getFullYear() + '<br/>' + 
lang['LBL_TIME'], type: 'th'}];
        if (includeResource)
        {
                colDefs.push({key: 'resource', label: lang['LBL_RESOURCE'], 
formatter: 'scheduleResourceColumn'});
@@ -62,8 +64,10 @@
                colDefs.push({key: keys[x], label: lang['WEEKDAYS_FULL'][x] + 
'<br>' + lang['MONTHS_LONG'][d.getMonth()] + ' ' + d.getDate(), formatter: 
colFormatter, date: d, day: d.getDate()});
        }
        var r = [{n: 'ResultSet'}, {n: 'Result'}];
+       var params = (schedule.params) ? schedule.params : new Array();
+
 //    createta d u c r cl
-       createTableSchedule(container, url, colDefs, r, classTable, datestr);
+       createTableSchedule(container, url, colDefs, r, classTable, params);
 
 };
 

Modified: branches/Version-2_0-branch/booking/templates/base/css/base.css
===================================================================
--- branches/Version-2_0-branch/booking/templates/base/css/base.css     
2016-09-30 07:03:33 UTC (rev 15764)
+++ branches/Version-2_0-branch/booking/templates/base/css/base.css     
2016-09-30 07:11:26 UTC (rev 15765)
@@ -180,7 +180,7 @@
 #week-selector li { display: inline; padding-right: .5em;}
 
 #schedule_container tr td { border-top: 1px solid #ccc; background: white; 
white-space: nowrap; }
-#schedule_container tr td:first-child { background: #eee; }
+#schedule_container tbody tr th:first-child { background: #eee; }
 #schedule_container tr.time td { border-top: 1px solid #444;}
 #schedule_container .color1  { background-color: #ccccff;}
 #schedule_container .color2  { background-color: #ccffcc;}

Modified: 
branches/Version-2_0-branch/booking/templates/base/season_wtemplate.xsl
===================================================================
--- branches/Version-2_0-branch/booking/templates/base/season_wtemplate.xsl     
2016-09-30 07:03:33 UTC (rev 15764)
+++ branches/Version-2_0-branch/booking/templates/base/season_wtemplate.xsl     
2016-09-30 07:11:26 UTC (rev 15765)
@@ -96,7 +96,7 @@
                var colDefs = [];
                $(window).load(function() {
                colDefs = [
-               {key: 'time', label: '<xsl:value-of 
select="php:function('lang', 'Time')" />'},
+               {key: 'time', label: '<xsl:value-of 
select="php:function('lang', 'Time')" />', type: 'th'},
                {key: 'resource', label: '<xsl:value-of 
select="php:function('lang', 'Resources')" />', formatter: 
'scheduleResourceColumn'},
                {key: '1', label: '<xsl:value-of select="php:function('lang', 
'Monday')" />', formatter: 'seasonDateColumn'},
                {key: '2', label: '<xsl:value-of select="php:function('lang', 
'Tuesday')" />', formatter: 'seasonDateColumn'},


Property changes on: branches/Version-2_0-branch/bookingfrontend
___________________________________________________________________
Modified: svn:mergeinfo
   - /branches/stavangerkommune/bookingfrontend:9468-12740,12986
/trunk/bookingfrontend:14721-14732,14770-14783,14794-14808,14824-14825,14838,14886-14894,14906-14909,14917-14919,14924-14978,14980-15258,15297,15312-15335,15585-15617,15621-15630
   + /branches/dev-syncromind-2/bookingfrontend:14933-15747
/branches/stavangerkommune/bookingfrontend:9468-12740,12986
/trunk/bookingfrontend:14721-14732,14770-14783,14794-14808,14824-14825,14838,14886-14894,14906-14909,14917-14919,14924-14978,14980-15258,15297,15312-15335,15585-15617,15621-15630,15714-15764

Modified: branches/Version-2_0-branch/bookingfrontend/css/bookingfrontend.css
===================================================================
--- branches/Version-2_0-branch/bookingfrontend/css/bookingfrontend.css 
2016-09-30 07:03:33 UTC (rev 15764)
+++ branches/Version-2_0-branch/bookingfrontend/css/bookingfrontend.css 
2016-09-30 07:11:26 UTC (rev 15765)
@@ -407,7 +407,7 @@
     border-top: 1px solid #ccc;
     white-space: nowrap;
 }
-#schedule_container tr td:first-child {
+#schedule_container tbody tr th:first-child {
     background: #eee none repeat scroll 0 0;
 }
 #schedule_container tr.time td {

Modified: 
branches/Version-2_0-branch/bookingfrontend/js/bookingfrontend/schedule.js
===================================================================
--- branches/Version-2_0-branch/bookingfrontend/js/bookingfrontend/schedule.js  
2016-09-30 07:03:33 UTC (rev 15764)
+++ branches/Version-2_0-branch/bookingfrontend/js/bookingfrontend/schedule.js  
2016-09-30 07:11:26 UTC (rev 15765)
@@ -1,4 +1,5 @@
 var schedule = new Array();
+schedule.params = {};
 
 schedule.renderSchedule = function (container, url, date, colFormatter, 
includeResource, classTable)
 {
@@ -9,6 +10,7 @@
        }
        var datestr = date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + 
date.getDate();
        url += '&date=' + datestr;
+       schedule.params.date = datestr;
 
        var detected_lang = navigator.language || navigator.userLanguage;
        var lang = {};
@@ -44,7 +46,8 @@
        }
 
        var colDefs = [
-               {key: 'time', label: date.getFullYear() + '<br/>' + 
lang['LBL_TIME']}];
+               {key: 'time', label: date.getFullYear() + '<br/>' + 
lang['LBL_TIME'], type: 'th'}
+    ];
        if (includeResource)
        {
                colDefs.push({key: 'resource', label: lang['LBL_RESOURCE'], 
formatter: 'scheduleResourceColumn'});
@@ -60,8 +63,10 @@
                colDefs.push({key: keys[x], label: lang['WEEKDAYS_FULL'][x] + 
'<br>' + lang['MONTHS_LONG'][d.getMonth()] + ' ' + d.getDate(), formatter: 
colFormatter, date: d, day: d.getDate()});
        }
        var r = [{n: 'ResultSet'}, {n: 'Result'}];
+       var params = (schedule.params) ? schedule.params : new Array();
+
 //    createta d u c r cl
-       createTableSchedule(container, url, colDefs, r, classTable, datestr);
+       createTableSchedule(container, url, colDefs, r, classTable, params);
 
 };
 

Modified: branches/Version-2_0-branch/controller/inc/class.uicomponent.inc.php
===================================================================
--- branches/Version-2_0-branch/controller/inc/class.uicomponent.inc.php        
2016-09-30 07:03:33 UTC (rev 15764)
+++ branches/Version-2_0-branch/controller/inc/class.uicomponent.inc.php        
2016-09-30 07:11:26 UTC (rev 15765)
@@ -57,6 +57,7 @@
                private $edit;
                private $delete;
                private $org_units;
+               private $custom;
                public $public_functions = array
                        (
                        'index' => true,
@@ -85,6 +86,8 @@
                        {
                                $GLOBALS['phpgw_info']['flags']['noframework'] 
= true;
                        }
+                       $this->custom = createObject('phpgwapi.custom_fields');
+
                }
 
                public function add_controll_from_master()
@@ -181,6 +184,7 @@
                                return $this->query();
                        }
                        phpgwapi_jquery::load_widget('core');
+                       phpgwapi_jquery::load_widget('autocomplete');
 
                        $users = 
$GLOBALS['phpgw']->acl->get_user_list_right(PHPGW_ACL_EDIT, '.checklist');
                        $user_list = array();
@@ -358,6 +362,9 @@
                                        'field' => 
$this->get_fields($filter_component),
                                ),
                        );
+
+                       self::add_javascript('controller', 'controller', 
'component.index.js');
+
                        self::render_template_xsl(array('component', 
'calendar/icon_color_map'), $data);
                }
 
@@ -465,10 +472,93 @@
                        }
                }
 
+               private function _get_location_filter_options( $location_id )
+               {
+                       $attrib_data = $this->_get_attrib_data( $location_id );
+
+                       $combos = array();
+                       $values_combo_box = array();
+
+                       if ($attrib_data)
+                       {
+                               $count = 0;
+                               foreach ($attrib_data as $attrib)
+                               {
+                                       if (($attrib['datatype'] == 'LB' || 
$attrib['datatype'] == 'CH' || $attrib['datatype'] == 'R') && $attrib['choice'])
+                                       {
+                                               $values_combo_box[$count][] = 
array(
+                                                       'id' => '',
+                                                       'name' => 
lang('select') . " '{$attrib['input_text']}'"
+                                               );
+
+                                               foreach ($attrib['choice'] as 
$choice)
+                                               {
+                                                       
$values_combo_box[$count][] = array(
+                                                               'id' => 
$choice['id'],
+                                                               'name' => 
htmlspecialchars($choice['value'], ENT_QUOTES, 'UTF-8'),
+                                                       );
+                                               }
+
+                                               $combos[] = array(
+                                                       'type' => 'filter',
+                                                       'name' => 
$attrib['column_name'],
+                                                       'list' => 
$values_combo_box[$count]
+                                               );
+
+                                               $count++;
+                                       }
+                               }
+                       }
+
+                       return $combos;
+
+               }
+
+               private function _get_attrib_data( $location_id )
+               {
+                       static $attrib_data = array();
+                       if(!isset($attrib_data[$location_id]))
+                       {
+                               $attrib_data[$location_id] = 
$this->custom->find2($location_id, 0, '', '', '', true, true);
+                       }
+                       return $attrib_data[$location_id];
+               }
+
+               private function _get_attrib_filter( $location_id )
+               {
+                       $attrib_data = $this->_get_attrib_data( $location_id );
+
+                       $attrib_filter = array();
+                       if ($attrib_data)
+                       {
+                               foreach ($attrib_data as $attrib)
+                               {
+                                       if ($attrib['datatype'] == 'LB' || 
$attrib['datatype'] == 'R')
+                                       {
+                                               if ($_attrib_filter_value = 
phpgw::get_var("custom_{$location_id}_{$attrib['column_name']}", 'int'))
+                                               {
+                                                       $attrib_filter[] = 
"json_representation->>'{$attrib['column_name']}' = '{$_attrib_filter_value}'";
+                                               }
+                                       }
+                                       else if ($attrib['datatype'] == 'CH')
+                                       {
+                                               if ($_attrib_filter_value = 
phpgw::get_var("custom_{$location_id}_{$attrib['column_name']}", 'int'))
+                                               {
+                                                       $attrib_filter[] = 
"json_representation->>'{$attrib['column_name']}' {$GLOBALS['phpgw']->db->like} 
'%,{$_attrib_filter_value},%'";
+                                               }
+                                       }
+                               }
+                       }
+                       return $attrib_filter;
+               }
+
+
+
                public function query()
                {
                        $entity_group_id = phpgw::get_var('entity_group_id', 
'int');
                        $location_id = phpgw::get_var('location_id', 'int');
+                       $location_code = phpgw::get_var('location_code', 
'string');
                        $control_area = phpgw::get_var('control_area', 'int');
                        $user_id = phpgw::get_var('user_id', 'int');
                        $district_id = phpgw::get_var('district_id', 'int');
@@ -541,6 +631,7 @@
                                                'filter_entity_group' => 
$entity_group_id,
                                                'location_id' => $_location_id,
                                                'district_id' => $district_id,
+                                               'location_code' => 
$location_code,
                                                'allrows' => true,
                                                'filter_item' => $component_list
                                                )
@@ -573,18 +664,23 @@
                                        $_location_id = 
(int)$_location_filter['id'];
                                        $exclude_locations[] = $_location_id;
 
+                                       $location_filter_options = 
$this->_get_location_filter_options($_location_id);
+
                                        $_components = 
execMethod('property.soentity.read', array(
                                                'filter_entity_group' => 
$entity_group_id,
                                                'location_id' => $_location_id,
                                                'district_id' => $district_id,
+                                               'location_code' => 
$location_code,
                                                'org_units' => $this->org_units,
                                                'allrows' => true,
                                                'control_registered' => 
!$all_items,
                                                'check_for_control' => true,
-                                               'filter_item' => 
$filter_component ? array($filter_component) : array()
+                                               'filter_item' => 
$filter_component ? array($filter_component) : array(),
+                                               'attrib_filter' => 
$this->_get_attrib_filter($_location_id)
                                                )
                                        );
                                        $components = array_merge($components, 
$_components);
+
                                }
 
                                if ($lookup_stray_items)
@@ -594,6 +690,7 @@
                                                'exclude_locations' => 
$exclude_locations,
                                                'location_id' => $_location_id,
                                                'district_id' => $district_id,
+                                               'location_code' => 
$location_code,
                                                'org_units' => $this->org_units,
                                                'allrows' => true,
                                                'control_registered' => 
!$all_items,
@@ -1021,7 +1118,9 @@
                        return array(
                                'components' => $result,
                                'summary' => null,
-                               'location_filter' => $location_filter
+                               'location_filter' => $location_filter,
+                               'location_filter_options'       => 
$location_filter_options,
+                               'return_location_id'            => 
(int)$_location_id
                        );
                }
 

Copied: branches/Version-2_0-branch/controller/js/controller/component.index.js 
(from rev 15764, trunk/controller/js/controller/component.index.js)
===================================================================
--- branches/Version-2_0-branch/controller/js/controller/component.index.js     
                        (rev 0)
+++ branches/Version-2_0-branch/controller/js/controller/component.index.js     
2016-09-30 07:11:26 UTC (rev 15765)
@@ -0,0 +1,341 @@
+/**
+ * Detect if browsertab is active - and update when revisit
+ */
+var vis = (function ()
+{
+       var stateKey, eventKey, keys = {
+               hidden: "visibilitychange",
+               webkitHidden: "webkitvisibilitychange",
+               mozHidden: "mozvisibilitychange",
+               msHidden: "msvisibilitychange"
+       };
+       for (stateKey in keys)
+       {
+               if (stateKey in document)
+               {
+                       eventKey = keys[stateKey];
+                       break;
+               }
+       }
+       return function (c)
+       {
+               if (c)
+
+                       document.addEventListener(eventKey, c);
+               return !document[stateKey];
+       }
+})();
+
+vis(function ()
+{
+       if (vis())
+       {
+               update_table();
+       }
+});
+
+
+
+$(document).ready(function ()
+{
+       update_table();
+
+       $("#location_name").on("autocompleteselect", function (event, ui)
+       {
+               var location_code = ui.item.value;
+//             alert($("#location_code").val());
+//             $("#location_code").val(location_code);
+               update_table(location_code);
+//             if (location_code != location_code_selection)
+//             {
+//                     building_id_selection = building_id;
+//             }
+       });
+});
+
+deselect_component = function ()
+{
+       $("[name='filter_component']").val('');
+       update_table();
+};
+update_table = function (location_code)
+{
+       if(typeof(location_code) == 'undefined')
+       {
+               location_code = $("#location_code").val();
+       }
+
+       $("#receipt").html('');
+
+       var report_type = $("#report_type").val();
+       var user_id = $("#user_id").val();
+       var custom_frontend = $("[name='custom_frontend']").val();
+       var hide_all_users = false;
+
+       if (custom_frontend == 1)
+       {
+               $("#user_id").hide();
+               $("[for='user_id']").hide();
+       }
+//console.log(user_id);
+       if (user_id < 0 || custom_frontend == 1)
+       {
+               $("#entity_group_id").hide();
+               $("[for='entity_group_id']").hide();
+               $("#location_id").hide();
+               $("[for='location_id']").hide();
+               $("[name='all_items']").hide();
+               $("[for='all_items']").hide();
+               $("#org_unit_id").hide();
+               $("[for='org_unit_id']").hide();
+               $("[name='all_users']").hide();
+               $("[for='all_users']").hide();
+               hide_all_users = true;
+       }
+       else
+       {
+               $("#entity_group_id").show();
+               $("[for='entity_group_id']").show();
+               $("#location_id").show();
+               $("[for='location_id']").show();
+               $("[name='all_items']").show();
+               $("[for='all_items']").show();
+               $("#org_unit_id").show();
+               $("[for='org_unit_id']").show();
+               $("[name='all_users']").show();
+               $("[for='all_users']").show();
+       }
+
+       if (report_type != 'summary' && hide_all_users == false)
+       {
+               $("[name='all_users']").show();
+               $("[for='all_users']").show();
+       }
+
+       if (user_id == '')
+       {
+               $("[name='all_users']").hide();
+               $("[for='all_users']").hide();
+       }
+
+       if (report_type == 'summary')
+       {
+               $("[name='all_items']").hide();
+               $("[for='all_items']").hide();
+               $("[name='status']").hide();
+               $("[for='status']").hide();
+       }
+
+       var requestUrl = $("#queryForm").attr("action");
+       requestUrl += '&phpgw_return_as=json' + "&" + 
$("#queryForm").serialize() + "&location_code=" + location_code ;
+
+       $.ajax({
+               type: 'POST',
+               dataType: 'json',
+               url: requestUrl,
+               success: function (data)
+               {
+                       if (data != null)
+                       {
+                               var components_data = data.components;
+                               var summary_data = data.summary;
+                               if (data.location_filter)
+                               {
+                                       var obj = data.location_filter;
+                                       var htmlString = "<option value=''>" + 
obj.length + " register funnet</option>";
+                                       var entity_group_id = 
$("#entity_group_id").val();
+                                       var location_id = 
$("#location_id").val();
+
+                                       if (entity_group_id)
+                                       {
+                                               var selected = '';
+                                               if (location_id == -1)
+                                               {
+                                                       selected = ' selected';
+                                               }
+                                               htmlString += "<option 
value='-1'" + selected + ">Velg alle</option>";
+                                       }
+
+                                       $.each(obj, function (i)
+                                       {
+                                               var selected = '';
+                                               if (obj[i].selected == 1)
+                                               {
+                                                       selected = ' selected';
+                                               }
+
+                                               htmlString += "<option value='" 
+ obj[i].id + "'" + selected + ">" + obj[i].name + "</option>";
+
+                                       });
+
+                                       $("#location_id").html(htmlString);
+
+                               }
+
+
+                               var filter_options = 
data.location_filter_options;
+                               var return_location_id = 
data.return_location_id;
+                               var filtered_location_id = 
$("#filtered_location_id").val();
+                               var location_id = $("#location_id").val();
+                               if (filter_options == null)
+                               {
+                                       $("#extra_row").hide();
+
+                               }
+                               if (filter_options !== null && 
filtered_location_id != return_location_id)
+                               {
+                                       
$("#filtered_location_id").val(location_id);
+                                       $("#extra_row").show();
+                                       $("#extra_filter").html('');
+                                       var $extra_filter = $("#extra_filter");
+                                       $.each(filter_options, function (key, 
filter)
+                                       {
+                                               var list = filter.list;
+                                               
$extra_filter.append($("<select></select>").attr("id", location_id + '_' + 
filter.name).text(location_id + '_' + filter.name));
+
+                                               var custom_select = $("#" + 
location_id + '_' + filter.name);
+
+                                               $.each(list, function (key, 
value)
+                                               {
+                                                       
custom_select.append($("<option></option>").attr("value", 
value.id).text(value.name));
+                                               });
+
+                                               $(document).on("change", "#" + 
location_id + '_' + filter.name, function ()
+                                               {
+
+                                                       var custom_input = 
document.getElementById("custom_" + location_id + '_' + filter.name);
+
+                                                       if (custom_input != 
null)
+                                                       {
+                                                               $("#custom_" + 
location_id + '_' + filter.name).val($(this).val());
+                                                       }
+                                                       else
+                                                       {
+                                                               $('<input 
/>').attr('type', 'hidden')
+                                                                       
.attr('id', 'custom_' + location_id + '_' + filter.name)
+                                                                       
.attr('name', 'custom_' + location_id + '_' + filter.name)
+                                                                       
.attr('value', $(this).val())
+                                                                       
.appendTo('#queryForm');
+                                                       }
+                                                       update_table();
+
+                                               });
+
+                                       });
+                               }
+
+                               if (components_data !== null)
+                               {
+                                       $("#tbody").html(components_data.tbody);
+                                       var time_sum = components_data.time_sum;
+                                       var time_sum_actual = 
components_data.time_sum_actual;
+
+                                       
$("#checkall").html(components_data.checkall);
+                                       
$("#total_records").html(components_data.total_records);
+                                       $("#sum_text").html('Sum');
+                                       $("#month0").html(time_sum[0] + '/' + 
time_sum_actual[0]);
+                                       $("#month1").html(time_sum[1] + '/' + 
time_sum_actual[1]);
+                                       $("#month2").html(time_sum[2] + '/' + 
time_sum_actual[2]);
+                                       $("#month3").html(time_sum[3] + '/' + 
time_sum_actual[3]);
+                                       $("#month4").html(time_sum[4] + '/' + 
time_sum_actual[4]);
+                                       $("#month5").html(time_sum[5] + '/' + 
time_sum_actual[5]);
+                                       $("#month6").html(time_sum[6] + '/' + 
time_sum_actual[6]);
+                                       $("#month7").html(time_sum[7] + '/' + 
time_sum_actual[7]);
+                                       $("#month8").html(time_sum[8] + '/' + 
time_sum_actual[8]);
+                                       $("#month9").html(time_sum[9] + '/' + 
time_sum_actual[9]);
+                                       $("#month10").html(time_sum[10] + '/' + 
time_sum_actual[10]);
+                                       $("#month11").html(time_sum[11] + '/' + 
time_sum_actual[11]);
+                                       $("#month12").html(time_sum[12] + '/' + 
time_sum_actual[12]);
+                               }
+
+                               if (summary_data !== null)
+                               {
+                                       $("#status_summary").show();
+                                       $("#components").hide();
+                                       $("#status_summary").html(summary_data);
+                               }
+                               else
+                               {
+                                       $("#status_summary").hide();
+                                       $("#components").show();
+
+                               }
+                       }
+
+               }
+       });
+
+};
+
+add_from_master = function (myclass)
+{
+       var myRadio = $('input[name=master_component]');
+       var master_component = myRadio.filter(':checked').val();
+
+       if (!master_component)
+       {
+               alert('velg master');
+               return;
+       }
+
+       var selected = new Array();
+
+       $("." + myclass).each(function ()
+       {
+               if ($(this).prop("checked"))
+               {
+                       selected.push($(this).val());
+               }
+       });
+
+       oArgs = {menuaction: 'controller.uicomponent.add_controll_from_master'};
+       var requestUrl = phpGWLink('index.php', oArgs, true);
+
+       $.ajax({
+               type: 'POST',
+               data: {master_component: master_component, target: selected},
+               dataType: 'json',
+               url: requestUrl,
+               success: function (data)
+               {
+                       if (data != null)
+                       {
+//console.log(data);
+                               var message = data.message;
+
+                               htmlString = "";
+                               var msg_class = "msg_good";
+                               if (data.status == 'error')
+                               {
+                                       msg_class = "error";
+                               }
+                               htmlString += "<div class=\"" + msg_class + 
"\">";
+                               htmlString += message;
+                               htmlString += '</div>';
+                               update_table();
+                               $("#receipt").html(htmlString);
+
+                       }
+               }
+       });
+
+};
+
+checkAll = function (myclass)
+{
+       $("." + myclass).each(function ()
+       {
+               if ($(this).prop("checked"))
+               {
+                       $(this).prop("checked", false);
+               }
+               else
+               {
+                       $(this).prop("checked", true);
+               }
+       });
+};
+
+var oArgs = {menuaction: 'property.bolocation.get_locations'};
+var strURL = phpGWLink('index.php', oArgs, true);
+JqueryPortico.autocompleteHelper(strURL, 'location_name', 'location_code', 
'location_container');

Modified: branches/Version-2_0-branch/controller/setup/phpgw_no.lang
===================================================================
--- branches/Version-2_0-branch/controller/setup/phpgw_no.lang  2016-09-30 
07:03:33 UTC (rev 15764)
+++ branches/Version-2_0-branch/controller/setup/phpgw_no.lang  2016-09-30 
07:11:26 UTC (rev 15765)
@@ -391,4 +391,5 @@
 components     controller      no      Komponenter
 report type    controller      no      RapportType
 lang_control_mandatory_location        controller      no      PĂ„krevd 
lokasjonsvalg
-Control types  controller      no      Kontrolltyper
\ No newline at end of file
+Control types  controller      no      Kontrolltyper
+location       controller      no      Lokasjon
\ No newline at end of file

Modified: branches/Version-2_0-branch/controller/templates/base/component.xsl
===================================================================
--- branches/Version-2_0-branch/controller/templates/base/component.xsl 
2016-09-30 07:03:33 UTC (rev 15764)
+++ branches/Version-2_0-branch/controller/templates/base/component.xsl 
2016-09-30 07:11:26 UTC (rev 15765)
@@ -199,8 +199,32 @@
                                                </td>
                                        </tr>
                                </xsl:for-each>
+                               <tr id = 'location_code'>
+                                       <td>
+                                               <label for='location_code'>
+                                               <xsl:value-of 
select="php:function('lang', 'location')"/>
+                                               </label>
+                                               </td>
+                                       <td>
+                                               <input type="hidden" 
id="location_code" name="location_code" />
+                                               <input type="text" 
id="location_name" name="location_name" />
+                                               <div id="location_container"/>
+                                       </td>
+                               </tr>
+                               <tr id = 'extra_row'>
+                                       <td>
+                                               <label for='extra_filter'>
+                                                       Extra
+                                               </label>
+                                               </td>
+                                       <td>
+                                               <div id="extra_filter">
+                                               </div>
+                                       </td>
+                               </tr>
                        </tbody>
                </table>
+               <input type ='hidden' id='filtered_location_id'/>
        </div>
 </xsl:template>
 
@@ -263,270 +287,6 @@
 
 
 <xsl:template name="datasource-definition">
-       <script type="text/javascript">
-<![CDATA[
-
-               /**
-               * Detect if browsertab is active - and update when revisit
-               */
-               var vis = (function(){
-                       var stateKey, eventKey, keys = {
-                               hidden: "visibilitychange",
-                               webkitHidden: "webkitvisibilitychange",
-                               mozHidden: "mozvisibilitychange",
-                               msHidden: "msvisibilitychange"
-                       };
-                       for (stateKey in keys) {
-                               if (stateKey in document) {
-                                       eventKey = keys[stateKey];
-                                       break;
-                               }
-                       }
-                       return function(c) {
-                               if (c) document.addEventListener(eventKey, c);
-                               return !document[stateKey];
-                       }
-               })();
-
-               vis(function(){
-                       if(vis())
-                       {
-                                       update_table();
-                       }
-               });
-
-
-
-               $(document).ready(function(){
-                       update_table();
-               });
-
-               deselect_component = function()
-               {
-                       $("[name='filter_component']").val('');
-                       update_table();
-               };
-               update_table = function()
-               {
-                       $("#receipt").html('');
-
-                       var report_type = $("#report_type").val();
-                       var user_id = $("#user_id").val();
-                       var custom_frontend = 
$("[name='custom_frontend']").val();
-                       var hide_all_users = false;
-
-                       if(custom_frontend ==1)
-                       {
-                               $( "#user_id" ).hide();
-                               $("[for='user_id']").hide();
-                       }
-//console.log(user_id);
-                       if(user_id < 0 || custom_frontend ==1)
-                       {
-                               $( "#entity_group_id" ).hide();
-                               $("[for='entity_group_id']").hide();
-                               $( "#location_id" ).hide();
-                               $("[for='location_id']").hide();
-                               $("[name='all_items']").hide();
-                               $("[for='all_items']").hide();
-                               $( "#org_unit_id" ).hide();
-                               $("[for='org_unit_id']").hide();
-                               $("[name='all_users']").hide();
-                               $("[for='all_users']").hide();
-                               hide_all_users = true;
-                       }
-                       else
-                       {
-                               $( "#entity_group_id" ).show();
-                               $("[for='entity_group_id']").show();
-                               $( "#location_id" ).show();
-                               $("[for='location_id']").show();
-                               $("[name='all_items']").show();
-                               $("[for='all_items']").show();
-                               $( "#org_unit_id" ).show();
-                               $("[for='org_unit_id']").show();
-                               $("[name='all_users']").show();
-                               $("[for='all_users']").show();
-                       }
-
-                       if(report_type != 'summary' && hide_all_users == false)
-                       {
-                               $("[name='all_users']").show();
-                               $("[for='all_users']").show();
-                       }
-
-                       if(user_id == '')
-                       {
-                               $("[name='all_users']").hide();
-                               $("[for='all_users']").hide();
-                       }
-
-                       if(report_type == 'summary')
-                       {
-                               $("[name='all_items']").hide();
-                               $("[for='all_items']").hide();
-                               $("[name='status']").hide();
-                               $("[for='status']").hide();
-                       }
-
-                       var requestUrl = $("#queryForm").attr("action");
-                       requestUrl += '&phpgw_return_as=json' + "&" + 
$("#queryForm").serialize();
-
-                       $.ajax({
-                               type: 'POST',
-                               dataType: 'json',
-                               url: requestUrl,
-                               success: function(data) {
-                                       if( data != null)
-                                       {
-                                               var components_data = 
data.components;
-                                               var summary_data = data.summary;
-                                               if(data.location_filter)
-                                               {
-                                                       var obj = 
data.location_filter;
-                                                       var htmlString  = 
"<option value=''>" + obj.length + " register funnet</option>";
-                                                       var entity_group_id = 
$("#entity_group_id").val();
-                                                       var location_id = 
$("#location_id").val();
-
-                                                       if(entity_group_id)
-                                                       {
-                                                               var selected = 
'';
-                                                               if(location_id 
== -1)
-                                                               {
-                                                                       
selected = ' selected';
-                                                               }
-                                                               htmlString  += 
"<option value='-1'" + selected + ">Velg alle</option>";
-                                                       }
-
-                                                       $.each(obj, function(i)
-                                                       {
-                                                               var selected = 
'';
-                                                               
if(obj[i].selected == 1)
-                                                               {
-                                                                       
selected = ' selected';
-                                                               }
-
-                                                               htmlString  += 
"<option value='" + obj[i].id + "'" + selected + ">" + obj[i].name + 
"</option>";
-
-                                                       });
-
-                                                       $("#location_id").html( 
htmlString );
-
-                                               }
-
-                                               if(components_data !==null)
-                                               {
-                                                       
$("#tbody").html(components_data.tbody);
-                                                       var time_sum = 
components_data.time_sum;
-                                                       var time_sum_actual = 
components_data.time_sum_actual;
-
-                                                       
$("#checkall").html(components_data.checkall);
-                                                       
$("#total_records").html(components_data.total_records);
-                                                       
$("#sum_text").html('Sum');
-                                                       
$("#month0").html(time_sum[0] + '/' + time_sum_actual[0]);
-                                                       
$("#month1").html(time_sum[1] + '/' + time_sum_actual[1]);
-                                                       
$("#month2").html(time_sum[2] + '/' + time_sum_actual[2]);
-                                                       
$("#month3").html(time_sum[3] + '/' + time_sum_actual[3]);
-                                                       
$("#month4").html(time_sum[4] + '/' + time_sum_actual[4]);
-                                                       
$("#month5").html(time_sum[5] + '/' + time_sum_actual[5]);
-                                                       
$("#month6").html(time_sum[6] + '/' + time_sum_actual[6]);
-                                                       
$("#month7").html(time_sum[7] + '/' + time_sum_actual[7]);
-                                                       
$("#month8").html(time_sum[8] + '/' + time_sum_actual[8]);
-                                                       
$("#month9").html(time_sum[9] + '/' + time_sum_actual[9]);
-                                                       
$("#month10").html(time_sum[10] + '/' + time_sum_actual[10]);
-                                                       
$("#month11").html(time_sum[11] + '/' + time_sum_actual[11]);
-                                                       
$("#month12").html(time_sum[12] + '/' + time_sum_actual[12]);
-                                               }
-
-                                               if(summary_data !== null)
-                                               {
-                                                       $( "#status_summary" 
).show();
-                                                       $( "#components" 
).hide();
-                                                       $( 
"#status_summary").html(summary_data);
-                                               }
-                                               else
-                                               {
-                                                       $( "#status_summary" 
).hide();
-                                                       $( "#components" 
).show();
-
-                                               }
-                                       }
-
-                               }
-                       });
-
-               };
-
-               add_from_master = function(myclass)
-               {
-                       var myRadio = $('input[name=master_component]');
-                       var master_component = myRadio.filter(':checked').val();
-
-                       if(!master_component)
-                       {
-                               alert('velg master');
-                               return;
-                       }
-
-                       var selected  = new Array();
-
-                       $("." + myclass).each(function()
-                       {
-                               if($(this).prop("checked"))
-                               {
-                                       selected.push( $(this).val() );
-                               }
-                       });
-
-                       oArgs = {menuaction: 
'controller.uicomponent.add_controll_from_master'};
-                       var requestUrl = phpGWLink('index.php', oArgs, true);
-
-                       $.ajax({
-                               type: 'POST',
-                               data: {master_component:master_component, 
target:selected},
-                               dataType: 'json',
-                               url: requestUrl,
-                               success: function(data) {
-                                       if( data != null)
-                                       {
-//console.log(data);
-                                               var message = data.message;
-
-                                               htmlString = "";
-                                               var msg_class = "msg_good";
-                                               if(data.status =='error')
-                                               {
-                                                       msg_class = "error";
-                                               }
-                                               htmlString += "<div class=\"" + 
msg_class + "\">";
-                                               htmlString += message;
-                                               htmlString += '</div>';
-                                               update_table();
-                                               $("#receipt").html(htmlString);
-
-                                       }
-                               }
-                       });
-
-               };
-
-               checkAll = function(myclass)
-               {
-                       $("." + myclass).each(function()
-                       {
-                               if($(this).prop("checked"))
-                               {
-                                       $(this).prop("checked", false);
-                               }
-                               else
-                               {
-                                       $(this).prop("checked", true);
-                               }
-                       });
-               };
-
-]]>
-       </script>
        <table id="components">
                <thead>
                        <tr>

Modified: branches/Version-2_0-branch/helpdesk/inc/class.uitts.inc.php
===================================================================
--- branches/Version-2_0-branch/helpdesk/inc/class.uitts.inc.php        
2016-09-30 07:03:33 UTC (rev 15764)
+++ branches/Version-2_0-branch/helpdesk/inc/class.uitts.inc.php        
2016-09-30 07:11:26 UTC (rev 15765)
@@ -759,8 +759,8 @@
                                'action' => 
$GLOBALS['phpgw']->link('/index.php', array
                                        (
                                        'menuaction' => 'helpdesk.uitts._print',
-                                       'target' => '_blank'
                                )),
+                               'target' => '_blank',
                                'parameters' => json_encode($parameters)
                        );
 
@@ -778,8 +778,8 @@
                                                        (
                                                        'menuaction' => 
'helpdesk.uijasper.view',
                                                        'jasper_id' => 
$report['id'],
-                                                       'target' => '_blank'
                                                )),
+                                               'target' => '_blank',
                                                'parameters' => 
json_encode($parameters)
                                        );
                                }

Modified: branches/Version-2_0-branch/phpgwapi/inc/class.jquery.inc.php
===================================================================
--- branches/Version-2_0-branch/phpgwapi/inc/class.jquery.inc.php       
2016-09-30 07:03:33 UTC (rev 15764)
+++ branches/Version-2_0-branch/phpgwapi/inc/class.jquery.inc.php       
2016-09-30 07:11:26 UTC (rev 15765)
@@ -182,7 +182,24 @@
                                        );
                                                
$GLOBALS['phpgw']->css->add_external_file("phpgwapi/js/contextMenu/jquery.contextMenu.min.css");
                                        break;
-
+                               
+                               case 'file-upload':
+                                       $load = array
+                                               (
+                                               "js/{$_jquery_core}{$_type}",
+                                               "js/{$_jquery_ui}{$_type}",
+                                               "file-upload/js/tmpl{$_type}",
+                                               
"file-upload/js/jquery.fileupload",
+                                               
"file-upload/js/jquery.fileupload-process",
+                                               
"file-upload/js/jquery.fileupload-validate",
+                                               
"file-upload/js/jquery.fileupload-ui",
+                                               
"file-upload/js/jquery.fileupload-jquery-ui",
+                                       );
+                                               
$GLOBALS['phpgw']->css->add_external_file("phpgwapi/js/jquery/file-upload/css/jquery.fileupload.css");
+                                               
$GLOBALS['phpgw']->css->add_external_file("phpgwapi/js/jquery/file-upload/css/jquery.fileupload-custom.css");
+                                               
$GLOBALS['phpgw']->css->add_external_file("phpgwapi/js/jquery/file-upload/css/jquery.fileupload-ui.css");
+                                       break;
+                               
                                default:
                                        $err = "Unsupported jQuery widget '%1' 
supplied to phpgwapi_jquery::load_widget()";
                                        trigger_error(lang($err, $widget), 
E_USER_WARNING);
@@ -467,4 +484,133 @@
 JS;
                        $GLOBALS['phpgw']->js->add_code('', $js);
                }
+               
+               public static function form_file_upload_generate( $action )
+               {
+                       self::load_widget('file-upload');
+                       $output = <<<HTML
+                       <form id="fileupload" action="{$action}" method="POST" 
enctype="multipart/form-data">
+                               <!-- The fileupload-buttonbar contains buttons 
to add/delete files and start/cancel the upload -->
+                               <div class="fileupload-buttonbar">
+                                       <div class="fileupload-buttons">
+                                               <!-- The fileinput-button span 
is used to style the file input field as button -->
+                                               <span class="fileinput-button 
pure-button">
+                                                       <span>Add 
files...</span>
+                                                       <input type="file" 
id="files" name="files[]" multiple>
+                                               </span>
+                                               <button type="submit" 
class="start pure-button">Start upload</button>
+                                               <button type="reset" 
class="cancel pure-button">Cancel upload</button>
+                                               <button type="button" 
class="delete pure-button">Delete</button>
+                                               <input type="checkbox" 
class="toggle">
+                                               <!-- The global file processing 
state -->
+                                               <span 
class="fileupload-process"></span>
+                                       </div>
+                                       <div class="fileupload-progress fade" 
style="display:none">
+                                               <!-- The global progress bar -->
+                                               <div class="progress" 
role="progressbar" aria-valuemin="0" aria-valuemax="100"></div>
+                                               <!-- The extended global 
progress state -->
+                                               <div 
class="progress-extended">&nbsp;</div>
+                                       </div>
+                               </div>
+                               <!-- The table listing the files available for 
upload/download -->
+                               <div style="position: relative; overflow: auto; 
max-height: 50vh; width: 100%;">                                        
+                                       <div class="presentation files" 
style="display: inline-table;"></div>
+                               </div>
+                       
+                       </form>
+
+                       <!-- The template to display files available for upload 
-->
+                       <script id="template-upload" type="text/x-tmpl">
+                       {% for (var i=0, file; file=o.files[i]; i++) { %}
+                               <div class="template-upload fade table-row">
+                                       <div class="table-cell">
+                                               <div 
class="name">{%=file.name%}</div>
+                                               <div class="error"></div>
+                                       </div>
+                                       <div class="table-cell">
+                                               <div 
class="size">Processing...</div>
+                                       </div>
+                                       <div class="table-cell">
+                                               <div class="progress" 
style="width: 100px;"></div>
+                                       </div>
+                                       <div class="table-cell">
+                                               {% if (!i && 
!o.options.autoUpload) { %}
+                                                       <button class="start 
pure-button" disabled>Start</button>
+                                               {% } %}
+                                               {% if (!i) { %}
+                                                       <button class="cancel 
pure-button">Cancel</button>
+                                               {% } %}
+                                       </div>
+                               </div>
+                       {% } %}
+                       </script>
+                       <!-- The template to display files available for 
download -->
+                       <script id="template-download" type="text/x-tmpl">
+                       {% for (var i=0, file; file=o.files[i]; i++) { %}
+                               <div class="template-download fade table-row">
+                                       <div class="table-cell">                
                                
+                                               <div class="name">
+                                                       <!--<a 
href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" 
{%=file.thumbnailUrl?'data-gallery':''%}>{%=file.name%}</a>-->
+                                                       {%=file.name%}          
                                        
+                                               </div>
+                                               {% if (file.error) { %} <div 
class="error">Error: {%=file.error%} </div>{% } %}
+                                       </div>
+                                       <div class="table-cell">
+                                               <div 
class="size">{%=o.formatFileSize(file.size)%}</div>
+                                       </div>
+                                       <div class="table-cell">
+                                               <button class="delete 
pure-button" data-type="{%=file.deleteType%}" data-url="{%=file.deleteUrl%}"{% 
if (file.deleteWithCredentials) { %} 
data-xhr-fields='{"withCredentials":true}'{% } %}>Delete</button>
+                                               <input type="checkbox" 
name="delete" value="1" class="toggle">
+                                       </div>
+                               </div>
+                       {% } %}
+                       </script>
+HTML;
+                       
+                       $js = <<<JS
+                                       
+               $(function () {
+                       'use strict';
+                                       
+                       // Initialize the jQuery File Upload widget:
+                       $('#fileupload').fileupload({
+                               // Uncomment the following to send cross-domain 
cookies:
+                               //xhrFields: {withCredentials: true},
+                               url: '{$action}',
+                               limitConcurrentUploads: 4,
+                               //acceptFileTypes: /(\.|\/)(png|pdf)$/i
+                       });
+                               
+                       // Enable iframe cross-domain access via redirect 
option:
+                       $('#fileupload').fileupload(
+                               'option',
+                               'redirect',
+                               window.location.href.replace(
+                                       /\/[^\/]*$/,
+                                       '/cors/result.html?%s'
+                               )
+                       );
+                               
+                       // Load existing files:
+                       $('#fileupload').addClass('fileupload-processing');
+                       $.ajax({
+                               // Uncomment the following to send cross-domain 
cookies:
+                               //xhrFields: {withCredentials: true},
+                               url: $('#fileupload').fileupload('option', 
'url'),
+                               dataType: 'json',
+                               context: $('#fileupload')[0]
+                       }).always(function () {
+                               $(this).removeClass('fileupload-processing');
+                       }).done(function (result) {
+                               $(this).fileupload('option', 'done')
+                                       .call(this, $.Event('done'), {result: 
result});
+                       });
+
+               });
+JS;
+                       $GLOBALS['phpgw']->js->add_code('', $js);
+                       
+                       return $output;
+               }
+               
        }
\ No newline at end of file

Modified: branches/Version-2_0-branch/phpgwapi/inc/class.uicommon_jquery.inc.php
===================================================================
--- branches/Version-2_0-branch/phpgwapi/inc/class.uicommon_jquery.inc.php      
2016-09-30 07:03:33 UTC (rev 15764)
+++ branches/Version-2_0-branch/phpgwapi/inc/class.uicommon_jquery.inc.php      
2016-09-30 07:11:26 UTC (rev 15765)
@@ -185,11 +185,17 @@
                public function link( $data )
                {
                        if ($GLOBALS['phpgw_info']['flags']['currentapp'] == 
'bookingfrontend')
+                       {
                                return 
$GLOBALS['phpgw']->link('/bookingfrontend/', $data);
-                       elseif ($GLOBALS['phpgw_info']['flags']['currentapp'] 
== 'activitycalendarfrontend')
+                       }
+                       else if ($GLOBALS['phpgw_info']['flags']['currentapp'] 
== 'activitycalendarfrontend')
+                       {
                                return 
$GLOBALS['phpgw']->link('/activitycalendarfrontend/', $data);
+                       }
                        else
+                       {
                                return $GLOBALS['phpgw']->link('/index.php', 
$data);
+                       }
                }
 
                public function redirect( $link_data )

Modified: branches/Version-2_0-branch/phpgwapi/js/jquery/common.js
===================================================================
--- branches/Version-2_0-branch/phpgwapi/js/jquery/common.js    2016-09-30 
07:03:33 UTC (rev 15764)
+++ branches/Version-2_0-branch/phpgwapi/js/jquery/common.js    2016-09-30 
07:11:26 UTC (rev 15765)
@@ -181,10 +181,10 @@
 };
 
 //JqueryPortico.formatCheckEvent = function(key, oData) {
-//     
-//        var hidden = '';
-//        
-//        return hidden + "<center><input type=\"checkbox\" class=\"mychecks\" 
 name=\"values[events]["+oData['id']+"_"+oData['schedule_time']+"]\" 
value=\""+oData['id']+"\"/></center>";
+//     
+//             var hidden = '';
+//             
+//             return hidden + "<center><input type=\"checkbox\" 
class=\"mychecks\"  
name=\"values[events]["+oData['id']+"_"+oData['schedule_time']+"]\" 
value=\""+oData['id']+"\"/></center>";
 //}
 
 JqueryPortico.formatCheckUis_agremment = function (key, oData)
@@ -604,6 +604,11 @@
                url: requestUrl,
                success: function (result)
                {
+                       if (typeof (result.sessionExpired) !== 'undefined')
+                       {
+                               alert('sessionExpired - please log in');
+                               return;
+                       }
                        callback(result);
                }
        });
@@ -1273,26 +1278,14 @@
 }
 
 
-function createTableSchedule(d, u, c, r, cl, dt)
+function createTableSchedule (d, u, c, r, cl, a, p, t)
 {
-//     var detected_lang = navigator.language || navigator.userLanguage;
-       var lang = {};
-
-//     if(detected_lang == 'no' || detected_lang == 'nn' || detected_lang == 
'nb' ||detected_lang == 'nb-no' || detected_lang == 'no-no' || detected_lang == 
'nn-no')
-       if (window.navigator.language != "en")
-       {
-               lang = {free: 'Ledig'};
-       }
-       else
-       {
-               lang = {free: 'free'};
-       }
-
        var container = document.getElementById(d);
+       var container_toolbar = document.createElement('div');
        var xtable = document.createElement('table');
        var tableHead = document.createElement('thead');
        var tableHeadTr = document.createElement('tr');
-       var date = (dt) ? dt : "";
+       var date = (a) ? (a.date) ? a.date : "" : "";
 
        restartColors();
        r = (r) ? r : 'data';
@@ -1310,6 +1303,8 @@
        tableHead.appendChild(tableHeadTr);
        xtable.appendChild(tableHead);
 
+       var key = c[0].key;
+
        var tableBody = document.createElement('tbody');
        var tableBodyTr = document.createElement('tr');
        var tableBodyTrTd = document.createElement('td');
@@ -1320,9 +1315,10 @@
        xtable.appendChild(tableBody);
 
        container.innerHTML = "";
+       container.appendChild(container_toolbar);
        container.appendChild(xtable);
 
-       $.get(u, function (data)
+       $.post(u, a, function (data)
        {
                var selected = new Array();
                if (typeof (r) == 'object')
@@ -1361,9 +1357,10 @@
                                $.each(c, function (ic, vc)
                                {
                                        var k = vc.key;
-                                       var colorCell = "";
-                                       var tableBodyTrTdType = (k == "time") ? 
"th" : "td";
 
+//                                     var tableBodyTrTdType = (k == key) ? 
"th" : "td";
+                                       var tableBodyTrTdType = (vc['type']) ? 
(vc['type'] == "th") ? "th" : "td" : "td";
+
                                        var tableBodyTrTd = 
document.createElement(tableBodyTrTdType);
 
                                        var classes = "";
@@ -1371,99 +1368,42 @@
 
                                        if (vc['formatter'])
                                        {
-                                               if (vc['formatter'] == 
"scheduleResourceColumn")
+                                               //var dataFormat = {};
+                                               var dataFormat = 
setFormatter(vc['formatter'], vd, vc, date)
+
+                                               if (dataFormat['text'])
                                                {
-                                                       if (vd[k])
+                                                       tableBodyTrTdText = 
dataFormat['text'];
+                                               }
+
+                                               if (dataFormat['classes'])
+                                               {
+                                                       classes += " " + 
dataFormat['classes'];
+                                               }
+
+                                               if (dataFormat['trAttributes'])
+                                               {
+                                                       
$.each(dataFormat['trAttributes'], function (i, v)
                                                        {
-                                                               
tableBodyTr.setAttribute('resource', vd['resource_id']);
-                                                       }
-                                                       var resourceLink = 
(date) ? vd['resource_link'] + "#date=" + date : vd['resource_link'];
-                                                       tableBodyTrTdText = 
(vd[k]) ? formatGenericLink(vd['resource'], resourceLink) : "";
+                                                               
tableBodyTr.setAttribute(v['attribute'], v['value']);
+                                                       });
                                                }
-                                               else
+
+                                               if (dataFormat['trFunction'])
                                                {
-                                                       if (vd[k])
+                                                       
$.each(dataFormat['trFunction'], function (i, v)
                                                        {
-                                                               var id = 
vd[k]['id'];
-                                                               var name = 
(vd[k]['shortname']) ? formatScheduleShorten(vd[k]['shortname'], 9) : 
formatScheduleShorten(vd[k]['name'], 9);
-                                                               var type = 
vd[k]['type'];
-                                                               if 
(vc['formatter'] == "seasonDateColumn")
-                                                               {
-                                                                       
tableBodyTrTdText = name;
-                                                                       
tableBodyTrTd.addEventListener('click', function ()
-                                                                       {
-                                                                               
schedule.newAllocationForm({'id': vd[k]['id']})
-                                                                       });
-                                                               }
-                                                               if 
(vc['formatter'] == "scheduleDateColumn")
-                                                               {
-                                                                       
tableBodyTrTdText = formatGenericLink(name, null);
-                                                               }
-                                                               if 
(vc['formatter'] == "backendScheduleDateColumn")
-                                                               {
-                                                                       var 
conflicts = new Array();
-                                                                       if 
(vd[k]['conflicts'])
-                                                                       {
-                                                                               
if (vd[k]['conflicts'].length > 0)
-                                                                               
{
-                                                                               
        conflicts = vd[k]['conflicts'];
-                                                                               
}
-                                                                       }
-                                                                       
tableBodyTrTdText = formatBackendScheduleDateColumn(id, name, type, conflicts);
-                                                                       classes 
+= " " + type;
-                                                               }
-                                                               if 
(vc['formatter'] == "frontendScheduleDateColumn")
-                                                               {
-                                                                       if 
(vd[k]['is_public'] == 0)
-                                                                       {
-                                                                               
name = formatScheduleShorten('Privat arr.', 9);
-                                                                       }
-                                                                       
tableBodyTrTdText = name;
-                                                                       classes 
+= " cellInfo";
-                                                                       classes 
+= " " + type;
-                                                                       
tableBodyTrTd.addEventListener('click', function ()
-                                                                       {
-                                                                               
schedule.showInfo(vd[k]['info_url'], tableBodyTr.getAttribute('resource'))
-                                                                       }, 
false);
-                                                               }
-                                                               colorCell = 
formatScheduleCellDateColumn(name, type);
-                                                               classes += " " 
+ colorCell;
-                                                               
tableBodyTrTd.setAttribute('class', classes);
-                                                       }
-                                                       else
-                                                       {
-                                                               
tableBodyTrTdText = lang.free;
-                                                               classes += " 
free";
-                                                               
tableBodyTrTd.setAttribute('class', classes);
-                                                               if 
(vc['formatter'] == "frontendScheduleDateColumn")
-                                                               {
-                                                                       
tableBodyTrTd.addEventListener('click', function ()
-                                                                       {
-                                                                               
schedule.newApplicationForm(vc['date'], vd['_from'], vd['_to'], 
tableBodyTr.getAttribute('resource'))
-                                                                       });
-                                                               }
-                                                               if 
(vc['formatter'] == "backendScheduleDateColumn")
-                                                               {
-                                                                       
tableBodyTrTd.addEventListener('click', function ()
-                                                                       {
-                                                                               
schedule.newApplicationForm(vc['date'], vd['_from'], vd['_to'])
-                                                                       });
-                                                               }
-                                                               if 
(vc['formatter'] == "seasonDateColumn")
-                                                               {
-                                                                       
tableBodyTrTd.addEventListener('click', function ()
-                                                                       {
-                                                                               
schedule.newAllocationForm({'_from': vd['_from'], '_to': vd['_to'], 'wday': 
vc['key']})
-                                                                       });
-                                                               }
-                                                       }
+                                                               
tableBodyTrTd.addEventListener(v['event'], v['callFunction'], false);
+                                                       });
                                                }
+
+                                               
tableBodyTrTd.setAttribute('class', classes);
                                        }
                                        else
                                        {
-                                               tableBodyTrTdText = (vd[k]) ? 
vd[k] : "";
+                                               tableBodyTrTdText = (vd[k]) ? 
(vc['value']) ? vd[k][vc['value']] : (vd[k]) : "";
                                        }
-                                       if (k == "time")
+                                       if (k == key)
                                        {
                                                borderTop = (vd[k]) ? "2" : "1";
                                        }
@@ -1482,10 +1422,517 @@
                                });
                                tableBody.appendChild(tableBodyTr);
                        });
+
+                       if (p)
+                       {
+                               var start = a.start;
+                               var total = 
data['ResultSet'].totalResultsAvailable;
+                               var n_objects = a.length;
+                               start = (start > total) ? 0 : start;
+
+                               var pages = Math.floor(total / n_objects);
+                               var res = total % n_objects;
+                               var page = (start == 0) ? 1 : (start / 
n_objects) + 1;
+
+                               pages = (res > 0) ? pages+1 : pages;
+                               pages = (pages == 0) ? pages+1 : pages;
+
+                               var paginator = createPaginatorSchedule(pages, 
page);
+                               container.appendChild(paginator);
+
+                               var input_start = 
document.createElement('input');
+                               input_start.setAttribute('type', 'hidden');
+                               input_start.setAttribute('name', 'start_index');
+                               input_start.setAttribute('id', 'start_index');
+                               input_start.value = start;
+                               container.appendChild(input_start);
+                       }
+
+                       if (t)
+                       {
+                               var toolbar = eval(t + "()");
+                               container_toolbar.appendChild(toolbar);
+//                             container.insertBefore(toolbar, xtable);
+                       }
                }
        });
 }
 
+// p -> n pages
+// a -> current page
+function createPaginatorSchedule (p, a)
+{
+       var max = 7;
+       var m = 4;
+
+       var ini = 1;
+       var end = p;
+
+       var buttons = new Array();
+       var n_button = "";
+       var old_button = "";
+
+       for (i = ini; i <= end; i++)
+       {
+               if (i == ini)
+               {
+                       n_button = i;
+               }
+               else if ( (a - ini < m ) && (i <= ini + m) )
+               {
+                       n_button = i;
+               }
+               else if ( (i >= a - 1) && (i <= a + 1) )
+               {
+                       n_button = i;
+               }
+               else if ( (end - a < m ) && (i >= end - m) )
+               {
+                       n_button = i;
+               }
+               else if (i == end)
+               {
+                       n_button = i;
+               }
+               else
+               {
+                       n_button = "...";
+               }
+               if (n_button != old_button)
+               {
+                       buttons.push(n_button);
+                       old_button = n_button;
+               }
+       }
+
+       var container = document.createElement('div');
+       container.classList.add('schedule_paginate');
+       container.id = "schedule-container_paginate";
+
+       var paginatorPrevButton = document.createElement('a');
+       var paginatorNextButton = document.createElement('a');
+
+       paginatorPrevButton.classList.add('paginate_button', 'previous');
+       paginatorNextButton.classList.add('paginate_button', 'next');
+
+       paginatorPrevButton.innerHTML = "Prev";
+       paginatorNextButton.innerHTML = "Next";
+
+       if (a > 1)
+       {
+               paginatorPrevButton.dataset.page = (a - 1);
+       }
+       else
+       {
+               paginatorPrevButton.classList.add('disabled');
+       }
+       if (a < p)
+       {
+               paginatorNextButton.dataset.page = (a + 1);
+       }
+       else
+       {
+               paginatorNextButton.classList.add('disabled');
+       }
+
+       container.appendChild(paginatorPrevButton);
+       var button_class = "paginate_button";
+       $.each(buttons, function (i, v)
+       {
+               button_class = "paginate_button"
+               var button = document.createElement('span');
+               if (v == "...")
+               {
+                       button_class = 'ellipsis';
+               }
+               button.classList.add(button_class);
+               button.dataset.page = v;
+               if (v == a)
+               {
+                       button.classList.add('current');
+               }
+               button.innerHTML = v;
+               container.appendChild(button);
+       });
+       container.appendChild(paginatorNextButton);
+
+       return container;
+}
+
+function setFormatter (callFunc, data, col, date)
+{
+       return eval(callFunc+'(data,col,date)');
+}
+
+function scheduleResourceColumn (data, col, date)
+{
+       var text = "";
+       var classes = "";
+       var trAttributes = [];
+       var trFunction = [];
+
+       var k = col.key;
+
+       if (data[k])
+       {
+               trAttributes.push( {attribute: 'resource', value: 
data['resource_id']} );
+       }
+
+       var resourceLink = (date) ? data['resource_link'] + "#date=" + date : 
data['resource_link'];
+       text = (data[k]) ? formatGenericLink(data['resource'], resourceLink) : 
"";
+
+       var data_return = {
+               text: text,
+               classes: classes,
+               trAttributes: trAttributes,
+               trFunction: trFunction
+       }
+
+       return data_return;
+}
+
+function seasonDateColumn (data, col, date)
+{
+       var text = "";
+       var classes = "";
+       var trAttributes = [];
+       var trFunction = [];
+
+       var k = col.key;
+
+       if (data[k])
+       {
+               var id = data[k]['id'];
+               var name = (data[k]['shortname']) ? 
formatScheduleShorten(data[k]['shortname'], 9) : 
formatScheduleShorten(data[k]['name'], 9);
+               var type = data[k]['type'];
+               var colorCell = formatScheduleCellDateColumn(name, type);
+
+               text = name;
+               classes = colorCell;
+               trFunction.push(
+                       {
+                               event: 'click',
+                               callFunction: function () {
+//                                     schedule.newAllocationForm({id: 
data[k]['id']});
+                                       schedule.newAllocationForm({id: id});
+                               }
+                       }
+               );
+       }
+       else
+       {
+               text = "free";
+               classes = "free";
+               trFunction.push(
+                       {
+                               event: 'click',
+                               callFunction: function () {
+                                       schedule.newAllocationForm({'_from': 
data['_from'], '_to': data['_to'], 'wday': col['key']});
+                               }
+                       }
+               );
+       }
+
+       var data_return = {
+               text: text,
+               classes: classes,
+               trAttributes: trAttributes,
+               trFunction: trFunction
+       }
+
+       return data_return;
+}
+
+function scheduleDateColumn (data, col, date)
+{
+       var text = "";
+       var classes = "";
+       var trAttributes = [];
+       var trFunction = [];
+
+       var k = col.key;
+
+       if (data[k])
+       {
+               var name = (data[k]['shortname']) ? 
formatScheduleShorten(data[k]['shortname'], 9) : 
formatScheduleShorten(data[k]['name'], 9);
+               var type = data[k]['type'];
+               var colorCell = formatScheduleCellDateColumn(name, type);
+
+               text = formatGenericLink(name, null);
+               classes = colorCell;
+       }
+
+       var data_return = {
+               text: text,
+               classes: classes,
+               trAttributes: trAttributes,
+               trFunction: trFunction
+       }
+
+       return data_return;
+}
+
+function backendScheduleDateColumn (data, col, date)
+{
+       var text = "";
+       var classes = "";
+       var trAttributes = [];
+       var trFunction = [];
+
+       var k = col.key;
+
+       if (data[k])
+       {
+               var id = data[k]['id'];
+               var name = (data[k]['shortname']) ? 
formatScheduleShorten(data[k]['shortname'], 9) : 
formatScheduleShorten(data[k]['name'], 9);
+               var type = data[k]['type'];
+               var colorCell = formatScheduleCellDateColumn(name, type);
+
+               var conflicts = new Array();
+
+               if (data[k]['conflicts'])
+               {
+                       if (data[k]['conflicts'].length > 0)
+                       {
+                               conflicts = data[k]['conflicts'];
+                       }
+               }
+               text = formatBackendScheduleDateColumn(id, name, type, 
conflicts);
+               classes = colorCell + " " + type;
+       }
+       else
+       {
+               text = "free";
+               classes = "free";
+               trFunction.push(
+                       {
+                               event: 'click',
+                               callFunction: function () {
+                                       
schedule.newApplicationForm(col['date'], data['_from'], data['_to'])
+                               }
+                       }
+               )
+       }
+
+       var data_return = {
+               text: text,
+               classes: classes,
+               trAttributes: trAttributes,
+               trFunction: trFunction
+       }
+
+       return data_return;
+}
+
+function frontendScheduleDateColumn (data, col, date)
+{
+       var text = "";
+       var classes = "";
+       var trAttributes = [];
+       var trFunction = [];
+
+       var k = col.key;
+
+       if (data[k])
+       {
+               var name = (data[k]['shortname']) ? 
formatScheduleShorten(data[k]['shortname'], 9) : 
formatScheduleShorten(data[k]['name'], 9);
+               var type = data[k]['type'];
+               var colorCell = formatScheduleCellDateColumn(name, type);
+
+               if (data[k]['is_public'] == 0)
+               {
+                       name = formatScheduleShorten('Privat arr.', 9);
+               }
+
+               text = name;
+               classes = "cellInfo " + colorCell + " " + type ;
+               trFunction.push(
+                       {
+                               event: 'click',
+                               callFunction: function () {
+                                       var resource = 
$(this).parent().attr('resource');
+                                       schedule.showInfo(data[k]['info_url'], 
resource);
+                               }
+                       }
+               );
+       }
+       else
+       {
+               text = "free";
+               classes = "free";
+               trFunction.push(
+                       {
+                               event: 'click',
+                               callFunction: function () {
+                                       var resource = 
$(this).parent().attr('resource');
+                                       
schedule.newApplicationForm(col['date'], data['_from'], data['_to'], resource);
+                               }
+                       }
+               );
+       }
+
+       var data_return = {
+               text: text,
+               classes: classes,
+               trAttributes: trAttributes,
+               trFunction: trFunction
+       }
+
+       return data_return;
+}
+
+function rentalSchedule (data, col, date)
+{
+       var text = "";
+       var classes = "";
+       var trAttributes = [];
+       var trFunction = [];
+
+       var k = col.key;
+
+       var needFree = true;
+       if (data[k])
+       {
+               text = data[k]['status'];
+               if (text == "Ikke ledig")
+               {
+                       needFree = false;
+               }
+       }
+       else
+       {
+               text = "free";
+               classes = "free";
+       }
+
+       trAttributes.push( {attribute: 'data-id', value: data['id']} );
+       trFunction.push(
+               {
+                       event: 'click',
+                       callFunction: function () {
+                               
$(this).parent().parent().find('tr').removeClass("trselected")
+                               $(this).parent().addClass("trselected");
+                               $('#schedule_toolbar button').attr('disabled', 
false);
+                               var b_needFree = eval(needFree);
+                               if (!b_needFree)
+                               {
+                                       $('#schedule_toolbar 
button.need-free').attr('disabled', true);
+                               }
+                               schedule.rental.data = data;
+                               schedule.rental.col = col;
+                       }
+               }
+       );
+
+       var data_return = {
+               text: text,
+               classes: classes,
+               trAttributes: trAttributes,
+               trFunction: trFunction
+       }
+
+       return data_return;
+}
+
+function rentalScheduleApplication (data, col, date)
+{
+       var text = "";
+       var classes = "";
+       var trAttributes = [];
+       var trFunction = [];
+       
+       var validate = false;
+       
+       if ( (schedule.rental.availability_from) && 
(schedule.rental.availability_to) ){
+               if (col.date >= schedule.rental.availability_from && col.date 
<= schedule.rental.availability_to){
+                       validate = true;
+               }
+       }
+       
+       if (validate)
+       {
+               var k = col.key;
+
+               var needFree = true;
+               if (data[k])
+               {
+                       text = data[k]['status'];
+                       if (text == "Ikke ledig")
+                       {
+                               needFree = false;
+                       }
+               }
+               else
+               {
+                       text = "free";
+                       classes = "free";
+               }
+
+               trAttributes.push( {attribute: 'data-id', value: data['id']} );
+               trFunction.push(
+                       {
+                               event: 'click',
+                               callFunction: function () {
+                                       
$(this).parent().parent().find('tr').removeClass("trselected")
+                                       $(this).parent().addClass("trselected");
+                                       $('#schedule_toolbar 
button').attr('disabled', false);
+                                       var b_needFree = eval(needFree);
+                                       if (!b_needFree)
+                                       {
+                                               $('#schedule_toolbar 
button.need-free').attr('disabled', true);
+                                       }
+                                       schedule.rental.data = data;
+                                       schedule.rental.col = col;
+                               }
+                       }
+               );
+       }
+
+       var data_return = {
+               text: text,
+               classes: classes,
+               trAttributes: trAttributes,
+               trFunction: trFunction
+       }
+
+       return data_return;
+}
+
+function rentalScheduleComposites (data, col, date)
+{
+       var text = "";
+       var classes = "";
+       var trAttributes = [];
+       var trFunction = [];
+
+       var k = col.key;
+       
+       text = data[k];
+
+       trAttributes.push( {attribute: 'data-id', value: data['id']} );
+       trFunction.push(
+               {
+                       event: 'click',
+                       callFunction: function () {
+                               
$(this).parent().parent().find('tr').removeClass("trselected")
+                               $(this).parent().addClass("trselected");
+                               $('#composites_toolbar 
button').attr('disabled', false);
+                               composites.rental.data = data;
+                               composites.rental.col = col;
+                       }
+               }
+       );
+
+       var data_return = {
+               text: text,
+               classes: classes,
+               trAttributes: trAttributes,
+               trFunction: trFunction
+       }
+
+       return data_return;
+}
+
 function restartColors()
 {
        colors = [
@@ -1508,6 +1955,7 @@
        var color = colorMap[name];
        return color;
 }
+
 function formatBackendScheduleDateColumn(id, name, type, conflicts)
 {
        var link = "";
@@ -1536,6 +1984,7 @@
        }
        return text;
 }
+
 function formatFrontendScheduleDateColumn()
 {
 }
@@ -1585,8 +2034,6 @@
        return decodeURIComponent(string.replace(/\+/g, ' '));
 }
 
-
-
 function genericLink()
 {
        var data = [];
@@ -1594,6 +2041,7 @@
        data['type'] = 'genericLink';
        return data;
 }
+
 function genericLink2()
 {
        var data = [];
@@ -1602,7 +2050,6 @@
        return data;
 }
 
-// nl = numero links
 function formatGenericLink(name, link)
 {
        if (!name || !link)
@@ -1614,6 +2061,7 @@
                return "<a href='" + link + "'>" + name + "</a>";
        }
 }
+
 function formatGenericLink2(name, link)
 {
        if (!name || !link)
@@ -1625,3 +2073,16 @@
                return "<a onclick='return confirm(\"Er du sikker pÄ at du vil 
slette denne?\")' href='" + link + "'>" + name + "</a>";
        }
 }
+
+parseISO8601 = function (string)
+{
+       var regexp = "(([0-9]{4})(-([0-9]{1,2})(-([0-9]{1,2}))))?( 
)?(([0-9]{1,2}):([0-9]{1,2}))?";
+       var d = string.match(new RegExp(regexp));
+       var year = d[2] ? (d[2] * 1) : 0;
+       date = new Date(year, (d[4] || 1) - 1, d[6] || 0);
+       if (d[9])
+               date.setHours(d[9]);
+       if (d[10])
+               date.setMinutes(d[10]);
+       return date;
+};
\ No newline at end of file

Modified: branches/Version-2_0-branch/property/inc/class.bolocation.inc.php
===================================================================
--- branches/Version-2_0-branch/property/inc/class.bolocation.inc.php   
2016-09-30 07:03:33 UTC (rev 15764)
+++ branches/Version-2_0-branch/property/inc/class.bolocation.inc.php   
2016-09-30 07:11:26 UTC (rev 15765)
@@ -56,7 +56,8 @@
                        'read_single' => true,
                        'save' => true,
                        'delete' => true,
-                       'get_locations_by_name' => true
+                       'get_locations_by_name' => true,
+                       'get_locations' => true
                );
 
                function __construct( $session = false )
@@ -1092,8 +1093,7 @@
                 */
                public function get_locations_by_name()
                {
-                       $data = array
-                               (
+                       $data = array(
                                'level' => phpgw::get_var('level', 'int'),
                                'location_name' => 
phpgw::get_var('location_name')
                        );
@@ -1135,4 +1135,29 @@
                {
                        return $this->so->get_item_id($location_code);
                }
+
+               public function get_locations(  )
+               {
+                       $location_code = phpgw::get_var('query');
+                       $_level = count(explode('-', $location_code)) + 1;
+
+                       $values = $this->so->get_locations($location_code);
+                       if($values)
+                       {
+                               $part = explode('-', $values[0]['id']);
+                               $parent_level = count($part);
+                               $_loc_arr = array();
+                               for ($i = 0; $i < ($parent_level -1); $i++)
+                               {
+                                       $_loc_arr[] = $part[$i];
+                               }
+                               $parent_location_code = implode('-', $_loc_arr);
+                               if($parent_location_code)
+                               {
+                                       array_unshift($values, array('id' => 
$parent_location_code, 'name' => $parent_location_code . '::' . 
$this->get_location_name($parent_location_code)));
+                               }
+                       }
+                       return array('ResultSet' => array('Result' => $values));
+
+               }
        }
\ No newline at end of file

Modified: branches/Version-2_0-branch/property/inc/class.menu.inc.php
===================================================================
--- branches/Version-2_0-branch/property/inc/class.menu.inc.php 2016-09-30 
07:03:33 UTC (rev 15764)
+++ branches/Version-2_0-branch/property/inc/class.menu.inc.php 2016-09-30 
07:11:26 UTC (rev 15765)
@@ -519,6 +519,11 @@
                                                'text' => lang('Generic 
import'),
                                                'url' => 
$GLOBALS['phpgw']->link('/index.php', array('menuaction' => 
'property.uiimport.index'))
                                        ),
+                                       'import_components' => array
+                                               (
+                                               'text' => lang('import 
components'),
+                                               'url' => 
$GLOBALS['phpgw']->link('/index.php', array('menuaction' => 
'property.uiimport_components.index'))
+                                       ),
                                        'entity' => array
                                                (
                                                'text' => lang('Admin entity'),

Modified: branches/Version-2_0-branch/property/inc/class.soinvoice.inc.php
===================================================================
--- branches/Version-2_0-branch/property/inc/class.soinvoice.inc.php    
2016-09-30 07:03:33 UTC (rev 15764)
+++ branches/Version-2_0-branch/property/inc/class.soinvoice.inc.php    
2016-09-30 07:11:26 UTC (rev 15765)
@@ -596,15 +596,20 @@
                                $where = 'AND';
                        }
 
+                       if(!$filtermethod)
+                       {
+                               return array();
+                       }
+
                        $groupmethod = "GROUP BY 
pmwrkord_code,bilagsnr,bilagsnr_ut,fakturanr,"
-                               . " 
currency,budsjettansvarligid,org_name,periode,periodization,periodization_start";
+                               . " 
currency,budsjettansvarligid,org_name,periode,periodization,periodization_start,external_voucher_id";
 
                        $sql = "SELECT DISTINCT 
pmwrkord_code,bilagsnr,bilagsnr_ut,fakturanr,sum(belop) as belop, 
sum(godkjentbelop) as godkjentbelop,"
-                               . " 
currency,budsjettansvarligid,org_name,periode,periodization,periodization_start"
+                               . " 
currency,budsjettansvarligid,org_name,periode,periodization,periodization_start,external_voucher_id"
                                . " FROM {$table}"
-                               . " {$this->join} fm_ecoart ON fm_ecoart.id = 
$table.artid"
-                               . " {$this->join} fm_workorder ON 
fm_workorder.id = $table.pmwrkord_code"
-                               . " {$this->join} fm_project ON 
fm_workorder.project_id = fm_project.id"
+//                             . " {$this->join} fm_ecoart ON fm_ecoart.id = 
$table.artid"
+//                             . " {$this->join} fm_workorder ON 
fm_workorder.id = $table.pmwrkord_code"
+//                             . " {$this->join} fm_project ON 
fm_workorder.project_id = fm_project.id"
                                . " {$this->join} fm_vendor ON 
{$table}.spvend_code = fm_vendor.id {$filtermethod} {$groupmethod}";
 
                        $this->db->query($sql . $ordermethod, __LINE__, 
__FILE__);
@@ -613,8 +618,7 @@
                        $values = array();
                        while ($this->db->next_record())
                        {
-                               $values[] = array
-                                       (
+                               $values[] = array(
                                        'workorder_id' => 
$this->db->f('pmwrkord_code'),
                                        'voucher_id' => 
$this->db->f('bilagsnr'),
                                        'voucher_out_id' => 
$this->db->f('bilagsnr_ut'),
@@ -626,7 +630,8 @@
                                        'period' => $this->db->f('periode'),
                                        'periodization' => 
$this->db->f('periodization'),
                                        'periodization_start' => 
$this->db->f('periodization_start'),
-                                       'budget_responsible' => 
$this->db->f('budsjettansvarligid')
+                                       'budget_responsible' => 
$this->db->f('budsjettansvarligid'),
+                                       'external_voucher_id' => 
$this->db->f('external_voucher_id'),
                                );
                        }
 

Modified: branches/Version-2_0-branch/property/inc/class.solocation.inc.php
===================================================================
--- branches/Version-2_0-branch/property/inc/class.solocation.inc.php   
2016-09-30 07:03:33 UTC (rev 15764)
+++ branches/Version-2_0-branch/property/inc/class.solocation.inc.php   
2016-09-30 07:11:26 UTC (rev 15765)
@@ -2118,4 +2118,48 @@
                        return $values;
 
                }
+
+               /**
+                * Get location by location_code
+                *
+                * @param string   location_code
+                *
+                * @return array array of hits
+                */
+               public function get_locations( $location_code )
+               {
+                       $location_arr = explode('-', $location_code);
+                       $level = count($location_arr) +1;
+
+                       $filtermethod = '';
+
+                       if(ctype_digit($location_arr[0]))
+                       {
+                               $filtermethod = "WHERE location_code 
{$this->like} '{$location_code}%'";
+                       }
+                       else
+                       {
+                               $query = 
$this->db->db_addslashes($location_arr[0]);
+                               $filtermethod = "WHERE loc{$level}_name 
{$this->like} '%{$query}%'";
+                       }
+
+                       $values = array();
+                       if ($location_code)
+                       {
+                               $sql = "SELECT loc{$level}_name as name, 
location_code FROM fm_location{$level} {$filtermethod}"
+                               . " ORDER BY location_code";
+                               $this->db->limit_query($sql, 0, __LINE__, 
__FILE__);
+                               while ($this->db->next_record())
+                               {
+                                       $_location_code = 
$this->db->f('location_code');
+
+                                       $values[] = array(
+                                               'id' => $_location_code,
+                                               'name' => $_location_code . 
'::' . $this->db->f('name', true)
+                                       );
+                               }
+                       }
+                       return $values;
+               }
+
        }
\ No newline at end of file

Modified: branches/Version-2_0-branch/property/inc/class.sotts.inc.php
===================================================================
--- branches/Version-2_0-branch/property/inc/class.sotts.inc.php        
2016-09-30 07:03:33 UTC (rev 15764)
+++ branches/Version-2_0-branch/property/inc/class.sotts.inc.php        
2016-09-30 07:11:26 UTC (rev 15765)
@@ -1565,7 +1565,8 @@
                                $order_id = 
execMethod('property.socommon.increment_id', 'order');
                                if ($order_id)
                                {
-                                       $this->db->query("UPDATE fm_tts_tickets 
SET order_id = {$order_id} WHERE id={$id}", __LINE__, __FILE__);
+                                       $this->db->query("UPDATE fm_tts_tickets 
SET order_id = {$order_id}, ordered_by = {$this->account} WHERE id={$id}", 
__LINE__, __FILE__);
+                                       $this->db->query("INSERT INTO fm_orders 
(id,type) VALUES ({$order_id},'ticket')");
                                }
                        }
 

Modified: branches/Version-2_0-branch/property/inc/class.uiimport.inc.php
===================================================================
--- branches/Version-2_0-branch/property/inc/class.uiimport.inc.php     
2016-09-30 07:03:33 UTC (rev 15764)
+++ branches/Version-2_0-branch/property/inc/class.uiimport.inc.php     
2016-09-30 07:11:26 UTC (rev 15765)
@@ -5,7 +5,8 @@
 
                var $public_functions = array
                        (
-                       'index' => true
+                       'index' => true,
+                       'components' => true
                );
 
                const DELIMITER = ";";
@@ -688,7 +689,25 @@
                                return false;
                        }
                }
+               
+               private function _xml2array ( $xmlObject, $out = array () )
+               {
+                       foreach ( (array) $xmlObject as $index => $node )
+                       {
+                               $out[$index] = ( is_object($node) || 
is_array($node) ) ? $this->_xml2array ( $node ) : $node;
+                       }
+                       
+                       return $out;
+               }
 
+               protected function getxmldata( $path, $get_identificator = true 
)
+               {
+                       $xml = simplexml_load_file($path);
+                       $out = $this->_xml2array($xml);
+
+                       return $out;
+               }
+               
                protected function getcsvdata( $path, $get_identificator = true 
)
                {
                        // Open the csv file
@@ -865,4 +884,305 @@
 
                        return $file_list;
                }
+               
+               /**
+                * Public method. 
+                * 
+                * @return unknown_type
+                */
+               public function components()
+               {
+                       // Set the submit button label to its initial state
+                       $this->import_button_label = "Start import";
+
+                       $check_method = 0;
+                       $get_identificator = false;
+                       /*if ($this->conv_type = phpgw::get_var('conv_type'))
+                       {
+                               $check_method ++;
+                               $get_identificator = true;
+                       }
+                       
+                       if ($this->location_id = phpgw::get_var('location_id', 
'int'))
+                       {
+                               $check_method ++;
+                               $get_identificator = true;
+                       }
+
+                       if ($table = phpgw::get_var('table'))
+                       {
+                               $check_method ++;
+                               $get_identificator = true;
+                       }*/
+
+                       if ($check_method > 1)
+                       {
+                               phpgwapi_cache::session_set('property', 
'import_message', 'choose only one target!');
+                               $GLOBALS['phpgw']->redirect_link('/index.php', 
array('menuaction' => 'property.uiimport.components'));
+                       }
+
+
+                       phpgwapi_cache::session_set('property', 
'import_settings', $_POST);
+
+                       /*$download_template = 
phpgw::get_var('download_template');
+
+                       if ($download_template)
+                       {
+                               $this->get_template($this->location_id);
+                       }*/
+
+                       // If the parameter 'importsubmit' exist (submit button 
in import form), set path
+                       if (phpgw::get_var("importsubmit"))
+                       {
+                               if ($GLOBALS['phpgw']->session->is_repost() && 
!phpgw::get_var('debug', 'bool'))
+                               {
+                                       phpgwapi_cache::session_set('property', 
'import_message', 'Hmm... looks like a repost!');
+                                       
$GLOBALS['phpgw']->redirect_link('/index.php', array('menuaction' => 
'property.uiimport.components'));
+                               }
+
+
+                               $start_time = time(); // Start time of import
+                               $start = date("G:i:s", $start_time);
+                               echo "<h3>Import started at: {$start}</h3>";
+                               echo "<ul>";
+
+                               /*if ($this->conv_type)
+                               {
+                                       if (preg_match('/\.\./', 
$this->conv_type))
+                                       {
+                                               throw new Exception("Not a 
valid file: {$this->conv_type}");
+                                       }
+
+                                       $file = PHPGW_SERVER_ROOT . 
"/property/inc/import/{$GLOBALS['phpgw_info']['user']['domain']}/{$this->conv_type}";
+
+                                       if (is_file($file))
+                                       {
+                                               require_once $file;
+                                       }
+                               }
+                               else
+                               {
+                                       require_once PHPGW_SERVER_ROOT . 
"/property/inc/import/import_update_generic.php";
+                               }*/
+
+
+                               $this->debug = phpgw::get_var('debug', 'bool');
+                               //$this->import_conversion = new 
import_conversion($this->location_id, $this->debug);
+
+                               // Get the path for user input or use a default 
path
+
+                               $files = array();
+                               if (isset($_FILES['file']['tmp_name']) && 
$_FILES['file']['tmp_name'])
+                               {
+                                       $files[] = array
+                                               (
+                                               'name' => 
$_FILES['file']['tmp_name'],
+                                               'type' => 
$_FILES['file']['type']
+                                       );
+                               }
+                               else
+                               {
+                                       $path = phpgw::get_var('path', 
'string');
+                                       $files = $this->get_files($path);
+                               }
+
+                               if (!$files)
+                               {
+                                       phpgwapi_cache::session_set('property', 
'import_message', 'Ingen filer er valgt');
+                                       
$GLOBALS['phpgw']->redirect_link('/index.php', array('menuaction' => 
'property.uiimport.components'));
+                               }
+
+                               $entity_categories_in_xml = array();
+                               foreach ($files as $file)
+                               {
+                                       $valid_type = true;
+                                       /*switch ($file['type'])
+                                       {
+                                               case 
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
+                                               case 
'application/vnd.oasis.opendocument.spreadsheet':
+                                               case 'application/vnd.ms-excel':
+                                                       $this->csvdata = 
$this->getexceldata($file['name'], $get_identificator);
+                                                       $valid_type = true;
+                                                       break;
+                                               case 'text/csv':
+                                               case 
'text/comma-separated-values':
+                                                       $this->csvdata = 
$this->getcsvdata($file['name'], $get_identificator);
+                                                       $valid_type = true;
+                                                       break;
+                                               default:
+                                                       throw new 
Exception("Not a valid filetype: {$file['type']}");
+                                       }*/
+
+                                       $result = 
$this->getxmldata($file['name'], $get_identificator);
+                                       
+                                       $postnrdelkode = 
$result['Prosjekter']['ProsjektNS']['Postnrplan']['PostnrdelKoder']['PostnrdelKode'];
+                                       $entities_name = array();
+                                       foreach ($postnrdelkode as $items) 
+                                       {
+                                               if 
($items['PostnrdelKoder']['PostnrdelKode']['Kode'])
+                                               {
+                                                               
$entities_name[$items['PostnrdelKoder']['PostnrdelKode']['Kode']] = array(
+                                                                       'name' 
=> $items['PostnrdelKoder']['PostnrdelKode']['Kode'].' - 
'.$items['PostnrdelKoder']['PostnrdelKode']['Navn']
+                                                               );              
                                        
+                                               }
+                                               else {
+                                                       foreach 
($items['PostnrdelKoder']['PostnrdelKode'] as $item) 
+                                                       {
+                                                               
$entities_name[$item['Kode']] = array('name' => $item['Kode'].' - 
'.$item['Navn']);
+                                                       }
+                                               }
+                                       }
+                                       
+                                       $posts = 
$result['Prosjekter']['ProsjektNS']['Prosjektdata']['Post'];
+                                       foreach ($posts as $post) 
+                                       {
+                                               $buildingpart = 
$post['Postnrdeler']['Postnrdel'][1]['Kode'];
+                                               
$entity_categories_in_xml[$buildingpart]['name'] = 
$entities_name[$buildingpart]['name'];
+                                               
$entity_categories_in_xml[$buildingpart]['components'][] = array(
+                                                       array('name' => 
'benevnelse', 'value' => trim($post['Egenskaper']['Egenskap']['Verdi'])),
+                                                       array('name' => 
'beskrivelse', 'value' => trim($post['Tekst']['Uformatert']))
+                                               );
+                                               
+                                               
//$buildingpart_in_xml[$post['Postnrdeler']['Postnrdel'][1]['Kode']] = 
$post['Postnrdeler']['Postnrdel'][1]['Kode'];
+                                       }
+               
+                                       //echo '<li class="info">Import: 
finished step ' . print_r($buildingpart) . '</li>';
+                               }
+                               
+                               require_once PHPGW_SERVER_ROOT . 
"/property/inc/import/import_update_components.php";
+
+                               $import_components = new import_components();
+                               $entity_categories  = 
$import_components->get_entity_categories();
+
+                               $buildingpart_out_table = array();
+                               foreach ($entity_categories_in_xml as $k => $v) 
+                               {
+                                       if (!array_key_exists((string)$k, 
$entity_categories))
+                                       {
+                                               $buildingpart_parent = 
substr($k, 0, strlen($k) -1);
+                                               $buildingpart_out_table[$k] = 
array('parent' => $entity_categories[$buildingpart_parent], 'name' => 
$v['name']);
+                                       } else {
+                                               
$entity_categories_in_xml[$k]['cat_id'] = $entity_categories[$k]['id'];
+                                               
$entity_categories_in_xml[$k]['entity_id'] = 
$entity_categories[$k]['entity_id'];
+                                       }
+                               }
+                               
+                               if (count($buildingpart_out_table))
+                               {
+                                       $buildingpart_processed = 
$import_components->add_entity_categories($buildingpart_out_table);
+                                       
+                                       if 
(count($buildingpart_processed['added']))
+                                       {
+                                               echo 'Entities added: <br>';
+                                               
foreach($buildingpart_processed['added'] as $k => $v)
+                                               {
+                                                       
$entity_categories_in_xml[$k]['cat_id'] = $v['id'];
+                                                       
$entity_categories_in_xml[$k]['entity_id'] = $v['entity_id'];                   
+                                                       echo $v['name'].'<br>';
+                                               }
+                                       } 
+                                       
+                                       if 
(count($buildingpart_processed['not_added']))
+                                       {
+                                               echo '<br>Entities not added: 
<br>';
+                                               
foreach($buildingpart_processed['not_added'] as $k => $v)
+                                               {
+                                                       
unset($entity_categories_in_xml[$k]);   
+                                                       echo $v['name'].'<br>';
+                                               }                               
                
+                                       }
+                               }
+                               
+                               $components_not_added = 
$import_components->add_bim_item($entity_categories_in_xml);
+                               if (count($components_not_added))
+                               {
+                                       echo '<br>Components not added: <br>';
+                                       foreach ($components_not_added as $k => 
$v)
+                                       {
+                                               echo $k.' => not added: 
'.$v.'<br>';
+                                       }
+                               }
+                               
+                               //print_r($entity_categories_in_xml);
+                               
+                               echo "</ul>";
+                               $end_time = time();
+                               $difference = ($end_time - $start_time) / 60;
+                               $end = date("G:i:s", $end_time);
+                               echo "<h3>Import ended at: {$end}. Import 
lasted {$difference} minutes.";
+
+                               if ($this->errors)
+                               {
+                                       echo "<ul>";
+                                       foreach ($this->errors as $error)
+                                       {
+                                               echo '<li class="error">Error: 
' . $error . '</li>';
+                                       }
+
+                                       echo "</ul>";
+                               }
+
+                               if ($this->warnings)
+                               {
+                                       echo "<ul>";
+                                       foreach ($this->warnings as $warning)
+                                       {
+                                               echo '<li 
class="warning">Warning: ' . $warning . '</li>';
+                                       }
+                                       echo "</ul>";
+                               }
+
+                               if ($this->messages)
+                               {
+                                       echo "<ul>";
+
+                                       foreach ($this->messages as $message)
+                                       {
+                                               echo '<li class="info">Message: 
' . $message . '</li>';
+                                       }
+                                       echo "</ul>";
+                               }
+                               echo '<a href="' . 
$GLOBALS['phpgw']->link('/home.php') . '">Home</a>';
+                               echo '</br><a href="' . 
$GLOBALS['phpgw']->link('/index.php', array('menuaction' => 
'property.uiimport.components')) . '">Import</a>';
+                       }
+                       else
+                       {
+                               $import_settings = 
phpgwapi_cache::session_get('property', 'import_settings');
+                               $import_message = 
phpgwapi_cache::session_get('property', 'import_message');
+
+                               phpgwapi_cache::session_clear('property', 
'import_message');
+
+
+                               $home = $GLOBALS['phpgw']->link('/home.php');
+                               $action = $GLOBALS['phpgw']->link('/index.php', 
array('menuaction' => 'property.uiimport.components'));
+
+                               //$debug_checked = 
isset($import_settings['debug']) && $import_settings['debug'] ? 'checked =  
"checked"' : '';
+                               $html = <<<HTML
+                               <h1><img 
src="rental/templates/base/images/32x32/actions/document-save.png" /> Importer 
( MsExcel / CSV )</h1>
+                               <div id="messageHolder">{$import_message}</div>
+                               <form action="{$action}" method="post" 
enctype="multipart/form-data">
+                                       <fieldset>
+                                               <p>
+                                                       <label 
for="file">Choose file:</label>
+                                                       <input type="file" 
name="file" id="file" title = 'Single file'/>
+                                               </p>
+                                               <p>
+                                                       <label for="path">Local 
path:</label>
+                                                       <input type="text" 
name="path" id="path" value = '{$import_settings['path']}' title = 'Alle filer 
i katalogen'/>
+                                               </p>
+                                               <p>
+                                                       <label 
for="debug">Debug:</label>
+                                                       <input type="checkbox" 
name="debug" id="debug" {$debug_checked} value ='1' />
+                                               </p>
+                                               <p>
+                                                       <input type="submit" 
name="importsubmit" value="{$this->import_button_label}"  />
+                                               </p>
+                                       </fieldset>
+                               </form>
+                               <br><a href='$home'>Home</a>
+HTML;
+                               echo $html;
+                       }
+               }
+               
        }
\ No newline at end of file

Copied: 
branches/Version-2_0-branch/property/inc/class.uiimport_components.inc.php 
(from rev 15764, trunk/property/inc/class.uiimport_components.inc.php)
===================================================================
--- branches/Version-2_0-branch/property/inc/class.uiimport_components.inc.php  
                        (rev 0)
+++ branches/Version-2_0-branch/property/inc/class.uiimport_components.inc.php  
2016-09-30 07:11:26 UTC (rev 15765)
@@ -0,0 +1,854 @@
+<?php
+       /**
+        * phpGroupWare - property: a part of a Facilities Management System.
+        *
+        * @author Sigurd Nes <address@hidden>
+        * @copyright Copyright (C) 2012 Free Software Foundation, Inc. 
http://www.fsf.org/
+        * This file is part of phpGroupWare.
+        *
+        * phpGroupWare is free software; you can redistribute it and/or modify
+        * it under the terms of the GNU General Public License as published by
+        * the Free Software Foundation; either version 2 of the License, or
+        * (at your option) any later version.
+        *
+        * phpGroupWare is distributed in the hope that it will be useful,
+        * but WITHOUT ANY WARRANTY; without even the implied warranty of
+        * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+        * GNU General Public License for more details.
+        *
+        * You should have received a copy of the GNU General Public License
+        * along with phpGroupWare; if not, write to the Free Software
+        * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  
02110-1301  USA
+        *
+        * @license http://www.gnu.org/licenses/gpl.html GNU General Public 
License
+        * @internal Development of this application was funded by 
http://www.bergen.kommune.no/
+        * @package property
+        * @subpackage logistic
+        * @version $Id: class.uigeneric_document.inc.php 14913 2016-04-11 
12:27:37Z sigurdne $
+        */
+
+       phpgw::import_class('phpgwapi.uicommon_jquery');
+       phpgw::import_class('phpgwapi.jquery');
+       
+       include_class('property', 'import_entity_categories', 'inc/import/');
+       include_class('property', 'import_components', 'inc/import/');
+       include_class('property', 'import_component_files', 'inc/import/');
+
+       class property_uiimport_components extends phpgwapi_uicommon_jquery
+       {
+               var $type = 'entity';
+               private $receipt = array();
+               protected $type_app = array
+                       (
+                       'entity' => 'property',
+                       'catch' => 'catch'
+               );
+               
+               public $public_functions = array(
+                       'query' => true,
+                       'index' => true,
+                       'get_locations_for_type' => true,
+                       'import_component_files' => true,
+                       'handle_import_files' => true,
+                       'import_components' => true,
+                       'get_attributes_from_template' => true,
+                       'download' => true
+               );
+
+               public function __construct()
+               {
+                       parent::__construct();
+
+                       $this->bocommon = CreateObject('property.bocommon');
+                       $this->custom = CreateObject('property.custom_fields');
+                       $this->bo = CreateObject('property.boadmin_entity', 
true);
+                       $this->acl = & $GLOBALS['phpgw']->acl;
+                       $this->db = & $GLOBALS['phpgw']->db;
+               }
+
+               public function download()
+               {
+                       $config = createObject('phpgwapi.config', 
'component_import');
+                       $values = $config->read_repository();
+                       $components = $values['preview_components'];
+                       
+                       $fields = array_keys($components[0]);
+
+                       $this->bocommon->download($components, $fields, 
$fields);
+               }
+
+               private function _msg_data( $receipt )
+               {
+                       if (isset($receipt['error']) && 
is_array($receipt['error']))
+                       {
+                               foreach ($receipt['error'] as $dummy => $error)
+                               {
+                                       $this->receipt['error'][] = $error;
+                               }
+                       }
+
+                       if (isset($receipt['message']) && 
is_array($receipt['message']))
+                       {
+                               foreach ($receipt['message'] as $dummy => 
$message)
+                               {
+                                       $this->receipt['message'][] = $message;
+                               }
+                       }
+
+                       return $this->receipt;
+               }
+               
+               private function _getexcelcolumnname( $index )
+               {
+                       //Get the quotient : if the index superior to base 26 
max ?
+                       $quotient = $index / 26;
+                       if ($quotient >= 1)
+                       {
+                               //If yes, get top level column + the current 
column code
+                               return $this->_getexcelcolumnname($quotient - 
1) . chr(($index % 26) + 65);
+                       }
+                       else
+                       {
+                               //If no just return the current column code
+                               return chr(65 + $index);
+                       }
+               }
+               
+               public function import_component_files()
+               {
+                       $location_code = 
phpgwapi_cache::session_get('property', 'location_code');
+                       $id = phpgwapi_cache::session_get('property', 
'location_item_id');
+                       $attrib_name_componentID = 
phpgwapi_cache::session_get('property', 'attrib_name_componentID');
+                       
+                       if (!$attrib_name_componentID)
+                       {
+                               $receipt['error'][] = array('msg' => 
lang('Choose attribute name for Component ID'));
+                               return $receipt;
+                       }
+                       if (!$location_code)
+                       {
+                               $receipt['error'][] = array('msg' => 
lang('Choose Location'));
+                               return $receipt;
+                       }
+                       
+                       $import_component_files = new import_component_files();
+                       $receipt = $import_component_files->add_files($id, 
$location_code, $attrib_name_componentID);
+                       
+                       return $receipt;
+               }
+               
+               private function _getArrayItem($id, $name, $selected, $options 
= array(), $no_lang = false, $attribs = '' )
+               {
+                       // should be in class common.sbox
+                       if ( !is_array($options) || !count($options) )
+                       {
+                               $options = array('no', 'yes');
+                       }
+
+                       $html = <<<HTML
+                       <select name="$name" id="$id" $attribs>
+
+HTML;
+
+                       $check = array();
+
+                       if (!is_array($selected))
+                       {
+                               $check[$selected] = true;       
+                       }
+                       else
+                       {
+                               foreach ($selected as $sel)
+                               {
+                                       $check[$sel] = true;
+                               }
+                       }
+
+                       foreach ( $options as $value => $option )
+                       {
+                               $check2 = isset( $check[$value] ) ? ' selected' 
: '';
+                               $option = $no_lang ? $option : lang($option);
+
+                               $html .= <<<HTML
+                                       <option 
value="{$value}"{$check2}>{$option}</option>
+
+HTML;
+                       }
+                       $html .= <<<HTML
+                       </select>
+
+HTML;
+                       return $html;
+               }
+               
+               public function handle_import_files()
+               {
+                       $path_upload_dir = 
phpgwapi_cache::session_get('property', 'path_upload_dir');
+                       if (empty($path_upload_dir))
+                       {
+                               return false;
+                       }
+                       require_once PHPGW_SERVER_ROOT . 
"/property/inc/import/UploadHandler.php";
+                       
+                       $options['upload_dir'] = $path_upload_dir;
+                       $options['script_url'] = 
$GLOBALS['phpgw']->link('/index.php', array('menuaction' => 
'property.uiimport_components.handle_import_files'));
+                       $upload_handler = new UploadHandler($options);
+               }
+
+               private function _get_components_cached_file ()
+               {
+                       $cached_file = phpgwapi_cache::session_get('property', 
'components_import_file');
+                       
+                       if ($_FILES['file']['tmp_name'])
+                       {
+                               if ($cached_file)
+                               {
+                                       
phpgwapi_cache::session_clear('property', 'components_import_file');
+                                       unlink($cached_file);
+                                       unset($cached_file);
+                               }
+                               
+                               $file = $_FILES['file']['tmp_name'];
+                               $cached_file = "{$file}_temporary_import_file";
+
+                               file_put_contents($cached_file, 
file_get_contents($file));
+                               phpgwapi_cache::session_set('property', 
'components_import_file', $cached_file);
+                       }
+                       
+                       return $cached_file;
+               }
+               
+               private function _build_sheets()
+               {
+                       $cached_file = $this->_get_components_cached_file();
+                       if (!$cached_file)
+                       {
+                               $this->receipt['error'][] = array('msg' => 
lang('Cached file not exists'));
+                               return;
+                       }
+                       
+                       $objPHPExcel = PHPExcel_IOFactory::load($cached_file);
+                       $AllSheets = $objPHPExcel->getSheetNames();
+
+                       $sheets = array();
+                       if ($AllSheets)
+                       {
+                               foreach ($AllSheets as $key => $sheet)
+                               {
+                                       $sheets[] = array
+                                               (
+                                               'id' => ($key + 1),
+                                               'name' => $sheet
+                                       );
+                               }
+                       }       
+
+                       return $sheets;                 
+               }
+               
+               private function _build_start_line()
+               {
+                       $sheet_id = phpgwapi_cache::session_get('property', 
'sheet_id');
+                       $cached_file = $this->_get_components_cached_file();
+                       if (!$cached_file)
+                       {
+                               $this->receipt['error'][] = array('msg' => 
lang('Cached file not exists'));
+                               return;
+                       }
+                       
+                       $objPHPExcel = PHPExcel_IOFactory::load($cached_file);
+                       $objPHPExcel->setActiveSheetIndex((int)($sheet_id - 1));
+                       $highestColumm = 
$objPHPExcel->getActiveSheet()->getHighestDataColumn();
+                       $highestColumnIndex = 
PHPExcel_Cell::columnIndexFromString($highestColumm);     
+
+                       $html_table = '<table class="pure-table 
pure-table-bordered">';
+                       $i = 0;
+                       $cols = array();
+                       for ($j = 0; $j < $highestColumnIndex; $j++)
+                       {
+                               $cols[] = $this->_getexcelcolumnname($j);
+                       }
+
+                       $html_table .= "<thead><tr><th align = 'center'>" . 
lang('select') . "</th><th align = 'center'>" . lang('row') . "</th><th 
align='center'>" . implode("</th><th align='center'>", $cols) . 
'</th></tr></thead>';
+                       foreach 
($objPHPExcel->getActiveSheet()->getRowIterator() as $row)
+                       {
+                               if ($i > 20)
+                               {
+                                       break;
+                               }
+
+                               $i++;
+                               $row_key = $i;
+
+                               $_radio = "<input type =\"radio\" 
name=\"start_line\" value=\"{$row_key}\">";
+
+                               $cellIterator = $row->getCellIterator();
+                               
$cellIterator->setIterateOnlyExistingCells(false);
+
+                               $row_values = array();
+                               foreach ($cellIterator as $cell)
+                               {
+                                       if (!is_null($cell))
+                                       {
+                                               $row_values[] = 
$cell->getCalculatedValue();
+                                       }
+                               }
+                               $html_table .= 
"<tr><td>{$_radio}</td><td>{$row_key}</td><td>" . implode('</td><td>', 
$row_values) . '</td></tr>';
+                       }
+                       $html_table .= '</table>';
+
+                       return $html_table;             
+               }
+               
+               private function _build_columns()
+               {
+                       $cached_file = $this->_get_components_cached_file();
+                       if (!$cached_file)
+                       {
+                               $this->receipt['error'][] = array('msg' => 
lang('Cached file not exists'));
+                               return;
+                       }
+                       $sheet_id = phpgwapi_cache::session_get('property', 
'sheet_id');
+                       $start_line = phpgwapi_cache::session_get('property', 
'start_line');
+                       $template_id = phpgwapi_cache::session_get('property', 
'template_id');
+
+                       $objPHPExcel = PHPExcel_IOFactory::load($cached_file);
+                       $objPHPExcel->setActiveSheetIndex((int)($sheet_id - 1));
+                       $highestColumm = 
$objPHPExcel->getActiveSheet()->getHighestDataColumn();
+                       $highestColumnIndex = 
PHPExcel_Cell::columnIndexFromString($highestColumm);     
+
+                       $html_table = '<table class="pure-table 
pure-table-bordered">';
+
+                       $_options = array
+                       (
+                               '' => ' ... ',
+                               'new_column' => 'New attribute',
+                               'building_part' => '-- Building Part',
+                               'name_building_part' => '-- Name of the 
Building Part',
+                               'component_id'    => '-- Component ID'
+                       );
+
+                       $template = explode("_", $template_id);
+
+                       $attributes = 
$this->custom->find($this->type_app[$this->type], 
".{$this->type}.{$template[0]}.{$template[1]}", 0, '', 'ASC', 'attrib_sort', 
true, true);
+
+                       foreach ($attributes as $attribute)
+                       {
+                               $_options[$attribute['name']] = 
$attribute['input_text'];
+                       }
+
+                       $data_types = $this->bocommon->select_datatype();
+                       $_options_data_type[''] = 'data type';
+                       foreach($data_types as $row) 
+                       {
+                               $_options_data_type[$row['id']] = $row['name'];
+                       }
+
+                       for ($j = 0; $j < $highestColumnIndex; $j++)
+                       {
+                               $_column = $this->_getexcelcolumnname($j);
+                               $_value = 
$objPHPExcel->getActiveSheet()->getCellByColumnAndRow($j, 
$start_line)->getCalculatedValue();
+                               //$selected = isset($columns[$_column]) && 
$columns[$_column] ? $columns[$_column] : '';
+                               $selected = '';
+
+                               $_listbox = 
$this->_getArrayItem("column_{$_column}", "columns[{$_column}]", $selected, 
$_options, true, "onchange=\"enabledAtributes('{$_column}')\" class='columns'");
+                               $_listTypes = 
$this->_getArrayItem("data_type_{$_column}", "data_types[{$_column}]", 
$selected, $_options_data_type, true, "disabled class='data_types'");
+                               $html_table .= "<tr>";
+                               $html_table .= "<td>[{$_column}] 
{$_value}</td>";
+                               $html_table .= "<td>{$_listbox}</td>";
+                               $html_table .= "<td><input type='text' 
id='name_{$_column}' name='names[{$_column}]' disabled class='names' 
placeholder='attribute name'></input></td>";
+                               $html_table .= "<td>{$_listTypes}</td>";
+                               $html_table .= "<td><input type='text' 
id='precision_{$_column}' name='precision[{$_column}]' disabled 
class='precision' placeholder='length'></input></td>";
+                               $html_table .= "</tr>";
+                       }
+
+                       $html_table .= '</table>';
+
+                       return $html_table;     
+               }
+               
+               private function _prepare_values_to_preview()
+               {
+                       $columns = (array) phpgw::get_var('columns');
+                       $attrib_data_types = 
phpgw::get_var('attrib_data_types');
+                       $attrib_names = phpgw::get_var('attrib_names');
+                       $attrib_precision = phpgw::get_var('attrib_precision');
+                       
+                       $cached_file = $this->_get_components_cached_file();
+                       if (!$cached_file)
+                       {
+                               $this->receipt['error'][] = array('msg' => 
lang('Cached file not exists'));
+                               return;
+                       }
+                       
+                       $sheet_id = phpgwapi_cache::session_get('property', 
'sheet_id');
+                       $start_line = phpgwapi_cache::session_get('property', 
'start_line');
+                       $template_id = phpgwapi_cache::session_get('property', 
'template_id');
+                       $attrib_name_componentID = 
phpgwapi_cache::session_get('property', 'attrib_name_componentID');
+                       
+                       $objPHPExcel = PHPExcel_IOFactory::load($cached_file);
+                       $objPHPExcel->setActiveSheetIndex((int)($sheet_id - 1));
+                       $rows = 
$objPHPExcel->getActiveSheet()->getHighestDataRow();
+                       
+                       $import_entity_categories = new 
import_entity_categories($template_id);
+                       $import_components = new import_components();
+
+                       if (count($attrib_names))
+                       {
+                               $receipt = 
$import_entity_categories->prepare_attributes_for_template($columns, 
$attrib_names, $attrib_data_types, $attrib_precision);
+                               $this->receipt = $this->_msg_data($receipt);
+                               if ($this->receipt['error'])
+                               {
+                                       return;
+                               } else {
+                                       $new_attribs_for_template = 
$receipt['new_attribs_for_template'];
+                               }
+                       }
+
+                       $rows = $rows ? $rows + 1 : 0;
+
+                       $building_part_out_table = array();
+                       $building_part_in_table = array();
+                       $import_data = array();
+
+                       $list_entity_categories  = 
$import_entity_categories->list_entity_categories();
+
+                       for ($i = $start_line; $i < $rows; $i++)
+                       {
+                               $_result = array();
+
+                               foreach ($columns as $_row_key => $_value_key)
+                               {
+                                       $_result[$_value_key] = 
$objPHPExcel->getActiveSheet()->getCell("{$_row_key}{$i}")->getCalculatedValue();
+                               }
+
+                               if ((int)$_result['building_part'] || 
$_result['building_part'] === '0')
+                               {
+                                       $cat_id = '';
+                                       $entity_id = '';
+
+                                       if 
(array_key_exists((string)$_result['building_part'], $list_entity_categories))
+                                       {
+                                               if 
(!empty($_result['component_id']))
+                                               {
+                                                       $cat_id = 
$list_entity_categories[$_result['building_part']]['id'];
+                                                       $entity_id = 
$list_entity_categories[$_result['building_part']]['entity_id'];
+
+                                                       
$building_part_in_table[$_result['building_part']] = array('entity_id' => 
$entity_id, 'cat_id' => $cat_id);
+                                               }
+                                       }
+                                       else {
+                                               if 
(empty($_result['component_id']))
+                                               {
+                                                       
$building_part_out_table[$_result['building_part']] = 
$_result['building_part'].' '.$_result['name_building_part'];
+                                               }
+                                       }
+
+                                       if (!empty($_result['component_id']))
+                                       {
+                                               
$import_data[$_result['building_part']]['cat_id'] = $cat_id;
+                                               
$import_data[$_result['building_part']]['entity_id'] = $entity_id;
+
+                                               $_result = 
array($attrib_name_componentID => $_result['component_id']) + $_result;
+                                               $_result = array('building 
part' => $_result['building_part']) + $_result;
+
+                                               
$import_data[$_result['building_part']]['components'][] = $_result;             
                                
+                                       }
+                               }
+                       }
+
+                       if (count($building_part_out_table))
+                       {
+                               asort($building_part_out_table);
+                               $receipt = 
$import_entity_categories->prepare_entity_categories($building_part_out_table);
+                               $this->receipt = $this->_msg_data($receipt);
+                               if ($this->receipt['error'])
+                               {
+                                       return;
+                               } else {
+                                       $new_entity_categories = 
$receipt['new_entity_categories'];
+                               }
+                       }                       
+                       
+                       $result = array();
+                       
+                       if (!count($import_data))
+                       {
+                               $result['error'][] = array('msg' => lang('not 
exist components to import'));
+                               return $result;
+                       }
+                       
+                       $preview_components = 
$import_components->prepare_preview_components($import_data);
+
+                       $config = createObject('phpgwapi.config', 
'component_import');
+
+                       if (count($new_attribs_for_template))
+                       {
+                               $config->value('new_attribs_for_template', 
serialize($new_attribs_for_template));
+                               foreach($new_attribs_for_template as $attrib)
+                               {
+                                       $values[] = $attrib['column_name'];
+                               }
+                               $result['new_attribs_for_template'] = $values;
+                       } else {
+                               $result['new_attribs_for_template'][] = 
lang('Not exist attributes to insert the template');
+                       }
+
+                       if (count($new_entity_categories))
+                       {
+                               $config->value('new_entity_categories', 
serialize($new_entity_categories));
+                               $result['new_entity_categories'] = 
array_values($new_entity_categories);
+                       } else {
+                               $result['new_entity_categories'][] = lang('Not 
exist new entity categories');
+                       }
+
+                       $config->value('building_part_in_table', 
serialize($building_part_in_table));
+                       $config->value('preview_components', 
serialize($preview_components));
+                       $config->value('new_components', 
serialize($import_data));
+                       $config->save_repository();
+
+                       return $result;
+               }
+               
+               private function _save_values_import()
+               {                       
+                       $template_id = phpgwapi_cache::session_get('property', 
'template_id');
+                       $attrib_name_componentID = 
phpgwapi_cache::session_get('property', 'attrib_name_componentID');
+                       $location_code = 
phpgwapi_cache::session_get('property', 'location_code');
+                       
+                       $import_entity_categories = new 
import_entity_categories($template_id);
+                       $import_components = new import_components();
+
+                       $receipt = 
$import_entity_categories->add_attributes_to_template();
+                       $this->receipt = $this->_msg_data($receipt);
+                       if ($this->receipt['error'])
+                       {
+                               return;
+                       }
+
+                       $receipt = 
$import_entity_categories->add_attributes_to_categories();
+                       $this->receipt = $this->_msg_data($receipt);
+                       if ($this->receipt['error'])
+                       {
+                               return;
+                       }
+
+                       $config = createObject('phpgwapi.config', 
'component_import');
+                       $config_repository = $config->read_repository();
+                       $import_data = $config_repository['new_components'];
+                       
+                       if (!count($import_data))
+                       {
+                               $this->receipt['error'][] = array('msg' => 
lang("not exist components to import"));
+                               return;
+                       }
+                       
+                       $building_part_processed = 
$import_entity_categories->add_entity_categories();
+                       if (count($building_part_processed['not_added']))
+                       {
+                               foreach($building_part_processed['not_added'] 
as $k => $v)
+                               {
+                                       $this->receipt['message'][] = 
array('msg' => lang("entity category {$v} not added"));   
+                               }
+                       }
+
+                       if (count($building_part_processed['added']))
+                       {
+                               foreach($building_part_processed['added'] as $k 
=> $v)
+                               {
+                                       $import_data[$k]['cat_id'] = $v['id'];
+                                       $import_data[$k]['entity_id'] = 
$v['entity_id'];                        
+                               }
+                               $this->receipt['message'][] = array('msg' => 
lang("%1 entity category has been added", 
count($building_part_processed['added'])));      
+                       }
+
+                       $receipt = 
$import_components->add_components($import_data, $location_code, 
$attrib_name_componentID);
+                       $this->receipt = $this->_msg_data($receipt);
+
+                       return $this->receipt;
+               }
+               
+               public function import_components()
+               {       
+                       $step = phpgw::get_var('step', 'int', 'REQUEST');
+                       $save = phpgw::get_var('save', 'int', 'REQUEST');
+                               
+                       phpgw::import_class('phpgwapi.phpexcel');
+                       
+                       if ($step == 1)
+                       {
+                               $result = $this->_build_sheets();
+                       }
+                       
+                       if ($step == 2) 
+                       {
+                               $sheet_id = phpgw::get_var('sheet_id', 'int', 
'REQUEST');
+                               if (!$sheet_id)
+                               {
+                                       $this->receipt['error'][] = array('msg' 
=> lang('Select Sheet'));
+                                       return $this->receipt;
+                               }
+                               phpgwapi_cache::session_set('property', 
'sheet_id', $sheet_id);
+                               
+                               $result = $this->_build_start_line();
+                       }
+                       
+                       if ($step == 3) 
+                       {
+                               $start_line = phpgw::get_var('start_line', 
'int', 'REQUEST');
+                               $template_id = phpgw::get_var('template_id');
+                               if (!$start_line)
+                               {
+                                       $this->receipt['error'][] = array('msg' 
=> lang('Select start line'));
+                                       return $this->receipt;
+                               }
+                               if (!$template_id)
+                               {
+                                       $this->receipt['error'][] = array('msg' 
=> lang('Select template'));
+                                       return $this->receipt;
+                               }
+                               phpgwapi_cache::session_set('property', 
'start_line', $start_line);
+                               phpgwapi_cache::session_set('property', 
'template_id', $template_id);
+                       
+                               $result = $this->_build_columns();
+                       }
+                       
+                       if ($step == 4) 
+                       {
+                               $attrib_name_componentID = 
phpgw::get_var('attribute_name_component_id');
+                               if (!$attrib_name_componentID)
+                               {
+                                       $this->receipt['error'][] = array('msg' 
=> lang('Choose attribute name for Component ID'));
+                                       return $this->receipt;
+                               }
+                               phpgwapi_cache::session_set('property', 
'attrib_name_componentID', $attrib_name_componentID);
+                               
+                               $result = $this->_prepare_values_to_preview();
+                       }
+                       
+                       if ($step == 5 && $save) 
+                       {
+                               $location_code = 
phpgw::get_var('location_code');
+                               $location_item_id = 
phpgw::get_var('location_item_id');
+                               if (!$location_code)
+                               {
+                                       $this->receipt['error'][] = array('msg' 
=> lang('Choose Location'));
+                                       return $this->receipt;
+                               }
+                               phpgwapi_cache::session_set('property', 
'location_code', $location_code);
+                               phpgwapi_cache::session_set('property', 
'location_item_id', $location_item_id);
+                               
+                               $result = $this->_save_values_import();
+                       }
+                       
+                       if ($this->receipt['error'])
+                       {
+                               return $this->receipt;
+                       }
+                       
+                       return $result;
+               }
+               
+               /**
+                * Prepare UI
+                * @return void
+                */
+               public function index()
+               {
+                       $tabs = array();
+                       $tabs['locations'] = array('label' => 
lang('Locations'), 'link' => '#locations');
+                       $tabs['files'] = array('label' => lang('Files'), 'link' 
=> '#files', 'disable' => 0);
+                       $tabs['components'] = array('label' => 
lang('Components'), 'link' => '#components', 'disable' => 1);
+                       $tabs['relations'] = array('label' => 
lang('Relations'), 'link' => '#relations', 'disable' => 1);
+                                       
+                       $active_tab = 'locations';
+
+                       $type_filter =  
execMethod('property.soadmin_location.read', array());                  
+                       $category_filter = $this->get_categories_for_type();
+
+                       $district_filter = 
$this->bocommon->select_district_list('filter');
+                       array_unshift($district_filter, array('id' => '', 
'name' => lang('no district')));
+
+                       $part_of_town_filter = $this->get_part_of_town();
+
+                       $related_def = array
+                               (
+                               array('key' => 'location_code', 'label' => 
lang('location'), 'sortable' => false, 'resizeable' => true),
+                               array('key' => 'loc1_name', 'label' => 
lang('name'), 'sortable' => false, 'resizeable' => true)
+                       );
+
+
+                       $datatable_def[] = array
+                       (
+                               'container' => 'datatable-container_0',
+                               'requestUrl' => 
json_encode(self::link(array('menuaction' => 
'property.uiimport_components.get_locations_for_type', 'phpgw_return_as' => 
'json'))),
+                               'ColumnDefs' => $related_def,
+                               'tabletools' => array(),
+                               'config' => array(
+                                       array('singleSelect' => true)
+                               )                               
+                       );      
+                               
+                       $entity_list = $this->bo->read(array('allrows' => 
true));
+                       $category_list = array();
+                       foreach ($entity_list as $entry)
+                       {
+                               $cat_list = 
$this->bo->read_category(array('entity_id' => $entry['id'], 'allrows' => true));
+
+                               foreach ($cat_list as $category)
+                               {
+                                       $category_list[] = array
+                                               (
+                                               'id' => 
"{$entry['id']}_{$category['id']}",
+                                               'name' => 
"{$entry['name']}::{$category['name']}"
+                                       );
+                               }
+                       }
+               
+                       $form_upload_action = 
$GLOBALS['phpgw']->link('/index.php', array('menuaction' => 
'property.uiimport_components.handle_import_files'));
+                       
+                       $access_error_upload_dir = '';
+                       $import_component_files = new import_component_files();
+                       $receipt = $import_component_files->check_upload_dir(); 
        
+                       if (($receipt['error']))
+                       {
+                               $access_error_upload_dir = $receipt['error'];
+                       } else {
+                               phpgwapi_cache::session_set('property', 
'path_upload_dir', $import_component_files->get_path_upload_dir());
+                       }
+                       
+                       $data = array
+                       (
+                               'datatable_def' => $datatable_def,
+                               'tabs' => 
phpgwapi_jquery::tabview_generate($tabs, $active_tab),
+                               
+                               'type_filter' => array('options' => 
$type_filter),
+                               'category_filter' => array('options' => 
$category_filter),
+                               'district_filter' => array('options' => 
$district_filter),
+                               'part_of_town_filter' => array('options' => 
$part_of_town_filter),
+                               'template_list' => array('options' => 
$category_list),
+                               'form_file_upload' => 
phpgwapi_jquery::form_file_upload_generate($form_upload_action),
+                               'access_error_upload_dir' => 
$access_error_upload_dir,
+                               'image_loader' => 
$GLOBALS['phpgw']->common->image('property', 'ajax-loader', '.gif', false)
+                       );
+
+                       self::add_javascript('property', 'portico', 
'import_components.js');
+                       $GLOBALS['phpgw_info']['flags']['app_header'] = 
lang('property') . '::' . lang('Importer ');
+
+                       self::render_template_xsl(array('import_components', 
'datatable_inline'), $data);
+               }
+
+               public function get_attributes_from_template()
+               {
+                       $category_template = 
phpgw::get_var('category_template');
+
+                       $template_info = explode('_', $category_template);
+                       $template_entity_id = $template_info[0];
+                       $template_cat_id = $template_info[1];
+
+                       $attrib_list = $this->bo->read_attrib(array('entity_id' 
=> $template_entity_id, 'cat_id' => $template_cat_id, 'allrows' => true));
+                       $list = array();
+                       foreach ($attrib_list as $attrib)
+                       {
+                               $list[] = array('id' => $attrib['column_name'], 
'name' => $attrib['input_text']); 
+                       }
+                       
+                       array_unshift($list, array('id' => '', 'name' => 
lang('choose attribute')));
+
+                       return $list;
+               }
+               
+               public function get_locations_for_type()
+               {
+                       $type_id = phpgw::get_var('type_id', 'int');
+
+                       if (!$type_id)
+                       {
+                               $type_id = 1;
+                       }
+                       
+                       $search = phpgw::get_var('search');
+                       $order = phpgw::get_var('order');
+                       $draw = phpgw::get_var('draw', 'int');
+                       $columns = phpgw::get_var('columns');
+
+                       $params = array(
+                               'start' => phpgw::get_var('start', 'int', 
'REQUEST', 0),
+                               'results' => phpgw::get_var('length', 'int', 
'REQUEST', 0),
+                               'query' => $search['value'],
+                               'order' => 
$columns[$order[0]['column']]['data'],
+                               'sort' => $order[0]['dir'],
+                               'cat_id' => phpgw::get_var('cat_id', 'int', 
'REQUEST', 0),
+                               'type_id' => $type_id,
+                               'district_id' => phpgw::get_var('district_id', 
'int', 'REQUEST', 0),
+                               'part_of_town_id' => 
phpgw::get_var('part_of_town_id', 'int', 'REQUEST', 0),
+                               'allrows' => phpgw::get_var('length', 'int') == 
-1
+                       );
+                       
+            $solocation = CreateObject('property.solocation');
+            $locations = $solocation->read($params);
+
+                       $values = array();
+                       foreach($locations as $item)
+                       {
+                               $values[] = array(
+                                       'id' => $item['id'],
+                                       'location_code' => 
$item['location_code'],
+                                       'loc1_name' => $item['loc1_name']
+                               );                              
+                       }
+
+                       $result_data = array('results' => $values);
+
+                       $result_data['total_records'] = 
$solocation->total_records;
+                       $result_data['draw'] = $draw;
+
+                       return $this->jquery_results($result_data);
+               }
+               
+               /**
+                * Fetch data from $this->bo based on parametres
+                * @return array
+                */
+               public function query()
+               {
+                       return;
+               }
+               
+               public function get_categories_for_type()
+               {
+                       $type_id = phpgw::get_var('type_id', 'int');
+
+                       if (!$type_id)
+                       {
+                               $type_id = 1;
+                       }
+                       
+                       $categories = 
$this->bocommon->select_category_list(array
+                               ('format' => 'filter',
+                               'selected' => '',
+                               'type' => 'location',
+                               'type_id' => $type_id,
+                               'order' => 'descr')
+                       );
+                       array_unshift($categories, array('id' => '', 'name' => 
lang('no category')));
+
+                       return $categories;
+               }
+               
+               public function get_data_type()
+               {
+                       $values = $this->bocommon->select_datatype();
+                       return $values;
+               }
+               
+               public function get_part_of_town()
+               {
+                       $district_id = phpgw::get_var('district_id', 'int');
+                       $values = 
$this->bocommon->select_part_of_town('filter', '', $district_id);
+                       array_unshift($values, array('id' => '', 'name' => 
lang('no part of town')));
+
+                       return $values;
+               }
+
+       }
\ No newline at end of file

Modified: branches/Version-2_0-branch/property/inc/class.uitts.inc.php
===================================================================
--- branches/Version-2_0-branch/property/inc/class.uitts.inc.php        
2016-09-30 07:03:33 UTC (rev 15764)
+++ branches/Version-2_0-branch/property/inc/class.uitts.inc.php        
2016-09-30 07:11:26 UTC (rev 15765)
@@ -56,7 +56,8 @@
                        'get_external_project'=> true,
                        'get_unspsc_code'=> true,
                        'receive_order' => true,
-                       'check_purchase_right'=> true
+                       'check_purchase_right'=> true,
+                       'show_attachment'       => true
                );
 
                /**
@@ -229,6 +230,35 @@
                        echo $html;
                }
 
+               function show_attachment(  )
+               {
+                       if (!$this->acl->check('.ticket.order', PHPGW_ACL_ADD, 
'property') && !$this->acl->check('.project', PHPGW_ACL_ADD, 'property'))
+                       {
+                               phpgw::no_access();
+                       }
+                       $GLOBALS['phpgw_info']['flags']['noheader'] = true;
+                       $GLOBALS['phpgw_info']['flags']['nofooter'] = true;
+                       $GLOBALS['phpgw_info']['flags']['xslt_app'] = false;
+
+                       $file_name = urldecode(phpgw::get_var('file_name'));
+                       $key = phpgw::get_var('key');
+                       $invoice_config = CreateObject('admin.soconfig', 
$GLOBALS['phpgw']->locations->get_id('property', '.invoice'));
+                       $directory_attachment = 
rtrim($invoice_config->config_data['import']['local_path'], '/') . 
'/attachment/' . $key;
+
+                       $file = "$directory_attachment/$file_name";
+
+                       if (file_exists($file))
+                       {
+                               $size = filesize($file);
+                               $content = file_get_contents($file);
+
+                               $browser = CreateObject('phpgwapi.browser');
+                               $browser->content_header($document['name'], '', 
$size);
+                               echo $content;
+                       }
+       
+               }
+
                function download2()
                {
                        if (!$this->acl->check('.ticket.external', 
PHPGW_ACL_READ, 'property'))
@@ -733,6 +763,8 @@
 
                                $values_combo_box[4] = 
$this->_get_user_list($this->user_id);
 
+                               $filter_tts_assigned_to_me = 
$GLOBALS['phpgw_info']['user']['preferences']['property']['tts_assigned_to_me'];
+
                                array_unshift($values_combo_box[4], array(
                                        'id' => -1 * 
$GLOBALS['phpgw_info']['user']['account_id'],
                                        'name' => lang('my assigned tickets'),
@@ -940,15 +972,21 @@
 
                        $parameters = array
                                (
-                               'parameter' => array
-                                       (
-                                       array
-                                               (
+                               'parameter' => array(
+                                       array(
                                                'name' => 'id',
                                                'source' => 'id'
                                        ),
                                )
                        );
+                       $parameters_location = array(
+                               'parameter' => array(
+                                       array(
+                                               'name' => 'location_code',
+                                               'source' => 'location_code'
+                                       ),
+                               )
+                       );
 
                        $data['datatable']['actions'][] = array
                                (
@@ -969,12 +1007,11 @@
                                'action' => 
$GLOBALS['phpgw']->link('/index.php', array
                                        (
                                        'menuaction' => 'property.uitts._print',
-                                       'target' => '_blank'
                                )),
+                               'target' => '_blank',
                                'parameters' => json_encode($parameters)
                        );
 
-
                        $jasper = execMethod('property.sojasper.read', 
array('location_id' => $GLOBALS['phpgw']->locations->get_id('property', 
$this->acl_location)));
 
                        foreach ($jasper as $report)
@@ -987,8 +1024,8 @@
                                                (
                                                'menuaction' => 
'property.uijasper.view',
                                                'jasper_id' => $report['id'],
-                                               'target' => '_blank'
                                        )),
+                                       'target' => '_blank',
                                        'parameters' => json_encode($parameters)
                                );
                        }
@@ -1008,6 +1045,18 @@
                                        'parameters' => json_encode($parameters)
                                );
                        }
+                       $data['datatable']['actions'][] = array
+                               (
+                               'my_name' => 'docs',
+                               'statustext' => lang('documents'),
+                               'text' => lang('documents'),
+                               'action' => 
$GLOBALS['phpgw']->link('/index.php', array
+                                       (
+                                       'menuaction' => 
'property.uidocument.list_doc',
+                               )),
+                               'target' => '_blank',
+                               'parameters' => 
json_encode($parameters_location)
+                       );
 
                        if 
(isset($GLOBALS['phpgw_info']['user']['preferences']['property']['tts_status_link'])
 && 
$GLOBALS['phpgw_info']['user']['preferences']['property']['tts_status_link'] == 
'yes' && $this->acl_edit)
                        {
@@ -2514,14 +2563,16 @@
 
                        // start invoice
                        $invoices = array();
-                       $active_invoices = 
execMethod('property.soinvoice.read_invoice_sub_sum', array(
-                               'order_id' => $id));
-                       $historical_invoices = 
execMethod('property.soinvoice.read_invoice_sub_sum', array(
-                               'order_id' => $id,
-                               'paid' => true));
-                       $invoices = array_merge($active_invoices, 
$historical_invoices);
+                       if(!empty($ticket['order_id']))
+                       {
+                               $active_invoices = 
execMethod('property.soinvoice.read_invoice_sub_sum', array(
+                                       'order_id' => $ticket['order_id']));
+                               $historical_invoices = 
execMethod('property.soinvoice.read_invoice_sub_sum', array(
+                                       'order_id' => $ticket['order_id'],
+                                       'paid' => true));
+                               $invoices = array_merge($active_invoices, 
$historical_invoices);
+                       }
 
-
                        $link_data_invoice1 = array
                                (
                                'menuaction' => 'property.uiinvoice.index',
@@ -2580,6 +2631,7 @@
 
                                $content_invoice[] = array
                                        (
+                                       'external_voucher_id'   => 
$entry['external_voucher_id'],
                                        'voucher_id' => ($_lean) ? 
$entry['voucher_id'] : $link_voucher_id,
                                        'voucher_out_id' => 
$entry['voucher_out_id'],
                                        'status' => $entry['status'],
@@ -2606,14 +2658,72 @@
                                $approved_amount += $entry['approved_amount'];
                        }
 
+
+                       if($invoices)
+                       {
+                               $invoice_config = 
CreateObject('admin.soconfig', $GLOBALS['phpgw']->locations->get_id('property', 
'.invoice'));
+                       }
+
+                       foreach ($invoices as $entry)
+                       {
+                               $directory_attachment = 
rtrim($invoice_config->config_data['import']['local_path'], '/') . 
'/attachment/' .$entry['external_voucher_id'];
+                               $attachmen_list = array();
+                               try
+                               {
+                                       $dir = new 
DirectoryIterator("$directory_attachment/");
+                                       if (is_object($dir))
+                                       {
+                                               foreach ($dir as $file)
+                                               {
+                                                       if ($file->isDot() || 
!$file->isFile() || !$file->isReadable())
+                                                       {
+                                                               continue;
+                                                       }
+
+                                                       $url = self::link(array(
+                                                               'menuaction'=> 
'property.uitts.show_attachment',
+                                                               'file_name' => 
urlencode((string)$file),
+                                                               'key'=> 
$entry['external_voucher_id']
+                                                               ));
+
+                                                       $attachmen_list[] = 
array(
+                                                               'voucher_id'    
=> $entry['external_voucher_id'],
+                                                               'file_name'     
        => "<a href='{$url}' target='_blank'>" . (string)$file . "</a>"
+                                                       );
+                                               }
+                                       }
+                               }
+                               catch (Exception $e)
+                               {
+
+                               }
+                       }
+                       $attachmen_def = array(
+                               array(
+                                       'key' => 'voucher_id',
+                                       'label' => 'key',
+                                       'hidden' => false
+                                       ),
+                               array(
+                                       'key' => 'file_name',
+                                       'label' => lang('attachments'),
+                                       'hidden' => false,
+                                       'sortable' => true,
+                                       )
+                               );
+
                        $invoice_def = array
                                (
                                array(
-                                       'key' => 'voucher_id',
-                                       'label' => lang('bilagsnr'),
+                                       'key' => 'external_voucher_id',
+                                       'label' => 'key',
                                        'sortable' => false,
                                        'value_footer' => lang('Sum')),
                                array(
+                                       'key' => 'voucher_id',
+                                       'label' => lang('bilagsnr'),
+                                       'sortable' => false),
+                               array(
                                        'key' => 'voucher_out_id',
                                        'hidden' => true),
                                array(
@@ -2636,7 +2746,7 @@
                                        'sortable' => false,
                                        'className' => 'right',
                                        'value_footer' => 
number_format($approved_amount, 2, $this->decimal_separator, '.')),
-                               array(
+/*                             array(
                                        'key' => 'period',
                                        'label' => lang('period'),
                                        'sortable' => false),
@@ -2647,7 +2757,7 @@
                                array(
                                        'key' => 'periodization_start',
                                        'label' => lang('periodization start'),
-                                       'sortable' => false),
+                                       'sortable' => false),*/
                                array(
                                        'key' => 'currency',
                                        'label' => lang('currency'),
@@ -2684,8 +2794,22 @@
                                )
                        );
 
+                       $datatable_def[] = array
+                               (
+                               'container' => 'datatable-container_8',
+                               'requestUrl' => "''",
+                               'data' => json_encode($attachmen_list),
+                               'ColumnDefs' => $attachmen_def,
+                               'config' => array(
+                                       array(
+                                               'disableFilter' => true),
+                                       array(
+                                               'disablePagination' => true)
+                               )
+                       );
 
 
+
                        // end invoice table
 
                        
//----------------------------------------------datatable settings--------
@@ -2735,6 +2859,7 @@
 //_debug_array($cat_select);die();
                        }
 
+                       $cat_select['disabled'] = !!$this->simple;
 
 //                     $this->cats->set_appname('property','.project');
 //                     $order_catetory = 
$this->cats->formatted_xslt_list(array('select_name' => 
'values[order_cat_id]','selected' => $ticket['order_cat_id']));

Modified: branches/Version-2_0-branch/property/inc/class.uiworkorder.inc.php
===================================================================
--- branches/Version-2_0-branch/property/inc/class.uiworkorder.inc.php  
2016-09-30 07:03:33 UTC (rev 15764)
+++ branches/Version-2_0-branch/property/inc/class.uiworkorder.inc.php  
2016-09-30 07:11:26 UTC (rev 15765)
@@ -1781,6 +1781,59 @@
                                $approved_amount += $entry['approved_amount'];
                        }
 
+                       if($invoices)
+                       {
+                               $invoice_config = 
CreateObject('admin.soconfig', $GLOBALS['phpgw']->locations->get_id('property', 
'.invoice'));
+                       }
+
+                       foreach ($invoices as $entry)
+                       {
+                               $directory_attachment = 
rtrim($invoice_config->config_data['import']['local_path'], '/') . 
'/attachment/' .$entry['external_voucher_id'];
+                               $attachmen_list = array();
+                               try
+                               {
+                                       $dir = new 
DirectoryIterator("$directory_attachment/");
+                                       if (is_object($dir))
+                                       {
+                                               foreach ($dir as $file)
+                                               {
+                                                       if ($file->isDot() || 
!$file->isFile() || !$file->isReadable())
+                                                       {
+                                                               continue;
+                                                       }
+
+                                                       $url = self::link(array(
+                                                               'menuaction'=> 
'property.uitts.show_attachment',
+                                                               'file_name' => 
urlencode((string)$file),
+                                                               'key'=> 
$entry['external_voucher_id']
+                                                               ));
+
+                                                       $attachmen_list[] = 
array(
+                                                               'voucher_id'    
=> $entry['external_voucher_id'],
+                                                               'file_name'     
        => "<a href='{$url}' target='_blank'>" . (string)$file . "</a>"
+                                                       );
+                                               }
+                                       }
+                               }
+                               catch (Exception $e)
+                               {
+
+                               }
+                       }
+                       $attachmen_def = array(
+                               array(
+                                       'key' => 'voucher_id',
+                                       'label' => 'key',
+                                       'hidden' => false
+                                       ),
+                               array(
+                                       'key' => 'file_name',
+                                       'label' => lang('attachments'),
+                                       'hidden' => false,
+                                       'sortable' => true,
+                                       )
+                               );
+
                        $invoice_def = array
                                (
                                array(
@@ -1876,6 +1929,19 @@
                                )
                        );
 
+                       $datatable_def[] = array(
+                               'container' => 'datatable-container_6',
+                               'requestUrl' => "''",
+                               'data' => json_encode($attachmen_list),
+                               'ColumnDefs' => $attachmen_def,
+                               'config' => array(
+                                       array(
+                                               'disableFilter' => true),
+                                       array(
+                                               'disablePagination' => true)
+                               )
+                       );
+
                        $datatable_def[] = array
                                (
                                'container' => 'datatable-container_3',

Modified: 
branches/Version-2_0-branch/property/inc/custom/default/BkBygg_exporter_varemottak_til_Agresso.php
===================================================================
--- 
branches/Version-2_0-branch/property/inc/custom/default/BkBygg_exporter_varemottak_til_Agresso.php
  2016-09-30 07:03:33 UTC (rev 15764)
+++ 
branches/Version-2_0-branch/property/inc/custom/default/BkBygg_exporter_varemottak_til_Agresso.php
  2016-09-30 07:11:26 UTC (rev 15765)
@@ -72,8 +72,8 @@
                                'order_id' => $values['order_id'],
                                'lines' => array(
                                        array(
-                                               'UnitCode' => 'STK',
-                                               'Quantity' => 
($received_amount),
+                                               'UnitCode' => 'SUM',
+                                               'Amount' => ($received_amount),
                                        )
                                )
                        );

Copied: branches/Version-2_0-branch/property/inc/import/UploadHandler.php (from 
rev 15764, trunk/property/inc/import/UploadHandler.php)
===================================================================
--- branches/Version-2_0-branch/property/inc/import/UploadHandler.php           
                (rev 0)
+++ branches/Version-2_0-branch/property/inc/import/UploadHandler.php   
2016-09-30 07:11:26 UTC (rev 15765)
@@ -0,0 +1,1393 @@
+<?php
+/*
+ * jQuery File Upload Plugin PHP Class
+ * https://github.com/blueimp/jQuery-File-Upload
+ *
+ * Copyright 2010, Sebastian Tschan
+ * https://blueimp.net
+ *
+ * Licensed under the MIT license:
+ * http://www.opensource.org/licenses/MIT
+ */
+
+class UploadHandler
+{
+
+    protected $options;
+
+    // PHP File Upload error message codes:
+    // http://php.net/manual/en/features.file-upload.errors.php
+    protected $error_messages = array(
+        1 => 'The uploaded file exceeds the upload_max_filesize directive in 
php.ini',
+        2 => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was 
specified in the HTML form',
+        3 => 'The uploaded file was only partially uploaded',
+        4 => 'No file was uploaded',
+        6 => 'Missing a temporary folder',
+        7 => 'Failed to write file to disk',
+        8 => 'A PHP extension stopped the file upload',
+        'post_max_size' => 'The uploaded file exceeds the post_max_size 
directive in php.ini',
+        'max_file_size' => 'File is too big',
+        'min_file_size' => 'File is too small',
+        'accept_file_types' => 'Filetype not allowed',
+        'max_number_of_files' => 'Maximum number of files exceeded',
+        'max_width' => 'Image exceeds maximum width',
+        'min_width' => 'Image requires a minimum width',
+        'max_height' => 'Image exceeds maximum height',
+        'min_height' => 'Image requires a minimum height',
+        'abort' => 'File upload aborted',
+        'image_resize' => 'Failed to resize image'
+    );
+
+    protected $image_objects = array();
+
+    public function __construct($options = null, $initialize = true, 
$error_messages = null) {
+        $this->response = array();
+        $this->options = array(
+            'script_url' => 
$this->get_full_url().'/'.$this->basename($this->get_server_var('SCRIPT_NAME')),
+            'upload_dir' => 
dirname($this->get_server_var('SCRIPT_FILENAME')).'/files/',
+            'upload_url' => $this->get_full_url().'/files/',
+            'input_stream' => 'php://input',
+            'user_dirs' => false,
+            'mkdir_mode' => 0755,
+            'param_name' => 'files',
+            // Set the following option to 'POST', if your server does not 
support
+            // DELETE requests. This is a parameter sent to the client:
+            'delete_type' => 'POST',
+            'access_control_allow_origin' => '*',
+            'access_control_allow_credentials' => false,
+            'access_control_allow_methods' => array(
+                'OPTIONS',
+                'HEAD',
+                'GET',
+                'POST',
+                'PUT',
+                'PATCH',
+                'DELETE'
+            ),
+            'access_control_allow_headers' => array(
+                'Content-Type',
+                'Content-Range',
+                'Content-Disposition'
+            ),
+            // By default, allow redirects to the referer protocol+host:
+            'redirect_allow_target' => '/^'.preg_quote(
+              parse_url($this->get_server_var('HTTP_REFERER'), PHP_URL_SCHEME)
+                .'://'
+                .parse_url($this->get_server_var('HTTP_REFERER'), PHP_URL_HOST)
+                .'/', // Trailing slash to not match subdomains by mistake
+              '/' // preg_quote delimiter param
+            ).'/',
+            // Enable to provide file downloads via GET requests to the PHP 
script:
+            //     1. Set to 1 to download files via readfile method through 
PHP
+            //     2. Set to 2 to send a X-Sendfile header for lighttpd/Apache
+            //     3. Set to 3 to send a X-Accel-Redirect header for nginx
+            // If set to 2 or 3, adjust the upload_url option to the base path 
of
+            // the redirect parameter, e.g. '/files/'.
+            'download_via_php' => false,
+            // Read files in chunks to avoid memory limits when 
download_via_php
+            // is enabled, set to 0 to disable chunked reading of files:
+            'readfile_chunk_size' => 10 * 1024 * 1024, // 10 MiB
+            // Defines which files can be displayed inline when downloaded:
+            'inline_file_types' => '/\.(gif|jpe?g|png)$/i',
+            // Defines which files (based on their names) are accepted for 
upload:
+            'accept_file_types' => '/.+$/i',
+            // The php.ini settings upload_max_filesize and post_max_size
+            // take precedence over the following max_file_size setting:
+            'max_file_size' => null,
+            'min_file_size' => 1,
+            // The maximum number of files for the upload directory:
+            'max_number_of_files' => null,
+            // Defines which files are handled as image files:
+            'image_file_types' => '/\.(gif|jpe?g|png)$/i',
+            // Use exif_imagetype on all files to correct file extensions:
+            'correct_image_extensions' => false,
+            // Image resolution restrictions:
+            'max_width' => null,
+            'max_height' => null,
+            'min_width' => 1,
+            'min_height' => 1,
+            // Set the following option to false to enable resumable uploads:
+            'discard_aborted_uploads' => true,
+            // Set to 0 to use the GD library to scale and orient images,
+            // set to 1 to use imagick (if installed, falls back to GD),
+            // set to 2 to use the ImageMagick convert binary directly:
+            'image_library' => 1,
+            // Uncomment the following to define an array of resource limits
+            // for imagick:
+            /*
+            'imagick_resource_limits' => array(
+                imagick::RESOURCETYPE_MAP => 32,
+                imagick::RESOURCETYPE_MEMORY => 32
+            ),
+            */
+            // Command or path for to the ImageMagick convert binary:
+            'convert_bin' => 'convert',
+            // Uncomment the following to add parameters in front of each
+            // ImageMagick convert call (the limit constraints seem only
+            // to have an effect if put in front):
+            /*
+            'convert_params' => '-limit memory 32MiB -limit map 32MiB',
+            */
+            // Command or path for to the ImageMagick identify binary:
+            'identify_bin' => 'identify',
+            'image_versions' => array(
+                // The empty image version key defines options for the 
original image:
+                '' => array(
+                    // Automatically rotate images based on EXIF meta data:
+                    'auto_orient' => true
+                ),
+                // Uncomment the following to create medium sized images:
+                /*
+                'medium' => array(
+                    'max_width' => 800,
+                    'max_height' => 600
+                ),
+                */
+                'thumbnail' => array(
+                    // Uncomment the following to use a defined directory for 
the thumbnails
+                    // instead of a subdirectory based on the version 
identifier.
+                    // Make sure that this directory doesn't allow execution 
of files if you
+                    // don't pose any restrictions on the type of uploaded 
files, e.g. by
+                    // copying the .htaccess file from the files directory for 
Apache:
+                    //'upload_dir' => 
dirname($this->get_server_var('SCRIPT_FILENAME')).'/thumb/',
+                    //'upload_url' => $this->get_full_url().'/thumb/',
+                    // Uncomment the following to force the max
+                    // dimensions and e.g. create square thumbnails:
+                    //'crop' => true,
+                    'max_width' => 80,
+                    'max_height' => 80
+                )
+            ),
+            'print_response' => true
+        );
+        if ($options) {
+            $this->options = $options + $this->options;
+        }
+        if ($error_messages) {
+            $this->error_messages = $error_messages + $this->error_messages;
+        }
+        if ($initialize) {
+            $this->initialize();
+        }
+    }
+
+    protected function initialize() {
+        switch ($this->get_server_var('REQUEST_METHOD')) {
+            case 'OPTIONS':
+            case 'HEAD':
+                $this->head();
+                break;
+            case 'GET':
+                $this->get($this->options['print_response']);
+                break;
+            case 'PATCH':
+            case 'PUT':
+            case 'POST':
+                $this->post($this->options['print_response']);
+                break;
+            case 'DELETE':
+                $this->delete($this->options['print_response']);
+                break;
+            default:
+                $this->header('HTTP/1.1 405 Method Not Allowed');
+        }
+    }
+
+    protected function get_full_url() {
+        $https = !empty($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 
'on') === 0 ||
+            !empty($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
+                strcasecmp($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') === 0;
+        return
+            ($https ? 'https://' : 'http://').
+            (!empty($_SERVER['REMOTE_USER']) ? $_SERVER['REMOTE_USER'].'@' : 
'').
+            (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 
($_SERVER['SERVER_NAME'].
+            ($https && $_SERVER['SERVER_PORT'] === 443 ||
+            $_SERVER['SERVER_PORT'] === 80 ? '' : 
':'.$_SERVER['SERVER_PORT']))).
+            substr($_SERVER['SCRIPT_NAME'],0, strrpos($_SERVER['SCRIPT_NAME'], 
'/'));
+    }
+
+    protected function get_user_id() {
+        @session_start();
+        return session_id();
+    }
+
+    protected function get_user_path() {
+        if ($this->options['user_dirs']) {
+            return $this->get_user_id().'/';
+        }
+        return '';
+    }
+
+    protected function get_upload_path($file_name = null, $version = null) {
+        $file_name = $file_name ? $file_name : '';
+        if (empty($version)) {
+            $version_path = '';
+        } else {
+            $version_dir = 
@$this->options['image_versions'][$version]['upload_dir'];
+            if ($version_dir) {
+                return $version_dir.$this->get_user_path().$file_name;
+            }
+            $version_path = $version.'/';
+        }
+        return $this->options['upload_dir'].$this->get_user_path()
+            .$version_path.$file_name;
+    }
+
+    protected function get_query_separator($url) {
+        return strpos($url, '?') === false ? '?' : '&';
+    }
+
+    protected function get_download_url($file_name, $version = null, $direct = 
false) {
+        if (!$direct && $this->options['download_via_php']) {
+            $url = $this->options['script_url']
+                .$this->get_query_separator($this->options['script_url'])
+                .$this->get_singular_param_name()
+                .'='.rawurlencode($file_name);
+            if ($version) {
+                $url .= '&version='.rawurlencode($version);
+            }
+            return $url.'&download=1';
+        }
+        if (empty($version)) {
+            $version_path = '';
+        } else {
+            $version_url = 
@$this->options['image_versions'][$version]['upload_url'];
+            if ($version_url) {
+                return 
$version_url.$this->get_user_path().rawurlencode($file_name);
+            }
+            $version_path = rawurlencode($version).'/';
+        }
+        return $this->options['upload_url'].$this->get_user_path()
+            .$version_path.rawurlencode($file_name);
+    }
+
+    protected function set_additional_file_properties($file) {
+        $file->deleteUrl = $this->options['script_url']
+            .$this->get_query_separator($this->options['script_url'])
+            .$this->get_singular_param_name()
+            .'='.rawurlencode($file->name);
+        $file->deleteType = $this->options['delete_type'];
+        if ($file->deleteType !== 'DELETE') {
+            $file->deleteUrl .= '&_method=DELETE';
+        }
+        if ($this->options['access_control_allow_credentials']) {
+            $file->deleteWithCredentials = true;
+        }
+    }
+
+    // Fix for overflowing signed 32 bit integers,
+    // works for sizes up to 2^32-1 bytes (4 GiB - 1):
+    protected function fix_integer_overflow($size) {
+        if ($size < 0) {
+            $size += 2.0 * (PHP_INT_MAX + 1);
+        }
+        return $size;
+    }
+
+    protected function get_file_size($file_path, $clear_stat_cache = false) {
+        if ($clear_stat_cache) {
+            if (version_compare(PHP_VERSION, '5.3.0') >= 0) {
+                clearstatcache(true, $file_path);
+            } else {
+                clearstatcache();
+            }
+        }
+        return $this->fix_integer_overflow(filesize($file_path));
+    }
+
+    protected function is_valid_file_object($file_name) {
+        $file_path = $this->get_upload_path($file_name);
+        if (is_file($file_path) && $file_name[0] !== '.') {
+            return true;
+        }
+        return false;
+    }
+
+    protected function get_file_object($file_name) {
+        if ($this->is_valid_file_object($file_name)) {
+            $file = new \stdClass();
+            $file->name = $file_name;
+            $file->size = $this->get_file_size(
+                $this->get_upload_path($file_name)
+            );
+            $file->url = $this->get_download_url($file->name);
+            foreach ($this->options['image_versions'] as $version => $options) 
{
+                if (!empty($version)) {
+                    if (is_file($this->get_upload_path($file_name, $version))) 
{
+                        $file->{$version.'Url'} = $this->get_download_url(
+                            $file->name,
+                            $version
+                        );
+                    }
+                }
+            }
+            $this->set_additional_file_properties($file);
+            return $file;
+        }
+        return null;
+    }
+
+    protected function get_file_objects($iteration_method = 'get_file_object') 
{
+        $upload_dir = $this->get_upload_path();
+        if (!is_dir($upload_dir)) {
+            return array();
+        }
+        return array_values(array_filter(array_map(
+            array($this, $iteration_method),
+            scandir($upload_dir)
+        )));
+    }
+
+    protected function count_file_objects() {
+        return count($this->get_file_objects('is_valid_file_object'));
+    }
+
+    protected function get_error_message($error) {
+        return isset($this->error_messages[$error]) ?
+            $this->error_messages[$error] : $error;
+    }
+
+    public function get_config_bytes($val) {
+        $val = trim($val);
+        $last = strtolower($val[strlen($val)-1]);
+        $val = (int)$val;
+        switch ($last) {
+            case 'g':
+                $val *= 1024;
+            case 'm':
+                $val *= 1024;
+            case 'k':
+                $val *= 1024;
+        }
+        return $this->fix_integer_overflow($val);
+    }
+
+    protected function validate($uploaded_file, $file, $error, $index) {
+        if ($error) {
+            $file->error = $this->get_error_message($error);
+            return false;
+        }
+        $content_length = $this->fix_integer_overflow(
+            (int)$this->get_server_var('CONTENT_LENGTH')
+        );
+        $post_max_size = $this->get_config_bytes(ini_get('post_max_size'));
+        if ($post_max_size && ($content_length > $post_max_size)) {
+            $file->error = $this->get_error_message('post_max_size');
+            return false;
+        }
+        if (!preg_match($this->options['accept_file_types'], $file->name)) {
+            $file->error = $this->get_error_message('accept_file_types');
+            return false;
+        }
+        if ($uploaded_file && is_uploaded_file($uploaded_file)) {
+            $file_size = $this->get_file_size($uploaded_file);
+        } else {
+            $file_size = $content_length;
+        }
+        if ($this->options['max_file_size'] && (
+                $file_size > $this->options['max_file_size'] ||
+                $file->size > $this->options['max_file_size'])
+            ) {
+            $file->error = $this->get_error_message('max_file_size');
+            return false;
+        }
+        if ($this->options['min_file_size'] &&
+            $file_size < $this->options['min_file_size']) {
+            $file->error = $this->get_error_message('min_file_size');
+            return false;
+        }
+        if (is_int($this->options['max_number_of_files']) &&
+                ($this->count_file_objects() >= 
$this->options['max_number_of_files']) &&
+                // Ignore additional chunks of existing files:
+                !is_file($this->get_upload_path($file->name))) {
+            $file->error = $this->get_error_message('max_number_of_files');
+            return false;
+        }
+        $max_width = @$this->options['max_width'];
+        $max_height = @$this->options['max_height'];
+        $min_width = @$this->options['min_width'];
+        $min_height = @$this->options['min_height'];
+        if (($max_width || $max_height || $min_width || $min_height)
+           && preg_match($this->options['image_file_types'], $file->name)) {
+            list($img_width, $img_height) = 
$this->get_image_size($uploaded_file);
+
+            // If we are auto rotating the image by default, do the checks on
+            // the correct orientation
+            if (
+                @$this->options['image_versions']['']['auto_orient'] &&
+                function_exists('exif_read_data') &&
+                ($exif = @exif_read_data($uploaded_file)) &&
+                (((int) @$exif['Orientation']) >= 5)
+            ) {
+                $tmp = $img_width;
+                $img_width = $img_height;
+                $img_height = $tmp;
+                unset($tmp);
+            }
+
+        }
+        if (!empty($img_width)) {
+            if ($max_width && $img_width > $max_width) {
+                $file->error = $this->get_error_message('max_width');
+                return false;
+            }
+            if ($max_height && $img_height > $max_height) {
+                $file->error = $this->get_error_message('max_height');
+                return false;
+            }
+            if ($min_width && $img_width < $min_width) {
+                $file->error = $this->get_error_message('min_width');
+                return false;
+            }
+            if ($min_height && $img_height < $min_height) {
+                $file->error = $this->get_error_message('min_height');
+                return false;
+            }
+        }
+        return true;
+    }
+
+    protected function upcount_name_callback($matches) {
+        $index = isset($matches[1]) ? ((int)$matches[1]) + 1 : 1;
+        $ext = isset($matches[2]) ? $matches[2] : '';
+        return ' ('.$index.')'.$ext;
+    }
+
+    protected function upcount_name($name) {
+        return preg_replace_callback(
+            '/(?:(?: \(([\d]+)\))?(\.[^.]+))?$/',
+            array($this, 'upcount_name_callback'),
+            $name,
+            1
+        );
+    }
+
+    protected function get_unique_filename($file_path, $name, $size, $type, 
$error,
+            $index, $content_range) {
+        while(is_dir($this->get_upload_path($name))) {
+            $name = $this->upcount_name($name);
+        }
+        // Keep an existing filename if this is part of a chunked upload:
+        $uploaded_bytes = $this->fix_integer_overflow((int)$content_range[1]);
+        while (is_file($this->get_upload_path($name))) {
+            if ($uploaded_bytes === $this->get_file_size(
+                    $this->get_upload_path($name))) {
+                break;
+            }
+            $name = $this->upcount_name($name);
+        }
+        return $name;
+    }
+
+    protected function fix_file_extension($file_path, $name, $size, $type, 
$error,
+            $index, $content_range) {
+        // Add missing file extension for known image types:
+        if (strpos($name, '.') === false &&
+                preg_match('/^image\/(gif|jpe?g|png)/', $type, $matches)) {
+            $name .= '.'.$matches[1];
+        }
+        if ($this->options['correct_image_extensions'] &&
+                function_exists('exif_imagetype')) {
+            switch (@exif_imagetype($file_path)){
+                case IMAGETYPE_JPEG:
+                    $extensions = array('jpg', 'jpeg');
+                    break;
+                case IMAGETYPE_PNG:
+                    $extensions = array('png');
+                    break;
+                case IMAGETYPE_GIF:
+                    $extensions = array('gif');
+                    break;
+            }
+            // Adjust incorrect image file extensions:
+            if (!empty($extensions)) {
+                $parts = explode('.', $name);
+                $extIndex = count($parts) - 1;
+                $ext = strtolower(@$parts[$extIndex]);
+                if (!in_array($ext, $extensions)) {
+                    $parts[$extIndex] = $extensions[0];
+                    $name = implode('.', $parts);
+                }
+            }
+        }
+        return $name;
+    }
+
+    protected function trim_file_name($file_path, $name, $size, $type, $error,
+            $index, $content_range) {
+        // Remove path information and dots around the filename, to prevent 
uploading
+        // into different directories or replacing hidden system files.
+        // Also remove control characters and spaces (\x00..\x20) around the 
filename:
+        $name = trim($this->basename(stripslashes($name)), ".\x00..\x20");
+        // Use a timestamp for empty filenames:
+        if (!$name) {
+            $name = str_replace('.', '-', microtime(true));
+        }
+        return $name;
+    }
+
+    protected function get_file_name($file_path, $name, $size, $type, $error,
+            $index, $content_range) {
+        $name = $this->trim_file_name($file_path, $name, $size, $type, $error,
+            $index, $content_range);
+        return $this->get_unique_filename(
+            $file_path,
+            $this->fix_file_extension($file_path, $name, $size, $type, $error,
+                $index, $content_range),
+            $size,
+            $type,
+            $error,
+            $index,
+            $content_range
+        );
+    }
+
+    protected function get_scaled_image_file_paths($file_name, $version) {
+        $file_path = $this->get_upload_path($file_name);
+        if (!empty($version)) {
+            $version_dir = $this->get_upload_path(null, $version);
+            if (!is_dir($version_dir)) {
+                mkdir($version_dir, $this->options['mkdir_mode'], true);
+            }
+            $new_file_path = $version_dir.'/'.$file_name;
+        } else {
+            $new_file_path = $file_path;
+        }
+        return array($file_path, $new_file_path);
+    }
+
+    protected function gd_get_image_object($file_path, $func, $no_cache = 
false) {
+        if (empty($this->image_objects[$file_path]) || $no_cache) {
+            $this->gd_destroy_image_object($file_path);
+            $this->image_objects[$file_path] = $func($file_path);
+        }
+        return $this->image_objects[$file_path];
+    }
+
+    protected function gd_set_image_object($file_path, $image) {
+        $this->gd_destroy_image_object($file_path);
+        $this->image_objects[$file_path] = $image;
+    }
+
+    protected function gd_destroy_image_object($file_path) {
+        $image = (isset($this->image_objects[$file_path])) ? 
$this->image_objects[$file_path] : null ;
+        return $image && imagedestroy($image);
+    }
+
+    protected function gd_imageflip($image, $mode) {
+        if (function_exists('imageflip')) {
+            return imageflip($image, $mode);
+        }
+        $new_width = $src_width = imagesx($image);
+        $new_height = $src_height = imagesy($image);
+        $new_img = imagecreatetruecolor($new_width, $new_height);
+        $src_x = 0;
+        $src_y = 0;
+        switch ($mode) {
+            case '1': // flip on the horizontal axis
+                $src_y = $new_height - 1;
+                $src_height = -$new_height;
+                break;
+            case '2': // flip on the vertical axis
+                $src_x  = $new_width - 1;
+                $src_width = -$new_width;
+                break;
+            case '3': // flip on both axes
+                $src_y = $new_height - 1;
+                $src_height = -$new_height;
+                $src_x  = $new_width - 1;
+                $src_width = -$new_width;
+                break;
+            default:
+                return $image;
+        }
+        imagecopyresampled(
+            $new_img,
+            $image,
+            0,
+            0,
+            $src_x,
+            $src_y,
+            $new_width,
+            $new_height,
+            $src_width,
+            $src_height
+        );
+        return $new_img;
+    }
+
+    protected function gd_orient_image($file_path, $src_img) {
+        if (!function_exists('exif_read_data')) {
+            return false;
+        }
+        $exif = @exif_read_data($file_path);
+        if ($exif === false) {
+            return false;
+        }
+        $orientation = (int)@$exif['Orientation'];
+        if ($orientation < 2 || $orientation > 8) {
+            return false;
+        }
+        switch ($orientation) {
+            case 2:
+                $new_img = $this->gd_imageflip(
+                    $src_img,
+                    defined('IMG_FLIP_VERTICAL') ? IMG_FLIP_VERTICAL : 2
+                );
+                break;
+            case 3:
+                $new_img = imagerotate($src_img, 180, 0);
+                break;
+            case 4:
+                $new_img = $this->gd_imageflip(
+                    $src_img,
+                    defined('IMG_FLIP_HORIZONTAL') ? IMG_FLIP_HORIZONTAL : 1
+                );
+                break;
+            case 5:
+                $tmp_img = $this->gd_imageflip(
+                    $src_img,
+                    defined('IMG_FLIP_HORIZONTAL') ? IMG_FLIP_HORIZONTAL : 1
+                );
+                $new_img = imagerotate($tmp_img, 270, 0);
+                imagedestroy($tmp_img);
+                break;
+            case 6:
+                $new_img = imagerotate($src_img, 270, 0);
+                break;
+            case 7:
+                $tmp_img = $this->gd_imageflip(
+                    $src_img,
+                    defined('IMG_FLIP_VERTICAL') ? IMG_FLIP_VERTICAL : 2
+                );
+                $new_img = imagerotate($tmp_img, 270, 0);
+                imagedestroy($tmp_img);
+                break;
+            case 8:
+                $new_img = imagerotate($src_img, 90, 0);
+                break;
+            default:
+                return false;
+        }
+        $this->gd_set_image_object($file_path, $new_img);
+        return true;
+    }
+
+    protected function gd_create_scaled_image($file_name, $version, $options) {
+        if (!function_exists('imagecreatetruecolor')) {
+            error_log('Function not found: imagecreatetruecolor');
+            return false;
+        }
+        list($file_path, $new_file_path) =
+            $this->get_scaled_image_file_paths($file_name, $version);
+        $type = strtolower(substr(strrchr($file_name, '.'), 1));
+        switch ($type) {
+            case 'jpg':
+            case 'jpeg':
+                $src_func = 'imagecreatefromjpeg';
+                $write_func = 'imagejpeg';
+                $image_quality = isset($options['jpeg_quality']) ?
+                    $options['jpeg_quality'] : 75;
+                break;
+            case 'gif':
+                $src_func = 'imagecreatefromgif';
+                $write_func = 'imagegif';
+                $image_quality = null;
+                break;
+            case 'png':
+                $src_func = 'imagecreatefrompng';
+                $write_func = 'imagepng';
+                $image_quality = isset($options['png_quality']) ?
+                    $options['png_quality'] : 9;
+                break;
+            default:
+                return false;
+        }
+        $src_img = $this->gd_get_image_object(
+            $file_path,
+            $src_func,
+            !empty($options['no_cache'])
+        );
+        $image_oriented = false;
+        if (!empty($options['auto_orient']) && $this->gd_orient_image(
+                $file_path,
+                $src_img
+            )) {
+            $image_oriented = true;
+            $src_img = $this->gd_get_image_object(
+                $file_path,
+                $src_func
+            );
+        }
+        $max_width = $img_width = imagesx($src_img);
+        $max_height = $img_height = imagesy($src_img);
+        if (!empty($options['max_width'])) {
+            $max_width = $options['max_width'];
+        }
+        if (!empty($options['max_height'])) {
+            $max_height = $options['max_height'];
+        }
+        $scale = min(
+            $max_width / $img_width,
+            $max_height / $img_height
+        );
+        if ($scale >= 1) {
+            if ($image_oriented) {
+                return $write_func($src_img, $new_file_path, $image_quality);
+            }
+            if ($file_path !== $new_file_path) {
+                return copy($file_path, $new_file_path);
+            }
+            return true;
+        }
+        if (empty($options['crop'])) {
+            $new_width = $img_width * $scale;
+            $new_height = $img_height * $scale;
+            $dst_x = 0;
+            $dst_y = 0;
+            $new_img = imagecreatetruecolor($new_width, $new_height);
+        } else {
+            if (($img_width / $img_height) >= ($max_width / $max_height)) {
+                $new_width = $img_width / ($img_height / $max_height);
+                $new_height = $max_height;
+            } else {
+                $new_width = $max_width;
+                $new_height = $img_height / ($img_width / $max_width);
+            }
+            $dst_x = 0 - ($new_width - $max_width) / 2;
+            $dst_y = 0 - ($new_height - $max_height) / 2;
+            $new_img = imagecreatetruecolor($max_width, $max_height);
+        }
+        // Handle transparency in GIF and PNG images:
+        switch ($type) {
+            case 'gif':
+            case 'png':
+                imagecolortransparent($new_img, imagecolorallocate($new_img, 
0, 0, 0));
+            case 'png':
+                imagealphablending($new_img, false);
+                imagesavealpha($new_img, true);
+                break;
+        }
+        $success = imagecopyresampled(
+            $new_img,
+            $src_img,
+            $dst_x,
+            $dst_y,
+            0,
+            0,
+            $new_width,
+            $new_height,
+            $img_width,
+            $img_height
+        ) && $write_func($new_img, $new_file_path, $image_quality);
+        $this->gd_set_image_object($file_path, $new_img);
+        return $success;
+    }
+
+    protected function imagick_get_image_object($file_path, $no_cache = false) 
{
+        if (empty($this->image_objects[$file_path]) || $no_cache) {
+            $this->imagick_destroy_image_object($file_path);
+            $image = new \Imagick();
+            if (!empty($this->options['imagick_resource_limits'])) {
+                foreach ($this->options['imagick_resource_limits'] as $type => 
$limit) {
+                    $image->setResourceLimit($type, $limit);
+                }
+            }
+            $image->readImage($file_path);
+            $this->image_objects[$file_path] = $image;
+        }
+        return $this->image_objects[$file_path];
+    }
+
+    protected function imagick_set_image_object($file_path, $image) {
+        $this->imagick_destroy_image_object($file_path);
+        $this->image_objects[$file_path] = $image;
+    }
+
+    protected function imagick_destroy_image_object($file_path) {
+        $image = (isset($this->image_objects[$file_path])) ? 
$this->image_objects[$file_path] : null ;
+        return $image && $image->destroy();
+    }
+
+    protected function imagick_orient_image($image) {
+        $orientation = $image->getImageOrientation();
+        $background = new \ImagickPixel('none');
+        switch ($orientation) {
+            case \imagick::ORIENTATION_TOPRIGHT: // 2
+                $image->flopImage(); // horizontal flop around y-axis
+                break;
+            case \imagick::ORIENTATION_BOTTOMRIGHT: // 3
+                $image->rotateImage($background, 180);
+                break;
+            case \imagick::ORIENTATION_BOTTOMLEFT: // 4
+                $image->flipImage(); // vertical flip around x-axis
+                break;
+            case \imagick::ORIENTATION_LEFTTOP: // 5
+                $image->flopImage(); // horizontal flop around y-axis
+                $image->rotateImage($background, 270);
+                break;
+            case \imagick::ORIENTATION_RIGHTTOP: // 6
+                $image->rotateImage($background, 90);
+                break;
+            case \imagick::ORIENTATION_RIGHTBOTTOM: // 7
+                $image->flipImage(); // vertical flip around x-axis
+                $image->rotateImage($background, 270);
+                break;
+            case \imagick::ORIENTATION_LEFTBOTTOM: // 8
+                $image->rotateImage($background, 270);
+                break;
+            default:
+                return false;
+        }
+        $image->setImageOrientation(\imagick::ORIENTATION_TOPLEFT); // 1
+        return true;
+    }
+
+    protected function imagick_create_scaled_image($file_name, $version, 
$options) {
+        list($file_path, $new_file_path) =
+            $this->get_scaled_image_file_paths($file_name, $version);
+        $image = $this->imagick_get_image_object(
+            $file_path,
+            !empty($options['crop']) || !empty($options['no_cache'])
+        );
+        if ($image->getImageFormat() === 'GIF') {
+            // Handle animated GIFs:
+            $images = $image->coalesceImages();
+            foreach ($images as $frame) {
+                $image = $frame;
+                $this->imagick_set_image_object($file_name, $image);
+                break;
+            }
+        }
+        $image_oriented = false;
+        if (!empty($options['auto_orient'])) {
+            $image_oriented = $this->imagick_orient_image($image);
+        }
+        $new_width = $max_width = $img_width = $image->getImageWidth();
+        $new_height = $max_height = $img_height = $image->getImageHeight();
+        if (!empty($options['max_width'])) {
+            $new_width = $max_width = $options['max_width'];
+        }
+        if (!empty($options['max_height'])) {
+            $new_height = $max_height = $options['max_height'];
+        }
+        if (!($image_oriented || $max_width < $img_width || $max_height < 
$img_height)) {
+            if ($file_path !== $new_file_path) {
+                return copy($file_path, $new_file_path);
+            }
+            return true;
+        }
+        $crop = !empty($options['crop']);
+        if ($crop) {
+            $x = 0;
+            $y = 0;
+            if (($img_width / $img_height) >= ($max_width / $max_height)) {
+                $new_width = 0; // Enables proportional scaling based on 
max_height
+                $x = ($img_width / ($img_height / $max_height) - $max_width) / 
2;
+            } else {
+                $new_height = 0; // Enables proportional scaling based on 
max_width
+                $y = ($img_height / ($img_width / $max_width) - $max_height) / 
2;
+            }
+        }
+        $success = $image->resizeImage(
+            $new_width,
+            $new_height,
+            isset($options['filter']) ? $options['filter'] : 
\imagick::FILTER_LANCZOS,
+            isset($options['blur']) ? $options['blur'] : 1,
+            $new_width && $new_height // fit image into constraints if not to 
be cropped
+        );
+        if ($success && $crop) {
+            $success = $image->cropImage(
+                $max_width,
+                $max_height,
+                $x,
+                $y
+            );
+            if ($success) {
+                $success = $image->setImagePage($max_width, $max_height, 0, 0);
+            }
+        }
+        $type = strtolower(substr(strrchr($file_name, '.'), 1));
+        switch ($type) {
+            case 'jpg':
+            case 'jpeg':
+                if (!empty($options['jpeg_quality'])) {
+                    $image->setImageCompression(\imagick::COMPRESSION_JPEG);
+                    
$image->setImageCompressionQuality($options['jpeg_quality']);
+                }
+                break;
+        }
+        if (!empty($options['strip'])) {
+            $image->stripImage();
+        }
+        return $success && $image->writeImage($new_file_path);
+    }
+
+    protected function imagemagick_create_scaled_image($file_name, $version, 
$options) {
+        list($file_path, $new_file_path) =
+            $this->get_scaled_image_file_paths($file_name, $version);
+        $resize = @$options['max_width']
+            .(empty($options['max_height']) ? '' : 'X'.$options['max_height']);
+        if (!$resize && empty($options['auto_orient'])) {
+            if ($file_path !== $new_file_path) {
+                return copy($file_path, $new_file_path);
+            }
+            return true;
+        }
+        $cmd = $this->options['convert_bin'];
+        if (!empty($this->options['convert_params'])) {
+            $cmd .= ' '.$this->options['convert_params'];
+        }
+        $cmd .= ' '.escapeshellarg($file_path);
+        if (!empty($options['auto_orient'])) {
+            $cmd .= ' -auto-orient';
+        }
+        if ($resize) {
+            // Handle animated GIFs:
+            $cmd .= ' -coalesce';
+            if (empty($options['crop'])) {
+                $cmd .= ' -resize '.escapeshellarg($resize.'>');
+            } else {
+                $cmd .= ' -resize '.escapeshellarg($resize.'^');
+                $cmd .= ' -gravity center';
+                $cmd .= ' -crop '.escapeshellarg($resize.'+0+0');
+            }
+            // Make sure the page dimensions are correct (fixes offsets of 
animated GIFs):
+            $cmd .= ' +repage';
+        }
+        if (!empty($options['convert_params'])) {
+            $cmd .= ' '.$options['convert_params'];
+        }
+        $cmd .= ' '.escapeshellarg($new_file_path);
+        exec($cmd, $output, $error);

@@ Diff output truncated at 153600 characters. @@



reply via email to

[Prev in Thread] Current Thread [Next in Thread]