Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Open
LU Notices
Commits
51cd1d8e
Commit
51cd1d8e
authored
Apr 27, 2021
by
Dainis Abols
Browse files
TPO3 v10 Compatability. Needs file migration on install!
v4.2.0
parent
be17bdfa
Changes
10
Expand all
Hide whitespace changes
Inline
Side-by-side
Classes/Controller/NoticesController.php
View file @
51cd1d8e
...
...
@@ -9,6 +9,7 @@ use Lu\LuNotices\Domain\Repository\TopicsRepository;
use
TYPO3\CMS\Core\Core\Environment
;
use
TYPO3\CMS\Core\Database\ConnectionPool
;
use
TYPO3\CMS\Core\DataHandling\DataHandler
;
use
TYPO3\CMS\Core\Resource\FileRepository
;
use
TYPO3\CMS\Core\Resource\ResourceFactory
;
use
TYPO3\CMS\Core\Utility\GeneralUtility
;
use
TYPO3\CMS\Extbase\Mvc\Controller\ActionController
;
...
...
@@ -208,31 +209,13 @@ class NoticesController extends ActionController
*
* @return array
*/
private
function
getFilesByNotice
(
$noticeId
)
private
function
getFilesByNotice
(
$noticeId
)
:
array
{
// Pre-set values
$files
=
[];
$notice
=
$this
->
noticesRepository
->
findByUid
(
$noticeId
);
// Check if files found
if
(
!
empty
(
$notice
->
getFiles
()))
{
$noticesFiles
=
explode
(
','
,
$notice
->
getFiles
());
// Removes storage folder name
if
(
!
empty
(
$noticesFiles
))
{
foreach
(
$noticesFiles
as
$filePath
)
{
if
(
!
empty
(
$filePath
)
&&
file_exists
(
Environment
::
getPublicPath
()
.
'/'
.
$filePath
))
{
$resourceFactory
=
ResourceFactory
::
getInstance
();
$filePath
=
str_replace
(
'fileadmin/'
,
''
,
$filePath
);
$f
=
$resourceFactory
->
getFileObjectByStorageAndIdentifier
(
1
,
$filePath
);
$f
->
getProperties
();
$files
[]
=
$f
;
}
}
}
}
$noticesTable
=
'tx_lunotices_domain_model_notices'
;
$fileRepository
=
GeneralUtility
::
makeInstance
(
FileRepository
::
class
);
return
$file
s
;
return
$file
Repository
->
findByRelation
(
$noticesTable
,
'media'
,
$noticeId
)
;
}
/**
...
...
Classes/Updates/FileMigrationWizard.php
0 → 100644
View file @
51cd1d8e
<?php
declare
(
strict_types
=
1
);
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
namespace
Lu\LuNotices\Updates
;
use
Doctrine\DBAL\DBALException
;
use
Psr\Log\LoggerAwareInterface
;
use
Psr\Log\LoggerAwareTrait
;
use
Symfony\Component\Console\Output\OutputInterface
;
use
TYPO3\CMS\Core\Core\Environment
;
use
TYPO3\CMS\Core\Database\ConnectionPool
;
use
TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder
;
use
TYPO3\CMS\Core\Resource\File
;
use
TYPO3\CMS\Core\Resource\ResourceStorage
;
use
TYPO3\CMS\Core\Resource\StorageRepository
;
use
TYPO3\CMS\Core\Utility\GeneralUtility
;
use
TYPO3\CMS\Core\Utility\PathUtility
;
use
TYPO3\CMS\Install\Updates\ChattyInterface
;
use
TYPO3\CMS\Install\Updates\DatabaseUpdatedPrerequisite
;
use
TYPO3\CMS\Install\Updates\UpgradeWizardInterface
;
/**
* Upgrade wizard which goes through all files
* and creates sys_file records as well as sys_file_reference records for each hit.
*/
class
FileMigrationWizard
implements
UpgradeWizardInterface
,
ChattyInterface
,
LoggerAwareInterface
{
use
LoggerAwareTrait
;
/**
* @var OutputInterface
*/
protected
$output
;
/**
* @var ResourceStorage
*/
protected
$storage
;
/**
* Table to migrate records from
*
* @var string
*/
protected
$table
=
'tx_lunotices_domain_model_notices'
;
/**
* Table field holding the migration to be
*
* @var string
*/
protected
$fieldToMigrate
=
'files'
;
/**
* target folder after migration
* Relative to fileadmin
*
* @var string
*/
protected
$targetPath
=
'_migrated/'
;
/**
* @return string Unique identifier of this updater
*/
public
function
getIdentifier
():
string
{
return
'noticesFileMigration'
;
}
/**
* @return string Title of this updater
*/
public
function
getTitle
():
string
{
return
'Migrate all LU Notices file relations to sys_file_references'
;
}
/**
* @return string Longer description of this updater
*/
public
function
getDescription
():
string
{
return
'This update wizard goes through all files that are referenced in the'
.
' notices.files field and adds the files to the FAL File Index.'
.
' It also moves the files from uploads/ to the fileadmin/_migrated/ path.'
;
}
/**
* @return bool True if there are records to update
*/
public
function
updateNecessary
():
bool
{
return
!
empty
(
$this
->
getRecordsFromTable
());
}
/**
* @return string[] All new fields and tables must exist
*/
public
function
getPrerequisites
():
array
{
return
[
DatabaseUpdatedPrerequisite
::
class
];
}
/**
* @param OutputInterface $output
*/
public
function
setOutput
(
OutputInterface
$output
):
void
{
$this
->
output
=
$output
;
}
/**
* Performs the configuration update.
*
* @return bool
*/
public
function
executeUpdate
():
bool
{
$result
=
true
;
try
{
$storages
=
GeneralUtility
::
makeInstance
(
StorageRepository
::
class
)
->
findAll
();
$this
->
storage
=
$storages
[
0
];
$records
=
$this
->
getRecordsFromTable
();
foreach
(
$records
as
$record
)
{
$this
->
migrateField
(
$record
);
}
}
catch
(
\
Exception
$e
)
{
// If something goes wrong, migrateField() logs an error
$result
=
false
;
}
return
$result
;
}
/**
* Get records from table where the field to migrate is not empty (NOT NULL and != '')
* and also not numeric (which means that it is migrated)
*
* @return array
* @throws \RuntimeException
*/
protected
function
getRecordsFromTable
()
{
$connectionPool
=
GeneralUtility
::
makeInstance
(
ConnectionPool
::
class
);
$queryBuilder
=
$connectionPool
->
getQueryBuilderForTable
(
$this
->
table
);
$queryBuilder
->
getRestrictions
()
->
removeAll
();
try
{
return
$queryBuilder
->
select
(
'uid'
,
'pid'
,
$this
->
fieldToMigrate
)
->
from
(
$this
->
table
)
->
where
(
$queryBuilder
->
expr
()
->
isNotNull
(
$this
->
fieldToMigrate
),
$queryBuilder
->
expr
()
->
neq
(
$this
->
fieldToMigrate
,
$queryBuilder
->
createNamedParameter
(
''
,
\
PDO
::
PARAM_STR
)
),
$queryBuilder
->
expr
()
->
comparison
(
'CAST(CAST('
.
$queryBuilder
->
quoteIdentifier
(
$this
->
fieldToMigrate
)
.
' AS DECIMAL) AS CHAR)'
,
ExpressionBuilder
::
NEQ
,
'CAST('
.
$queryBuilder
->
quoteIdentifier
(
$this
->
fieldToMigrate
)
.
' AS CHAR)'
)
)
->
orderBy
(
'uid'
)
->
execute
()
->
fetchAll
();
}
catch
(
DBALException
$e
)
{
throw
new
\
RuntimeException
(
'Database query failed. Error was: '
.
$e
->
getPrevious
()
->
getMessage
(),
1511950673
);
}
}
/**
* Migrates a single field.
*
* @param array $row
* @throws \Exception
*/
protected
function
migrateField
(
$row
)
{
$fieldItems
=
GeneralUtility
::
trimExplode
(
','
,
$row
[
$this
->
fieldToMigrate
],
true
);
if
(
empty
(
$fieldItems
)
||
is_numeric
(
$row
[
$this
->
fieldToMigrate
]))
{
return
;
}
$fileadminDirectory
=
rtrim
(
$GLOBALS
[
'TYPO3_CONF_VARS'
][
'BE'
][
'fileadminDir'
],
'/'
)
.
'/'
;
$i
=
0
;
$storageUid
=
(
int
)
$this
->
storage
->
getUid
();
$connectionPool
=
GeneralUtility
::
makeInstance
(
ConnectionPool
::
class
);
foreach
(
$fieldItems
as
$item
)
{
$fileUid
=
null
;
$sourcePath
=
Environment
::
getPublicPath
()
.
'/'
.
$item
;
$strippedPath
=
str_replace
(
"fileadmin/user_upload/"
,
""
,
$item
);
$targetDirectory
=
Environment
::
getPublicPath
()
.
'/'
.
$fileadminDirectory
.
$this
->
targetPath
;
$targetPath
=
$targetDirectory
.
$strippedPath
;
// Remove file name
$temp
=
explode
(
"/"
,
$strippedPath
);
array_pop
(
$temp
);
$subdir
=
implode
(
"/"
,
$temp
);
$subdir
=
$targetDirectory
.
$subdir
;
// maybe the file was already moved, so check if the original file still exists
if
(
file_exists
(
$sourcePath
)
&&
!
is_dir
(
$sourcePath
))
{
if
(
!
is_dir
(
$targetDirectory
))
{
GeneralUtility
::
mkdir_deep
(
$targetDirectory
);
}
// Create subdirectory
if
(
!
is_dir
(
$subdir
))
{
GeneralUtility
::
mkdir_deep
(
$subdir
);
}
// see if the file already exists in the storage
$fileSha1
=
sha1_file
(
$sourcePath
);
$queryBuilder
=
$connectionPool
->
getQueryBuilderForTable
(
'sys_file'
);
$queryBuilder
->
getRestrictions
()
->
removeAll
();
$existingFileRecord
=
$queryBuilder
->
select
(
'uid'
)
->
from
(
'sys_file'
)
->
where
(
$queryBuilder
->
expr
()
->
eq
(
'sha1'
,
$queryBuilder
->
createNamedParameter
(
$fileSha1
,
\
PDO
::
PARAM_STR
)
),
$queryBuilder
->
expr
()
->
eq
(
'storage'
,
$queryBuilder
->
createNamedParameter
(
$storageUid
,
\
PDO
::
PARAM_INT
)
)
)
->
execute
()
->
fetch
();
// the file exists, the file does not have to be moved again
if
(
is_array
(
$existingFileRecord
))
{
$fileUid
=
$existingFileRecord
[
'uid'
];
}
else
{
// just move the file (no duplicate)
rename
(
$sourcePath
,
$targetPath
);
}
}
if
(
$fileUid
===
null
)
{
// get the File object if it hasn't been fetched before
try
{
// if the source file does not exist, we should just continue, but leave a message in the docs;
// ideally, the user would be informed after the update as well.
/** @var File $file */
$file
=
$this
->
storage
->
getFile
(
$this
->
targetPath
.
$strippedPath
);
$fileUid
=
$file
->
getUid
();
}
catch
(
\
InvalidArgumentException
$e
)
{
// no file found, no reference can be set
$this
->
logger
->
notice
(
'File '
.
$item
.
' does not exist. Reference was not migrated.'
,
[
'table'
=>
$this
->
table
,
'record'
=>
$row
,
'field'
=>
$this
->
fieldToMigrate
,
]
);
$format
=
'File \'%s\' does not exist. Referencing field: %s.%d.%s. The reference was not migrated.'
;
$this
->
output
->
writeln
(
sprintf
(
$format
,
$item
,
$this
->
table
,
$row
[
'uid'
],
$this
->
fieldToMigrate
));
continue
;
}
}
if
(
$fileUid
>
0
)
{
$fields
=
[
'fieldname'
=>
$this
->
fieldToMigrate
,
'table_local'
=>
'sys_file'
,
'pid'
=>
$this
->
table
===
'pages'
?
$row
[
'uid'
]
:
$row
[
'pid'
],
'uid_foreign'
=>
$row
[
'uid'
],
'uid_local'
=>
$fileUid
,
'tablenames'
=>
$this
->
table
,
'crdate'
=>
time
(),
'tstamp'
=>
time
(),
'sorting_foreign'
=>
$i
,
];
$queryBuilder
=
$connectionPool
->
getQueryBuilderForTable
(
'sys_file_reference'
);
$queryBuilder
->
insert
(
'sys_file_reference'
)
->
values
(
$fields
)
->
execute
();
++
$i
;
}
}
// Update referencing table's original field to now contain the count of references,
// but only if all new references could be set
if
(
$i
===
count
(
$fieldItems
))
{
$queryBuilder
=
$connectionPool
->
getQueryBuilderForTable
(
$this
->
table
);
$queryBuilder
->
update
(
$this
->
table
)
->
where
(
$queryBuilder
->
expr
()
->
eq
(
'uid'
,
$queryBuilder
->
createNamedParameter
(
$row
[
'uid'
],
\
PDO
::
PARAM_INT
)
)
)
->
set
(
$this
->
fieldToMigrate
,
$i
)
->
execute
();
}
}
}
Configuration/TCA/tx_lunotices_domain_model_notices.php
View file @
51cd1d8e
...
...
@@ -32,25 +32,27 @@ return [
'exclude'
=>
0
,
'label'
=>
'LLL:EXT:lu_notices/Resources/Private/Language/locallang.xlf:starttime'
,
'config'
=>
[
'type'
=>
'input'
,
'size'
=>
8
,
'max'
=>
20
,
'eval'
=>
'datetime,int'
,
'default'
=>
'0'
,
'checkbox'
=>
'0'
,
'type'
=>
'input'
,
'renderType'
=>
'inputDateTime'
,
'size'
=>
8
,
'max'
=>
20
,
'eval'
=>
'datetime,int'
,
'default'
=>
'0'
,
'checkbox'
=>
'0'
,
],
],
'endtime'
=>
[
'exclude'
=>
0
,
'label'
=>
'LLL:EXT:lu_notices/Resources/Private/Language/locallang.xlf:endtime'
,
'config'
=>
[
'type'
=>
'input'
,
'size'
=>
8
,
'max'
=>
20
,
'eval'
=>
'datetime,int'
,
'checkbox'
=>
'0'
,
'default'
=>
'0'
,
'range'
=>
[
'type'
=>
'input'
,
'renderType'
=>
'inputDateTime'
,
'size'
=>
8
,
'max'
=>
20
,
'eval'
=>
'datetime,int'
,
'checkbox'
=>
'0'
,
'default'
=>
'0'
,
'range'
=>
[
'upper'
=>
mktime
(
3
,
14
,
7
,
1
,
19
,
2038
),
'lower'
=>
mktime
(
0
,
0
,
0
,
date
(
'm'
)
-
1
,
date
(
'd'
),
date
(
'Y'
)),
],
...
...
@@ -82,40 +84,26 @@ return [
'eval'
=>
'trim'
,
],
],
'body'
=>
[
'label'
=>
'LLL:EXT:lu_notices/Resources/Private/Language/locallang.xlf:notices.body'
,
'config'
=>
[
'type'
=>
'text'
,
'cols'
=>
30
,
'rows'
=>
5
,
'eval'
=>
'trim'
,
'body'
=>
[
'label'
=>
'LLL:EXT:lu_notices/Resources/Private/Language/locallang.xlf:notices.body'
,
'config'
=>
[
'type'
=>
'text'
,
'enableRichtext'
=>
true
,
'cols'
=>
30
,
'rows'
=>
5
,
'eval'
=>
'trim'
,
],
'defaultExtras'
=>
'richtext[]'
,
],
'url'
=>
[
'url'
=>
[
'exclude'
=>
0
,
'label'
=>
'LLL:EXT:lu_notices/Resources/Private/Language/locallang.xlf:notice.url'
,
'config'
=>
[
'type'
=>
'input'
,
'size'
=>
'15'
,
'max'
=>
'255'
,
'checkbox'
=>
''
,
'eval'
=>
'trim'
,
'wizards'
=>
[
'_PADDING'
=>
2
,
'link'
=>
[
'type'
=>
'popup'
,
'title'
=>
'Link'
,
'icon'
=>
'link_popup.gif'
,
'module'
=>
[
'name'
=>
'wizard_element_browser'
,
'urlParameters'
=>
[
'mode'
=>
'wizard'
,
],
],
'JSopenParams'
=>
'height=300,width=500,status=0,menubar=0,scrollbars=1'
,
],
],
'type'
=>
'input'
,
'renderType'
=>
'inputLink'
,
'size'
=>
'15'
,
'max'
=>
'255'
,
'checkbox'
=>
''
,
'eval'
=>
'trim'
,
],
],
'priority'
=>
[
...
...
@@ -137,18 +125,15 @@ return [
'files'
=>
[
'exclude'
=>
0
,
'label'
=>
'LLL:EXT:lu_notices/Resources/Private/Language/locallang.xlf:notice.files'
,
'config'
=>
[
'type'
=>
'group'
,
//'internal_type' => 'file',
'internal_type'
=>
'file_reference'
,
'allowed'
=>
''
,
'disallowed'
=>
'php,php3'
,
'max_size'
=>
$GLOBALS
[
'TYPO3_CONF_VARS'
][
'BE'
][
'maxFileSize'
],
//'uploadfolder' => 'uploads/user_lunotices',
'size'
=>
10
,
'minitems'
=>
0
,
'maxitems'
=>
100
,
],
'config'
=>
\
TYPO3\CMS\Core\Utility\ExtensionManagementUtility
::
getFileFieldTCAConfig
(
'files'
,
[
'minitems'
=>
0
,
'maxitems'
=>
100
,
],
''
,
'php,php3'
),
],
],
'types'
=>
[
...
...
Configuration/TCA/tx_lunotices_domain_model_topics.php
View file @
51cd1d8e
...
...
@@ -91,6 +91,7 @@ return [
'label'
=>
'LLL:EXT:lu_notices/Resources/Private/Language/locallang.xlf:fegroup'
,
'config'
=>
[
'type'
=>
'select'
,
'renderType'
=>
'selectSingle'
,
'foreign_table'
=>
'fe_groups'
,
'foreign_table_where'
=>
'ORDER BY fe_groups.title ASC'
,
'eval'
=>
'required'
,
...
...
@@ -107,7 +108,7 @@ return [
],
],
'types'
=>
[
'0'
=>
[
'showitem'
=>
'hidden;;1;;1-1-1, ;;2;;2-2-2, description;;;;3-3-3, priority'
],
'0'
=>
[
'showitem'
=>
'hidden
, --palette--
;;1;;1-1-1,
--palette--
;;2;;2-2-2, description;;;;3-3-3, priority'
],
],
'palettes'
=>
[
'1'
=>
[
'showitem'
=>
'starttime, endtime, fe_group'
],
...
...
LICENSE
0 → 100644
View file @
51cd1d8e
This diff is collapsed.
Click to expand it.
composer.json
View file @
51cd1d8e
{
"name"
:
"luitd/lu-notices"
,
"version"
:
"4.
1.6
"
,
"version"
:
"4.
2.0
"
,
"description"
:
"General notice publisher for internal portal"
,
"type"
:
"typo3-cms-extension"
,
"keywords"
:
[
...
...
ext_emconf.php
View file @
51cd1d8e
...
...
@@ -9,10 +9,10 @@ $EM_CONF[$_EXTKEY] = [
'author_company'
=>
'University of Latvia'
,
'state'
=>
'stable'
,
'clearCacheOnLoad'
=>
true
,
'version'
=>
'4.
1.6
'
,
'version'
=>
'4.
2.0
'
,
'constraints'
=>
[
'depends'
=>
[
'typo3'
=>
'9.5.0-
9
.9.99'
,
'typo3'
=>
'9.5.0-
10
.9.99'
,
],
],
'autoload'
=>
[
...
...
ext_localconf.php
View file @
51cd1d8e
...
...
@@ -25,3 +25,6 @@ defined('TYPO3_MODE') || die('Access denied.');
// Register hooks
$GLOBALS
[
'TYPO3_CONF_VARS'
][
'SC_OPTIONS'
][
\
TYPO3\CMS\Recordlist\RecordList\DatabaseRecordList
::
class
][
'modifyQuery'
][]
=
\
Lu\LuNotices\Hooks\Backend\RecordListQueryHook
::
class
;
$GLOBALS
[
'TYPO3_CONF_VARS'
][
'SC_OPTIONS'
][
'ext/install'
][
'update'
][
'noticesFileMigration'
]
=
Lu\LuNotices\Updates\FileMigrationWizard
::
class
;
ext_tables.sql
View file @
51cd1d8e
...
...
@@ -25,29 +25,30 @@ CREATE TABLE tx_lunotices_domain_model_topics (
#
#
Table
structure
for
table
'tx_lunotices_domain_model_notices'
#
CREATE
TABLE
tx_lunotices_domain_model_notices
(
uid
INT
(
11
)
NOT
NULL
auto_increment
,
pid
INT
(
11
)
DEFAULT
'0'
NOT
NULL
,
topic_id
text
,
title
tinytext
,
summary
text
,
body
longtext
,
url
tinytext
,
priority
INT
(
3
)
DEFAULT
'0'
NOT
NULL
,
files
text
,
hidden
TINYINT
(
4
)
DEFAULT
'0'
NOT
NULL
,
starttime
INT
(
11
)
DEFAULT
'0'
NOT
NULL
,
endtime
INT
(
11
)
DEFAULT
'0'
NOT
NULL
,
cruser_id
INT
(
11
)
DEFAULT
'0'
NOT
NULL
,
fe_group
INT
(
11
)
DEFAULT
'0'
NOT
NULL
,
crdate
INT
(
11
)
DEFAULT
'0'
NOT
NULL
,
deleted
TINYINT
(
4
)
DEFAULT
'0'
NOT
NULL
,
deleted_at
INT
(
11
)
DEFAULT
'0'
NOT
NULL
,
tstamp
INT
(
11
)
DEFAULT
'0'
NOT
NULL
,
sorting
INT
(
11
)
DEFAULT
'0'
NOT
NULL
,
CREATE
TABLE
tx_lunotices_domain_model_notices
(
uid
INT
(
11
)
NOT
NULL
auto_increment
,
pid
INT
(
11
)
DEFAULT
'0'
NOT
NULL
,
topic_id
text
,
title
tinytext
,
summary
text
,
body
longtext
,
url
tinytext
,
priority
INT
(
3
)
DEFAULT
'0'
NOT
NULL
,
files
varchar
(
255
)
DEFAULT
''
NOT
NULL
,
hidden
TINYINT
(
4
)
DEFAULT
'0'
NOT
NULL
,
starttime
INT
(
11
)
DEFAULT
'0'
NOT
NULL
,
endtime
INT
(
11
)
DEFAULT
'0'
NOT
NULL
,
cruser_id
INT
(
11
)
DEFAULT
'0'
NOT
NULL
,
fe_group
INT
(
11
)
DEFAULT
'0'
NOT
NULL
,
crdate
INT
(
11
)
DEFAULT
'0'
NOT
NULL
,
deleted
TINYINT
(
4
)
DEFAULT
'0'
NOT
NULL
,
deleted_at
INT
(
11
)
DEFAULT
'0'
NOT
NULL
,
tstamp
INT
(
11
)
DEFAULT
'0'
NOT
NULL
,
sorting
INT
(
11
)
DEFAULT
'0'
NOT
NULL
,
PRIMARY
KEY
(
uid
),
KEY
parent
(
pid
)
PRIMARY
KEY
(
uid
),
KEY
parent
(
pid
)
);
#
...
...
readme.md
View file @
51cd1d8e
...
...
@@ -4,11 +4,11 @@
## Version
4.
1.6
4.
2.0
## Dependencies
*
TYPO3 v
8+, v9+
*
TYPO3 v
9.5 | v10
## Author
...
...
Write
Preview