Projekt

Obecné

Profil

« Předchozí | Další » 

Revize ce045025

Přidáno uživatelem Petr Lukašík před téměř 6 roky(ů)

Re #7510 kompletní import, bugfixy v parseru+preview, js na anti-spam uploadu

Zobrazit rozdíly:

app/AdminModule/component/Transport/ImportForm.php
46 46
        }
47 47
    }
48 48

  
49
    public function formSuccess(Form $form)
49
    public function formSuccess()
50 50
    {
51 51
        $this->presenter->forward('Transport:previewImport', $this->parser);
52 52
    }
app/AdminModule/presenters/TransportPresenter.php
4 4

  
5 5
use App\AdminModule\Components\IExportFormFactory;
6 6
use App\AdminModule\Components\IImportFormFactory;
7
use App\Enum\EFlashMessage;
8
use App\Model\Facade\TransportFacade;
7 9
use App\Model\Repository\ObjectTypeRepository;
8 10
use App\Model\Repository\SurfaceTypeRepository;
9 11
use App\Utils\TextParser;
10 12

  
11 13
class TransportPresenter extends BaseUserPresenter
12 14
{
13
    /** @var IImportFormFactory  */
15
    /** @var IImportFormFactory */
14 16
    private $importFormFactory;
15 17

  
16
    /** @var IExportFormFactory  */
18
    /** @var IExportFormFactory */
17 19
    private $exportFormFactory;
18 20

  
19 21
    /** @var SurfaceTypeRepository */
......
22 24
    /** @var ObjectTypeRepository */
23 25
    private $objectTypeRepository;
24 26

  
27
    /** @var TransportFacade */
28
    private $transportFacade;
29

  
25 30
    public function __construct(
26 31
        IImportFormFactory $importFormFactory,
27 32
        IExportFormFactory $exportFormFactory,
28 33
        SurfaceTypeRepository $surfaceTypeRepository,
29
        ObjectTypeRepository $objectTypeRepository
34
        ObjectTypeRepository $objectTypeRepository,
35
        TransportFacade $transportFacade
30 36
    )
31 37
    {
32 38
        parent::__construct();
......
34 40
        $this->exportFormFactory = $exportFormFactory;
35 41
        $this->surfaceTypeRepository = $surfaceTypeRepository;
36 42
        $this->objectTypeRepository = $objectTypeRepository;
43
        $this->transportFacade = $transportFacade;
37 44
    }
38 45

  
39
    public function actionPreviewImport(TextParser $parser){
46
    /**
47
     * View pro zobrazení importovaných dat před uložením do databáze
48
     * @param TextParser $parser
49
     */
50
    public function renderPreviewImport(TextParser $parser)
51
    {
40 52
        $objectTypes = $this->objectTypeRepository->fetchObjectTypes();
41 53
        $surfaceTypes = $this->surfaceTypeRepository->fetchSurfaceTypes();
42 54
        $parser->setTypes($objectTypes, $surfaceTypes);
43 55

  
44
        $this->template->fileName = $parser->textFile->getName();
45
        $this->template->parsedFile = $parser->parseText();
56
        // Potřebuju to jako persistentní data do další akce presenteru
57
        $_SESSION['parsedText'] = $parser->parseText();
58

  
59
        $this->template->fileName = $parser->getTextFile()->getName();
60
        $this->template->parsedFile = $_SESSION['parsedText'];
46 61
        $this->template->transliterationNum = $this->countTransliterations();
47 62
        $this->template->surfaces = $surfaceTypes;
48 63
    }
49 64

  
50
    public function countTransliterations(){
51
        $num=0;
52
        foreach ($this->template->parsedFile as $book){
65
    /** Uloží data z textového souboru do databáze
66
     * @throws \Nette\Application\AbortException
67
     */
68
    public function actionConfirmPreview()
69
    {
70
        $result = $this->transportFacade->saveImportedData($_SESSION['parsedText']);
71
        $_SESSION['parsedText'] = null;
72

  
73
        if ($result) {
74
            $this->presenter->flashMessage('All data were imported successfully.', EFlashMessage::SUCCESS);
75
        } else {
76
            $this->presenter->flashMessage('There was an error when importing data.', EFlashMessage::ERROR);
77
        }
78

  
79
        $this->redirect("Transport:");
80
    }
81

  
82
    /** Počítá počet importovaných transliterací */
83
    public function countTransliterations()
84
    {
85
        $num = 0;
86
        foreach ($this->template->parsedFile as $book) {
53 87
            $num += count($book);
54 88
        }
55 89
        return $num;
app/AdminModule/templates/Transport/previewImport.latte
4 4
            <div class="display-5">Preview of import: {$fileName}</div>
5 5
        </div>
6 6
        <div class="col-2 text-right">
7
            <a n:href="Transport:confirmPreview" class="btn btn-sm btn-success"><span class="fa fa-fw fa-check"></span> Confirm
8
                preview</a>
7
            <a id="confirmation" n:href="Transport:confirmPreview" class="btn btn-sm btn-success"><span class="fa fa-fw fa-check"></span>
8
                Confirm preview</a>
9 9
        </div>
10 10
    </div>
11
    <div class="row col-8">
11
    <div class="row col-8 mb-3">
12 12
        Imported {$transliterationNum} transliterations
13 13
    </div>
14 14

  
15
    <div class="mt-5 p-3 col-8" style="border: 1px solid #c8c8c8;border-radius: 5px">
16
        <div class="col-12 display-5" n:foreach="$parsedFile as $book=>$chapters">Book {$book}</div>
17
        <div class="row" n:foreach="$chapters as $chapter=>$references">
18
            <div class="col-12 mt-3">
19
                <fieldset style="background-color: #f7f7dd">
20
                    <legend style="background-color: #f7f7dd">Chapter {$chapter}</legend>
21
                    <div n:foreach="$references as $reference=>$element">
22
                        <i>{$surfaces[$reference]}</i><br>
23
                        {foreach $element as $value}
24
                            {$value}.<br>
25
                        {/foreach}
26
                        {if !(end($references) == $element)}<hr>{/if}
15
    <div class="p-3 col-8" style="border: 1px solid #c8c8c8;border-radius: 5px">
16
        {foreach $parsedFile as $book=>$chapters}
17
            <div class="col-12 display-5 mt-3">Book {$book}</div>
18
            {foreach $chapters as $chapter=>$references}
19
                <div class="row">
20
                    <div class="col-12 mb-3">
21
                        <fieldset style="background-color: #f7f7dd">
22
                            <legend style="background-color: #f7f7dd">Chapter {$chapter}</legend>
23
                            <div n:foreach="$references as $reference=>$element">
24
                                <i>{$surfaces[$reference]}</i><br>
25
                                {foreach $element as $value}
26
                                    {$value}.<br>
27
                                {/foreach}
28
                                {if !(end($references) == $element)}
29
                                    <hr>{/if}
30
                            </div>
31
                        </fieldset>
27 32
                    </div>
28
                </fieldset>
29
            </div>
30
        </div>
33
                </div>
34
            {/foreach}
35
        {/foreach}
31 36
    </div>
32
    <button onclick="toTop()" class="btn btn-sm btn-info mt-2 col-8"><span class="fa fa-fw fa-arrow-up"></span> Back to top</button>
37
    <button onclick="toTop()" class="btn btn-sm btn-info mt-2 col-8"><span class="fa fa-fw fa-arrow-up"></span> Back to
38
        top
39
    </button>
33 40
{/block}
34 41

  
35 42
{block scripts}
36 43
    <script>
37 44
        function toTop() {
38
            window.scrollTo(0,0);
45
            window.scrollTo(0, 0);
39 46
        }
47

  
48
        $(document).ready(function () {
49
            $('#confirmation').click(function () {
50
                $('#confirmation').addClass('disabled');
51
            });
52
        });
40 53
    </script>
41 54
{/block}
app/config/model.neon
20 20
    #Facade
21 21
    - App\Model\Facade\UserFacade
22 22
    - App\Model\Facade\TransliterationFacade
23
    - App\Model\Facade\TransportFacade
23 24

  
24 25
    #Sessions
25 26
    - App\Model\TransliterationSearchModel
app/model/facade/TransportFacade.php
1
<?php
2

  
3

  
4
namespace App\Model\Facade;
5

  
6
use App\Model\Repository\BookRepository;
7
use App\Model\Repository\LineRepository;
8
use App\Model\Repository\SurfaceRepository;
9
use App\Model\Repository\TransliterationRepository;
10
use Nette\Database\Context;
11
use Nette\Database\Table\ActiveRow;
12

  
13
/**
14
 * Class TransportFacade sloužící pro import/export práce s db
15
 * @package App\Model\Facade
16
 */
17
class TransportFacade
18
{
19
    /** @var BookRepository */
20
    private $bookRepository;
21

  
22
    /** @var TransliterationRepository */
23
    private $transliterationRepository;
24

  
25
    /** @var SurfaceRepository */
26
    private $surfaceRepository;
27

  
28
    /** @var LineRepository */
29
    private $lineRepository;
30

  
31
    /** @var Context */
32
    private $context;
33

  
34

  
35
    public function __construct(BookRepository $bookRepository,
36
                                TransliterationRepository $transliterationRepository,
37
                                SurfaceRepository $surfaceRepository,
38
                                LineRepository $lineRepository,
39
                                Context $context
40
    )
41
    {
42
        $this->bookRepository = $bookRepository;
43
        $this->transliterationRepository = $transliterationRepository;
44
        $this->surfaceRepository = $surfaceRepository;
45
        $this->lineRepository = $lineRepository;
46
        $this->context = $context;
47
    }
48

  
49
    /**
50
     * Uloží data transliterace z importu
51
     *
52
     * @param $data
53
     * @return bool
54
     */
55
    public function saveImportedData($data)
56
    {
57
        // Škaredý zanoření hodnot z dat v importu :( Tohle bude pro db náročný
58
        foreach ($data as $book => $chapters) {
59
            try {
60
                $bookId = $this->getBookIdByName($book);
61
                if (!$bookId) {
62
                    $bookId = $this->bookRepository->insert([BookRepository::COLUMN_BOOK_ABREV => $book])->getPrimary();
63
                }
64
            } catch (\Exception $exception) {
65
                \Tracy\Debugger::log('Nepodařila se uložit nová kniha. Chyba: ' . $exception->getMessage(), 'transport-facade');
66
                return FALSE;
67
            }
68
            foreach ($chapters as $chapter => $surfaces) {
69
                try {
70
                    $transliterationId = $this->getTransliterationIdCurrentBookChapter($bookId, trim(explode(" ", $chapter)[0]));
71
                    if (!$transliterationId) {
72
                        $chapterReg = explode(" ", $chapter);
73
                        if (isset($chapterReg[1])) {
74
                            $chapterReg[1] = str_replace(array('(', ')'), '', $chapterReg[1]);
75
                            $this->transliterationRepository->insert([
76
                                TransliterationRepository::COLUMN_BOOK_ID => $bookId,
77
                                TransliterationRepository::COLUMN_CHAPTER => $chapterReg[0],
78
                                TransliterationRepository::COLUMN_REG_NO => $chapterReg[1]
79
                            ]);
80
                            $transliterationId = $this->context->getInsertId(TransliterationRepository::COLUMN_ID);
81
                        } else {
82
                            $this->transliterationRepository->insert([
83
                                TransliterationRepository::COLUMN_BOOK_ID => $bookId,
84
                                TransliterationRepository::COLUMN_CHAPTER => $chapterReg[0]
85
                            ]);
86
                            $transliterationId = $this->context->getInsertId(TransliterationRepository::COLUMN_ID);
87
                        }
88
                    }
89
                } catch (\Exception $exception) {
90
                    \Tracy\Debugger::log('Nepodařila se uložit nová transliterace. Chyba: ' . $exception->getMessage(), 'transport-facade');
91
                    return FALSE;
92
                }
93
                foreach ($surfaces as $surface => $values) {
94
                    try {
95
                        $surfaceId = $this->getSurfaceIdByCurrentTransSurfType($transliterationId, $surface);
96
                        if (!$surfaceId) {
97
                            $surfaceId = $this->surfaceRepository->insert([
98
                                SurfaceRepository::COLUMN_TRANSLITERATION_ID => $transliterationId,
99
                                SurfaceRepository::COLUMN_SURFACE_TYPE_ID => $surface,
100
                                SurfaceRepository::COLUMN_OBJECT_TYPE_ID => 1
101
                            ])->getPrimary();
102
                        }
103
                    } catch (\Exception $exception) {
104
                        \Tracy\Debugger::log('Nepodařil se uložit nový surface. Chyba: ' . $exception->getMessage(), 'transport-facade');
105
                        return FALSE;
106
                    }
107

  
108
                    foreach ($values as $line) {
109
                        try {
110
                            $lineId = $this->getLineIdByCurrentSurfLineNum($surfaceId, (explode(' ', $line)[0]));
111
                            if (!$lineId) {
112
                                $lineId = $this->lineRepository->insert([
113
                                    LineRepository::COLUMN_SURFACE_ID => $surfaceId,
114
                                    LineRepository::COLUMN_LINE_NUMBER => (explode(' ', $line)[0]),
115
                                    LineRepository::COLUMN_TRANSLITERATION => substr(strchr($line, " "), 1),
116
                                ])->{LineRepository::COLUMN_ID};
117
                            } else {
118
                                $this->lineRepository->fetchById($lineId)->update([
119
                                    LineRepository::COLUMN_TRANSLITERATION => substr(strchr($line, " "), 1)
120
                                ]);
121
                            }
122
                        } catch (\Exception $exception) {
123
                            \Tracy\Debugger::log('Nepodařil se uložit nová řádka (line) transliterace. Chyba: ' . $exception->getMessage(), 'transport-facade');
124
                            return FALSE;
125
                        }
126
                    }
127
                }
128
            }
129
        }
130
        return TRUE;
131
    }
132

  
133

  
134
    /**
135
     * Vrací id knihy podle jména zkratky
136
     * @param $bookName
137
     * @return bool|mixed|ActiveRow
138
     */
139
    public
140
    function getBookIdByName(string $bookName)
141
    {
142
        $book = $this->bookRepository->getBookByBookAbbrev($bookName)->fetch();
143
        if (!empty($book)) {
144
            return $book->getPrimary();
145
        } else {
146
            return false;
147
        }
148
    }
149

  
150

  
151
    private
152
    function getTransliterationIdCurrentBookChapter(int $bookId, string $chapterName)
153
    {
154
        $transliteration = $this->transliterationRepository->getTransliterationByChapterNameAndBookId($bookId, $chapterName)->fetch();
155
        if (!empty($transliteration)) {
156
            return $transliteration->getPrimary();
157
        } else {
158
            return false;
159
        }
160
    }
161

  
162
    private function getSurfaceIdByCurrentTransSurfType(int $transliterationId, int $surfaceId)
163
    {
164
        $surface = $this->surfaceRepository->getSurfaceByTransliterationIdAndSurfaceTypeId($transliterationId, $surfaceId)->fetch();
165

  
166
        if (!empty($surface)) {
167
            return $surface->getPrimary();
168
        } else {
169
            return false;
170
        }
171
    }
172

  
173
    private function getLineIdByCurrentSurfLineNum(int $surfaceId, $lineNum)
174
    {
175
        $line = $this->lineRepository->getLineBySurfaceIdAndLineNumber($surfaceId, $lineNum)->fetch();
176
        if (!empty($line)) {
177
            return $line->{LineRepository::COLUMN_ID};
178
        } else {
179
            return false;
180
        }
181
    }
182
}
app/model/repository/BookRepository.php
38 38
        return $this->findAll()->where(self::COLUMN_BOOK_ABREV . ' LIKE', '%' . $bookName . '%');
39 39
    }
40 40

  
41
    /**
42
     * Vrací pouze jednu knihu podle book_abrev jelikož jsou unique
43
     * @param string $bookName
44
     * @return \Nette\Database\Table\Selection
45
     */
46
    public function getBookByBookAbbrev(string $bookName){
47
        return $this->findBy([self::COLUMN_BOOK_ABREV => $bookName]);
48
    }
49

  
41 50
    /**
42 51
     * Vrátí všechny abbrev
43 52
     *
app/model/repository/LineRepository.php
97 97
        return $this->findBy([self::COLUMN_ID => $lineIds])->delete();
98 98
    }
99 99

  
100
    public function getLineBySurfaceIdAndLineNumber(int $surfaceId, $lineNum)
101
    {
102
        return $this->findBy([self::COLUMN_SURFACE_ID => $surfaceId, self::COLUMN_LINE_NUMBER => $lineNum]);
103
    }
104

  
100 105
}
app/model/repository/SurfaceRepository.php
40 40
            ]
41 41
        )->fetch();
42 42
    }
43

  
44
    public function getSurfaceByTransliterationIdAndSurfaceTypeId(int $transliterationId, int $surfaceId)
45
    {
46
        return $this->findBy([self::COLUMN_TRANSLITERATION_ID => $transliterationId, self::COLUMN_SURFACE_TYPE_ID => $surfaceId]);
47
    }
43 48
}
app/model/repository/TransliterationRepository.php
212 212
                  WHERE t.id_transliteration = ?", $id
213 213
        )->fetch();
214 214
    }
215

  
216
    public function getTransliterationByChapterNameAndBookId(int $bookId, string $chapterName){
217
        return $this->findBy([self::COLUMN_BOOK_ID => $bookId, self::COLUMN_CHAPTER => $chapterName]);
218
    }
215 219
}
app/utils/TextParser.php
5 5

  
6 6
class TextParser
7 7
{
8
    public $textFile;
8
    private $textFile;
9 9
    private $objectTypes;
10 10
    private $surfaceTypes;
11 11

  
......
14 14
        $this->textFile = $file;
15 15
    }
16 16

  
17
    /** Rozparsuje importovaný text */
17 18
    public function parseText()
18 19
    {
19 20
        $array = explode("\n", file_get_contents($this->textFile));
20 21
        $array = array_map('trim', $array);
21 22

  
23
        $nextBook = true;
22 24
        $output = array();
23 25
        $currentBook = "";
24 26
        $currentChapter = "";
......
26 28

  
27 29
        //TODO kontrola a parsovani object types (tablet, envelope)
28 30
        foreach ($array as $value) {
29
            if ($value[0] == '|' && !is_numeric($value[1])) {
31
            Debugger::barDump($value);
32
            if (strlen($value)==0){
33
                $nextBook = true;
34
            }
35
            elseif ($value[0] == '|' && $nextBook) {
30 36
                $currentBook = substr($value, 1);
31 37
                $currentChapter = "";
32 38
                $currentSurface = $this->transformAbbrev("obverse");
39
                $nextBook = false;
33 40
            }
34
            elseif ($value[0] == '|' && is_numeric($value[1])){
35
                $currentChapter = substr($value, 1);
36
                $currentSurface = $this->transformAbbrev("obverse");
37
            }else{
41
            elseif ($value[0] == '|'){
42
                // TYPÍIIIIIČO ono to může být i tady... k posrání. Odděleno '-', jakože pro jistotu demence (OBTR => "15 (T.R.4020) - le.e.")
43
                $withRef = explode(" - ", substr($value, 1));
44
                if(isset($withRef[1])){
45
                    $currentChapter = trim(substr($value, 1, strripos($value, "-")-1));
46
                    $currentSurface = $this->transformAbbrev(trim($withRef[1]));
47
                }else{
48
                    $currentChapter = substr($value, 1);
49
                    $currentSurface = $this->transformAbbrev("obverse");
50
                }
51
            }
52
            else{
38 53
                if (strchr($value, '$')) {
39 54
                    $output[$currentBook][$currentChapter][$currentSurface][] = trim(substr($value,0,stripos($value,"&")));
40 55
                    $currentSurface = $this->transformAbbrev(substr(strchr($value, "&"),1, -1));
......
47 62
        return $output;
48 63
    }
49 64

  
50
    /** Nejvíc kontrola souboru*/
65
    /** Nejvíc kontrola souboru, kontroluje zda soubor existuje a zda aspoň začátek souboru vyhovuje formátu */
51 66
    public function isFileParsable()
52 67
    {
53 68
        if (file_exists($this->textFile)) {
......
68 83
        $this->surfaceTypes = $surfaces;
69 84
    }
70 85

  
86
    /** Funkce pro transformaci zkratek surfaceType na jejich příslušná idčka v db */
71 87
    private function transformAbbrev($abbrev){
72 88
        switch ($abbrev){
73 89
            case "rev.":
......
101 117
                return array_search("obverse", $this->surfaceTypes);
102 118
        }
103 119
    }
120

  
121
    public function getTextFile(){
122
        return $this->textFile;
123
    }
104 124
}
www/css/admin/style.css
103 103
    padding: 0 1rem;
104 104
}
105 105

  
106
li.nav-item .active{
106
li.nav-item .active {
107 107
    background-color: #003366;
108 108
    border-color: #003366;
109 109
    color: #FAFAFA;
110 110
}
111 111

  
112
.ul-alert{
112
.ul-alert {
113 113
    margin-bottom: 0;
114 114
}
115 115

  
116
.required{
116
.required {
117 117
    font-weight: bold;
118
}
119

  
120
.disabled {
121
    pointer-events: none;
122
    cursor: default;
118 123
}

Také k dispozici: Unified diff