Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Open
LU Names
Commits
2c9feeaa
Commit
2c9feeaa
authored
Nov 26, 2020
by
Dainis Abols
Browse files
Names initial public
1.0.0
parents
Pipeline
#149
failed with stages
in 0 seconds
Changes
53
Pipelines
2
Hide whitespace changes
Inline
Side-by-side
Classes/Command/ImportCommand.php
0 → 100644
View file @
2c9feeaa
<?php
namespace
Lu\LuNames\Command
;
use
PhpOffice\PhpSpreadsheet\Reader\Xlsx
;
use
Symfony\Component\Console\Command\Command
;
use
Symfony\Component\Console\Input\InputArgument
;
use
Symfony\Component\Console\Input\InputInterface
;
use
Symfony\Component\Console\Output\OutputInterface
;
use
Symfony\Component\Console\Style\SymfonyStyle
;
use
TYPO3\CMS\Backend\Utility\BackendUtility
;
use
TYPO3\CMS\Core\Configuration\ExtensionConfiguration
;
use
TYPO3\CMS\Core\Core\Bootstrap
;
use
TYPO3\CMS\Core\DataHandling\DataHandler
;
use
TYPO3\CMS\Core\Resource\ResourceFactory
;
use
TYPO3\CMS\Core\Utility\GeneralUtility
;
class
ImportCommand
extends
Command
{
/**
* Configure the command by defining the name, options and arguments
*/
protected
function
configure
()
{
$this
->
setDescription
(
'Imports data from xlsx.'
)
->
addArgument
(
'xlsxFile'
,
InputArgument
::
REQUIRED
,
'Xlsx file.'
);
}
/**
* Executes the command for import
*
* @param InputInterface $input
* @param OutputInterface $output
*/
protected
function
execute
(
InputInterface
$input
,
OutputInterface
$output
)
{
Bootstrap
::
initializeBackendAuthentication
();
Bootstrap
::
initializeBackendUser
();
$config
=
require
'/home/portal/typo3/typo3conf/LocalConfiguration.php'
;
$inputFile
=
$input
->
getArgument
(
'xlsxFile'
);
$storagePid
=
GeneralUtility
::
makeInstance
(
ExtensionConfiguration
::
class
)
->
get
(
'lu_names'
)[
'storage_page_id'
];
$db
=
new
\
PDO
(
'mysql:host='
.
$config
[
'DB'
][
'Connections'
][
'Default'
][
'host'
]
.
';dbname='
.
$config
[
'DB'
][
'Connections'
][
'Default'
][
'dbname'
],
$config
[
'DB'
][
'Connections'
][
'Default'
][
'user'
],
$config
[
'DB'
][
'Connections'
][
'Default'
][
'password'
]);
$reader
=
new
Xlsx
();
$reader
->
setReadDataOnly
(
true
);
$reader
->
setReadEmptyCells
(
false
);
$spreadsheet
=
$reader
->
load
(
$inputFile
);
$rawData
=
$spreadsheet
->
getActiveSheet
()
->
toArray
(
null
,
true
,
true
,
true
);
// Remove title row
array_slice
(
array_shift
(
$rawData
),
0
,
21
);
$formattedData
=
[];
// Get only necessary columns
foreach
(
$rawData
as
$row
=>
$value
)
{
$formattedData
[]
=
array_slice
(
$value
,
0
,
21
);
}
$values
=
[];
foreach
(
$formattedData
as
$key
=>
$row
)
{
$occupationId
=
0
;
$familyStatusId
=
0
;
$sources
=
[];
$personId
=
0
;
foreach
(
$row
as
$cell
=>
$data
)
{
// Save photo id
if
(
$cell
==
'A'
)
{
$personId
=
$data
;
unset
(
$row
[
$cell
]);
}
// Split birth/death date
if
(
$cell
==
'H'
||
$cell
==
'J'
)
{
// Default values
$date
=
[
0
,
0
,
0
];
$temp
=
[];
if
(
strlen
(
$row
[
$cell
])
!=
0
)
{
$temp
=
explode
(
" "
,
$row
[
$cell
]);
}
unset
(
$row
[
$cell
]);
array_splice
(
$date
,
0
,
count
(
$temp
),
$temp
);
if
(
$cell
==
'H'
)
{
array_splice
(
$row
,
8
,
0
,
$date
);
}
else
{
array_splice
(
$row
,
10
,
0
,
$date
);
}
}
// Convert gender value to expected lower case
if
(
$cell
==
'P'
)
{
$row
[
$cell
]
=
strtolower
(
$data
);
}
// Create and link locations
if
(
$cell
==
'I'
||
$cell
==
'K'
||
$cell
==
'L'
||
$cell
==
'M'
||
$cell
==
'N'
)
{
$locations
=
explode
(
', '
,
$data
);
$locationIds
=
[];
foreach
(
$locations
as
$key
=>
$location
)
{
$findLocation
=
$db
->
prepare
(
"SELECT uid FROM tx_lunames_domain_model_location WHERE title = '"
.
$location
.
"' AND deleted = 0"
);
$findLocation
->
execute
();
// Add new location if it doesn't exist
if
(
$findLocation
->
rowCount
()
==
0
&&
!
empty
(
$location
))
{
$locationInsert
=
'('
.
$storagePid
.
', '
.
time
()
.
', '
.
time
()
.
', '
.
'0, '
.
'0, '
.
"'"
.
$location
.
"'"
.
')'
;
$query
=
"INSERT INTO tx_lunames_domain_model_location (pid, tstamp, crdate, cruser_id, deleted, title) VALUES "
.
$locationInsert
;
$addLocation
=
$db
->
prepare
(
$query
);
$addLocation
->
execute
();
// Get new record uid
$findLocation
->
execute
();
}
if
(
!
empty
(
$location
))
{
$result
=
$findLocation
->
fetch
();
$locationIds
[]
=
$result
[
'uid'
];
}
else
{
$locationIds
[]
=
''
;
}
}
$row
[
$cell
]
=
implode
(
','
,
$locationIds
);
}
// Create and link occupation
if
(
$cell
==
'O'
)
{
$findOccupation
=
$db
->
prepare
(
"SELECT uid FROM tx_lunames_domain_model_occupation WHERE title = '"
.
$data
.
"' AND deleted = 0"
);
$findOccupation
->
execute
();
// Add new occupation if it doesn't exist
if
(
$findOccupation
->
rowCount
()
==
0
&&
!
empty
(
$data
))
{
$occupationInsert
=
'('
.
$storagePid
.
', '
.
time
()
.
', '
.
time
()
.
', '
.
'0, '
.
'0, '
.
"'"
.
$data
.
"'"
.
')'
;
$query
=
"INSERT INTO tx_lunames_domain_model_occupation (pid, tstamp, crdate, cruser_id, deleted, title) VALUES "
.
$occupationInsert
;
$addOccupation
=
$db
->
prepare
(
$query
);
$addOccupation
->
execute
();
// Get new record uid
$findOccupation
->
execute
();
}
if
(
!
empty
(
$data
))
{
$occupationId
=
$findOccupation
->
fetch
()[
'uid'
];
}
unset
(
$row
[
$cell
]);
}
// Create and link family status
if
(
$cell
==
'Q'
)
{
$findFamilyStatus
=
$db
->
prepare
(
"SELECT uid FROM tx_lunames_domain_model_family_status WHERE title = '"
.
$data
.
"' AND deleted = 0"
);
$findFamilyStatus
->
execute
();
// Add new family status if it doesn't exist
if
(
$findFamilyStatus
->
rowCount
()
==
0
&&
!
empty
(
$data
))
{
$familyStatusInsert
=
'('
.
$storagePid
.
', '
.
time
()
.
', '
.
time
()
.
', '
.
'0, '
.
'0, '
.
"'"
.
$data
.
"'"
.
')'
;
$query
=
"INSERT INTO tx_lunames_domain_model_family_status (pid, tstamp, crdate, cruser_id, deleted, title) VALUES "
.
$familyStatusInsert
;
$addFamilyStatus
=
$db
->
prepare
(
$query
);
$addFamilyStatus
->
execute
();
// Get new record uid
$findFamilyStatus
->
execute
();
}
if
(
!
empty
(
$data
))
{
$familyStatusId
=
$findFamilyStatus
->
fetch
()[
'uid'
];
}
unset
(
$row
[
$cell
]);
}
// Save source ids
if
(
$cell
==
'T'
)
{
$sources
=
$data
;
unset
(
$row
[
$cell
]);
}
}
$insert
=
'('
.
$personId
.
', '
.
$storagePid
.
', '
.
time
()
.
', '
.
time
()
.
', '
.
'0, '
.
'0, '
;
$insert
.
=
"'"
.
implode
(
"','"
,
$row
)
.
"',"
;
$insert
.
=
$occupationId
.
","
.
$familyStatusId
.
")"
;
$values
[]
=
[
'sources'
=>
$sources
,
'insert'
=>
$insert
,
'personId'
=>
$personId
];
}
// Construct person insert values
$insertValues
=
[];
foreach
(
$values
as
$value
)
{
$insertValues
[]
=
$value
[
'insert'
];
}
// Add persons
$statement
=
$db
->
prepare
(
'INSERT INTO tx_lunames_domain_model_person (uid, pid, tstamp, crdate, cruser_id, deleted, family_name,
maiden_name, other_name, given_name, father, mother, place_of_birth, year_of_birth, day_of_birth, month_of_birth,
year_of_death, day_of_death, month_of_death, place_of_death, region, prewar_residence, war_residence, gender, spouse, fate,
comments, occupation,family_status)
VALUES '
.
implode
(
','
,
$insertValues
)
);
$statement
->
execute
();
// Construct source insert values
$insertValues
=
[];
foreach
(
$values
as
$value
)
{
$sources
=
explode
(
' '
,
$value
[
'sources'
]);
foreach
(
$sources
as
$sourceKey
=>
$source
)
{
$insert
=
''
;
$source
=
(
int
)
ltrim
(
rtrim
(
$source
,
']'
),
'['
);
$sorting
=
$sourceKey
+
1
;
$insert
=
'('
.
$value
[
'personId'
]
.
', '
.
$source
.
', '
.
$sorting
.
', 0)'
;
$insertValues
[]
=
$insert
;
}
}
// Link sources
$statement
=
$db
->
prepare
(
'INSERT INTO tx_lunames_domain_model_related_source (uid_local, uid_foreign, sorting, sorting_foreign) VALUES '
.
implode
(
','
,
$insertValues
)
);
$statement
->
execute
();
// Link images
$resourceFactory
=
ResourceFactory
::
getInstance
();
$storage
=
$resourceFactory
->
getDefaultStorage
();
$folder
=
$storage
->
getFolder
(
'/user_upload/names/'
);
$files
=
$folder
->
getFiles
();
$fileIds
=
[];
// Get file uid and corresponding person id from file name
foreach
(
$files
as
$file
)
{
$fileIds
[]
=
[
'uid'
=>
$file
->
getUid
(),
'personId'
=>
explode
(
'_'
,
$file
->
getName
())[
0
]];
}
$dataHandler
=
GeneralUtility
::
makeInstance
(
DataHandler
::
class
);
$dataHandler
->
BE_USER
=
$GLOBALS
[
'BE_USER'
];
$dataHandler
->
BE_USER
->
user
[
'admin'
]
=
1
;
$dataHandler
->
userid
=
$GLOBALS
[
'BE_USER'
]
->
user
[
'uid'
];
$dataHandler
->
admin
=
true
;
$dataHandler
->
bypassWorkspaceRestrictions
=
true
;
foreach
(
$values
as
$value
)
{
foreach
(
$fileIds
as
$fileId
)
{
if
(
$fileId
[
'personId'
]
==
$value
[
'personId'
])
{
$fileObject
=
$resourceFactory
->
getFileObject
((
int
)
$fileId
[
'uid'
]);
$contentElement
=
BackendUtility
::
getRecord
(
'tx_lunames_domain_model_person'
,
$value
[
'personId'
]
);
$newId
=
'NEWrandomstr'
;
// Gets replaced by new record uid
$data
=
[];
$data
[
'sys_file_reference'
][
$newId
]
=
[
'table_local'
=>
'sys_file'
,
'uid_local'
=>
$fileObject
->
getUid
(),
'tablenames'
=>
'tx_lunames_domain_model_person'
,
'uid_foreign'
=>
$contentElement
[
'uid'
],
'fieldname'
=>
'photo'
,
'pid'
=>
$contentElement
[
'pid'
],
];
$data
[
'tx_lunames_domain_model_person'
][
$contentElement
[
'uid'
]]
=
[
'pid'
=>
$storagePid
,
'photo'
=>
$newId
];
$dataHandler
->
start
(
$data
,
[]);
$dataHandler
->
process_datamap
();
}
}
}
return
0
;
}
}
Classes/Controller/FrontController.php
0 → 100644
View file @
2c9feeaa
<?php
namespace
Lu\LuNames\Controller
;
use
Lu\LuNames\Domain\Model\Person
;
use
Lu\LuNames\Domain\Repository\PersonRepository
;
use
TYPO3\CMS\Core\Resource\FileRepository
;
use
TYPO3\CMS\Core\Utility\GeneralUtility
;
use
TYPO3\CMS\Extbase\Mvc\Controller\ActionController
;
/**
* Class FrontController
*
* @package Lu\LuNames\Controller
*/
class
FrontController
extends
ActionController
{
/**
* @var \Lu\LuNames\Domain\Repository\PersonRepository
*/
private
PersonRepository
$personRepository
;
/**
* @param \Lu\LuNames\Domain\Repository\PersonRepository $personRepository
*/
public
function
injectPersonRepository
(
PersonRepository
$personRepository
)
{
$this
->
personRepository
=
$personRepository
;
}
/**
* Detail action
*/
public
function
detailAction
()
{
$uid
=
$this
->
request
->
getArgument
(
'uid'
);
$person
=
$this
->
personRepository
->
findByUid
(
$uid
);
$assign
=
[
'photo'
=>
$this
->
getPhoto
(
$uid
),
'birthDate'
=>
$this
->
formatDate
(
$person
->
getYearOfBirth
(),
$person
->
getMonthOfBirth
(),
$person
->
getDayOfBirth
()),
'deathDate'
=>
$this
->
formatDate
(
$person
->
getYearOfDeath
(),
$person
->
getMonthOfDeath
(),
$person
->
getDayOfDeath
()),
'person'
=>
$person
,
];
$this
->
view
->
assignMultiple
(
$assign
);
}
/**
* Get photo from UID
*
* @param $uid
*
* @return \TYPO3\CMS\Core\Resource\FileReference
*/
private
function
getPhoto
(
$uid
)
{
$personTable
=
GeneralUtility
::
makeInstance
(
Person
::
class
)
->
getTableName
();
$fileRepository
=
GeneralUtility
::
makeInstance
(
FileRepository
::
class
);
return
$fileRepository
->
findByRelation
(
$personTable
,
'photo'
,
$uid
);
}
/**
* @param $year
* @param $month
* @param $day
*
* @return string
*/
private
function
formatDate
(
$year
,
$month
,
$day
):
string
{
return
(
$year
??
''
)
.
(
$month
?
'-'
.
sprintf
(
"%02d"
,
$month
)
:
''
)
.
(
$day
?
'-'
.
sprintf
(
"%02d"
,
$day
)
:
''
);
}
}
Classes/Controller/PersonController.php
0 → 100644
View file @
2c9feeaa
<?php
namespace
Lu\LuNames\Controller
;
use
TYPO3\CMS\Backend\Template\Components\ButtonBar
;
use
TYPO3\CMS\Backend\Utility\BackendUtility
;
use
TYPO3\CMS\Backend\View\BackendTemplateView
;
use
TYPO3\CMS\Core\Configuration\ExtensionConfiguration
;
use
TYPO3\CMS\Core\FormProtection\FormProtectionFactory
;
use
TYPO3\CMS\Core\Imaging\Icon
;
use
TYPO3\CMS\Core\Imaging\IconFactory
;
use
TYPO3\CMS\Core\Page\PageRenderer
;
use
TYPO3\CMS\Core\Utility\GeneralUtility
;
use
TYPO3\CMS\Core\Utility\HttpUtility
;
use
TYPO3\CMS\Core\Utility\MathUtility
;
use
TYPO3\CMS\Extbase\Mvc\Controller\ActionController
;
use
TYPO3\CMS\Extbase\Mvc\View\ViewInterface
;
use
TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder
;
use
TYPO3\CMS\Backend\Routing\UriBuilder
as
BackendUriBuilder
;
use
TYPO3\CMS\Recordlist\RecordList\DatabaseRecordList
;
/**
* Class PersonController
*
* @package Lu\LuNames\Controller
*/
class
PersonController
extends
ActionController
{
/**
* @var int
*/
private
int
$storagePageId
=
0
;
/**
* @var array
*/
private
$pageInformation
=
[];
/**
* @var BackendTemplateView
*/
protected
$defaultViewObjectName
=
BackendTemplateView
::
class
;
/**
* @param \TYPO3\CMS\Extbase\Mvc\View\ViewInterface $view
*/
protected
function
initializeView
(
ViewInterface
$view
)
{
parent
::
initializeView
(
$view
);
if
(
$view
instanceof
BackendTemplateView
)
{
$view
->
getModuleTemplate
()
->
getPageRenderer
()
->
loadRequireJsModule
(
'TYPO3/CMS/Backend/Modal'
);
$view
->
getModuleTemplate
()
->
getPageRenderer
()
->
loadRequireJsModule
(
'TYPO3/CMS/Backend/ToggleSearchToolbox'
);
}
$config
=
GeneralUtility
::
makeInstance
(
ExtensionConfiguration
::
class
)
->
get
(
'lu_names'
);
$this
->
storagePageId
=
(
int
)
$config
[
'storage_page_id'
];
$this
->
pageInformation
=
BackendUtility
::
readPageAccess
(
$this
->
storagePageId
,
''
);
}
/**
* List Action
*
* @return void
*/
public
function
listAction
()
{
$this
->
createButtons
();
$args
=
GeneralUtility
::
_GP
(
'tx_lunames_web_lunamesnames'
);
// Initialize the dbList object:
$dbList
=
GeneralUtility
::
makeInstance
(
DatabaseRecordList
::
class
);
$dbList
->
script
=
GeneralUtility
::
getIndpEnv
(
'REQUEST_URI'
);
$dbList
->
allFields
=
1
;
$dbList
->
thumbs
=
1
;
$dbList
->
clickTitleMode
=
'edit'
;
$dbList
->
calcPerms
=
$GLOBALS
[
'BE_USER'
]
->
calcPerms
(
$this
->
pageInformation
);
$dbList
->
disableSingleTableView
=
1
;
$dbList
->
dontShowClipControlPanels
=
true
;
$pointer
=
MathUtility
::
forceIntegerInRange
(
GeneralUtility
::
_GP
(
'pointer'
),
0
);
$levelLimit
=
0
;
$itemLimit
=
20
;
$searchField
=
$args
[
'search_field'
];
$dbList
->
start
(
$this
->
storagePageId
,
'tx_lunames_domain_model_person'
,
$pointer
,
$searchField
,
$levelLimit
,
$itemLimit
);
$dbList
->
setDispFields
();
$dbList
->
noControlPanels
=
true
;
$dbList
->
setFields
=
[
'tx_lunames_domain_model_person'
=>
GeneralUtility
::
trimExplode
(
','
,
'given_name,family_name,year_of_birth,year_of_death'
,
true
),
];
$dbList
->
generateList
();
$assignedValues
=
[
'personList'
=>
$dbList
->
HTMLcode
,
'personCount'
=>
$dbList
->
counter
,
'formSubmitted'
=>
$args
[
'formSubmitted'
],
'searchTerm'
=>
$searchField
,
'requestUri'
=>
GeneralUtility
::
quoteJSvalue
(
rawurlencode
(
GeneralUtility
::
getIndpEnv
(
'REQUEST_URI'
))),
];
$this
->
view
->
assignMultiple
(
$assignedValues
);
}
/**
* Add Action
*
* @return void
*/
public
function
addAction
()
{
$config
=
GeneralUtility
::
makeInstance
(
ExtensionConfiguration
::
class
)
->
get
(
'lu_names'
);
// Predefine values/models
$table
=
'tx_lunames_domain_model_person'
;
$uriBuilder
=
GeneralUtility
::
makeInstance
(
BackendUriBuilder
::
class
);
// Create redirect url
$returnUrl
=
'index.php?route=/web/LuNamesNames/&id='
.
$this
->
storagePageId
.
$this
->
getToken
();
$pid
=
$config
[
'storage_page_id'
];
$url
=
$uriBuilder
->
buildUriFromRoute
(
'record_edit'
,
[
'edit['
.
$table
.
']['
.
$pid
.
']'
=>
'new'
,
'returnUrl'
=>
$returnUrl
,
]
);
// Redirect
HttpUtility
::
redirect
(
$url
);
}
/**
* Adds header buttons
*
* @return void
*/
protected
function
createButtons
()
{
$buttonBar
=
$this
->
view
->
getModuleTemplate
()
->
getDocHeaderComponent
()
->
getButtonBar
();
$uriBuilder
=
$this
->
objectManager
->
get
(
UriBuilder
::
class
);
$iconFactory
=
GeneralUtility
::
makeInstance
(
IconFactory
::
class
);
$uriBuilder
->
setRequest
(
$this
->
request
);
$searchButton
=
$buttonBar
->
makeLinkButton
();
$searchButton
->
setHref
(
'#'
)
->
setClasses
(
't3js-toggle-search-toolbox'
)
->
setTitle
(
'Search'
)
->
setIcon
(
$iconFactory
->
getIcon
(
'actions-search'
,
Icon
::
SIZE_SMALL
));
$buttonBar
->
addButton
(
$searchButton
,
ButtonBar
::
BUTTON_POSITION_LEFT
,
2
);
$buttons
=
[
[
'table'
=>
'tx_lunames_domain_model_person'
,
'label'
=>
'module.createNewRecord'
,
'action'
=>
'add'
,
'icon'
=>
'actions-document-new'
,
],
];
foreach
(
$buttons
as
$key
=>
$tableConfiguration
)
{
$title
=
$GLOBALS
[
'LANG'
]
->
sL
(
'LLL:EXT:lu_names/Resources/Private/Language/locallang.xlf:'
.
$tableConfiguration
[
'label'
]);
$viewButton
=
$buttonBar
->
makeLinkButton
()
->
setHref
(
$uriBuilder
->
reset
()
->
setRequest
(
$this
->
request
)
->
uriFor
(
$tableConfiguration
[
'action'
],
[],
'Person'
))
->
setTitle
(
$title
)
->
setIcon
(
$iconFactory
->
getIcon
(
$tableConfiguration
[
'icon'
],
Icon
::
SIZE_SMALL
));
$buttonBar
->
addButton
(
$viewButton
,
ButtonBar
::
BUTTON_POSITION_LEFT
,
1
);
}
}
/**
* Get a CSRF token
*
* @param bool $tokenOnly
*
* @return string
*/
protected
function
getToken
(
$tokenOnly
=
false
)
{
$token
=
FormProtectionFactory
::
get
(
'backend'
)
->
generateToken
(
'route'
,
'web_LuNamesNames'
);
if
(
$tokenOnly
)
{
return
$token
;
}
else
{
return
'&token='
.
$token
;
}
}
}
Classes/Controller/SearchController.php
0 → 100644
View file @
2c9feeaa
<?php
namespace
Lu\LuNames\Controller
;
use
Lu\LuApi\DataSources\SolrLibrary
;
use
Lu\LuApi\DataSources\SolrNames
;
use
Lu\LuApi\Helpers\DataHelper
;
use
Lu\LuNames\Domain\Model\Person
;
use
TYPO3\CMS\Core\Context\Context
;
use
TYPO3\CMS\Core\Page\PageRenderer
;
use
TYPO3\CMS\Core\Resource\FileRepository
;
use
TYPO3\CMS\Core\Utility\GeneralUtility
;
use
TYPO3\CMS\Extbase\Mvc\Controller\ActionController
;
use
TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder
;
/**
* Class SearchController
*
* @author Dainis Abols <dainis.abols@lu.lv>
* @owner University of Latvia
* @since 06.10.2020
*
* @package Lu\LuNames\Controller
*/
class
SearchController
extends
ActionController
{
/**
* Frontend-Session
*
* @var \Lu\LuNames\Domain\Session\FrontendSessionHandler
*/
protected
$frontendSession
;
/**
* Frontend- or Backend-Session
* The type of session is set automatically in initializeAction().
*
* @var \Lu\LuNames\Domain\Session\SessionHandler
*/
protected
$session
;
/**