From afbe82e9f4531ef40d8dcc7ae0500ad03d48c7d9 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Thu, 25 Feb 2021 00:12:45 +0100 Subject: [PATCH] changed the way how prefixes are added to urls instead at the end we adding a prefix before an extension, e.g: filename_(2).jpg --- winixd/core/misc.cpp | 57 ++++++++++++----- winixd/core/misc.h | 6 ++ winixd/models/item.cpp | 137 ++++++++++++++++++++++++++++++----------- winixd/models/item.h | 31 +++++----- 4 files changed, 165 insertions(+), 66 deletions(-) diff --git a/winixd/core/misc.cpp b/winixd/core/misc.cpp index 05107f0..95c6805 100644 --- a/winixd/core/misc.cpp +++ b/winixd/core/misc.cpp @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2008-2018, Tomasz Sowa + * Copyright (c) 2008-2021, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1161,30 +1161,55 @@ bool GetUTF8File(const std::wstring & file_path, std::wstring & content, bool cl } -// if there is not an extension it returns a pointer to the last '\0' character +// if there is no an extension it returns a pointer to the last '\0' character const wchar_t * GetFileExt(const wchar_t * name) { -size_t i, ilast; + const wchar_t * dot_ptr = nullptr; - // looking for the end of the name - for(i=0 ; name[i] != 0 ; ++i); + for( ; *name != 0 ; ++name) + { + if( *name == '.' ) + { + dot_ptr = name; + } + } - if( i == 0 ) - return name; // ops, the name is empty + return dot_ptr ? dot_ptr + 1 : name; +} - // remember the end of the string - ilast = i; - // looking for the last dot - for(--i ; i>0 && name[i] != '.' ; --i); +void PrepareNewFileName(const wchar_t * src, const wchar_t * postfix, std::wstring & res, bool clear_res) +{ + bool has_ext = false; + const wchar_t * ext = GetFileExt(src); - if( name[i] != '.' ) - return name + ilast; // ops, there is not a dot + if( clear_res ) + res.clear(); - // the extensions starts from i+1 - // and can be empty (if the last character is a dot) + size_t len = ext - src; -return name + i + 1; + if( len > 0 ) + { + if( *(ext-1) == '.' ) + { + len -= 1; + has_ext = true; + } + } + + res.append(src, len); + res.append(postfix); + + if( has_ext ) + res.append(1, '.'); + + res.append(ext); +} + + +void PrepareNewFileName(const std::wstring & src, const std::wstring & postfix, std::wstring & res, bool clear_res) +{ + return PrepareNewFileName(src.c_str(), postfix.c_str(), res, clear_res); } diff --git a/winixd/core/misc.h b/winixd/core/misc.h index f5a9e6f..df66b49 100644 --- a/winixd/core/misc.h +++ b/winixd/core/misc.h @@ -77,6 +77,7 @@ double Tod(const wchar_t * str); // if the buffer is too small it will be terminated at the beginning (empty string) // and the function returns false +// IMPROVEME now we can use Toa from Pikotools template bool Toa(unsigned long value, CharType * buffer, size_t buf_len, int base = 10) { @@ -663,6 +664,11 @@ bool GetUTF8File(const std::wstring & file_path, std::wstring & content, bool cl const wchar_t * GetFileExt(const wchar_t * name); + +void PrepareNewFileName(const wchar_t * src, const wchar_t * postfix, std::wstring & res, bool clear_res = true); +void PrepareNewFileName(const std::wstring & src, const std::wstring & postfix, std::wstring & res, bool clear_res = true); + + int SelectFileType(const wchar_t * file_name); int SelectFileType(const std::wstring & file_name); diff --git a/winixd/models/item.cpp b/winixd/models/item.cpp index f71662c..0adf8fc 100644 --- a/winixd/models/item.cpp +++ b/winixd/models/item.cpp @@ -33,6 +33,7 @@ */ #include "models/item.h" +#include "core/misc.h" #include "finder.h" @@ -60,7 +61,6 @@ void Item::map_fields() field(L"subject", subject); field(L"template", html_template); field(L"sort_index", sort_index); - //field(L"content_id", content_id); field(L"content_id", item_content, true, true, true); // may we should add a method setTypeFromInt(int t)? @@ -76,42 +76,73 @@ void Item::table_name(PT::TextStream & stream) void Item::before_insert() { - // IMPROVEME if prepare_status is false then update the 'url' with the 'id' - // add a method: update_url() - url_was_prepared_correctly = prepare_url(); } void Item::after_insert() { get_last_sequence(L"core.item_id_seq", id); - - if( !url_was_prepared_correctly ) - { - // update_url(); - // what about an error from update_url()? - } } +bool Item::insert(morm::ModelData * model_data, bool update_whole_tree) +{ + bool url_prepared_correctly = prepare_url(); + bool insert_status = morm::Model::insert(model_data, update_whole_tree); + + if( insert_status ) + { + if( !url_prepared_correctly ) + { + PT::Toa(id, url); + morm::Model::update(model_data, false); + } + } + + return insert_status; +} + + +bool Item::insert(morm::ModelData & model_data, bool update_whole_tree) +{ + return insert(&model_data, update_whole_tree); +} + + +bool Item::insert(bool update_whole_tree) +{ + return insert(nullptr, update_whole_tree); +} + + + +/* + * + * this can be done better + * instead of calculating if more than zero items are in a directory + * just get the one item (should be one in normal circumstances) + * and compare its 'id' with 'this.id' and if these ids are different + * then prepare a new url + * + * + */ bool Item::update(morm::ModelData * model_data, bool url_was_changed, bool update_whole_tree) { - bool prepare_url_status = true; + bool url_prepared_correctly = true; if( url_was_changed ) { - prepare_url_status = prepare_url(); + url_prepared_correctly = prepare_url(); } bool update_status = morm::Model::update(model_data, update_whole_tree); if( update_status ) { - if( !prepare_url_status ) + if( !url_prepared_correctly ) { - // IMPROVEME add update_url() method - // set 'url' to the same value as 'id' - //update_status = update_url(); + PT::Toa(id, url); + morm::Model::update(model_data, false); } } @@ -132,6 +163,41 @@ bool Item::update(bool url_was_changed, bool update_whole_tree) +bool Item::save(morm::ModelData * model_data, bool url_was_changed, bool save_whole_tree) +{ + bool url_prepared_correctly = true; + + if( save_mode == DO_INSERT_ON_SAVE || (save_mode == DO_UPDATE_ON_SAVE && url_was_changed) ) + { + url_prepared_correctly = prepare_url(); + } + + bool save_status = morm::Model::save(model_data, save_whole_tree); + + if( save_status ) + { + if( !url_prepared_correctly ) + { + PT::Toa(id, url); + morm::Model::save(model_data, false); + } + } + + return save_status; +} + +bool Item::save(morm::ModelData & model_data, bool url_was_changed, bool save_whole_tree) +{ + return save(&model_data, url_was_changed, save_whole_tree); +} + + +bool Item::save(bool url_was_changed, bool save_whole_tree) +{ + return save(nullptr, url_was_changed, save_whole_tree); +} + + void Item::Clear() @@ -143,11 +209,7 @@ void Item::Clear() subject.clear(); html_template.clear(); sort_index = 0; - content_id = -1; item_content.Clear(); - - // used only when inserting, not saved to the database - url_was_prepared_correctly = true; } @@ -167,32 +229,36 @@ long Item::calc_items_by_url(long parent_id, const std::wstring & url) } - +/* + * may we should check for '.' and '..' here too? + */ bool Item::prepare_url() { std::wstring temp_url; bool is_that_url; int index = 1; const int max_index = 99; -wchar_t appendix[20]; -size_t appendix_len = sizeof(appendix) / sizeof(wchar_t); - - appendix[0] = 0; +std::wstring postfix; // only root dir may not have the url if( parent_id != -1 && url.empty() ) - url = L"empty"; // IMPROVEME move me to locales + url = L"_"; do { - temp_url = url; - temp_url += appendix; + if( index > 1 ) + { + postfix = L"_("; + PT::Toa(index, postfix, false); + postfix += L")"; + } + + PrepareNewFileName(url, postfix, temp_url); long size = calc_items_by_url(parent_id, temp_url); if( size > 0 ) { - swprintf(appendix, appendix_len, L"_(%d)", ++index); is_that_url = true; } else @@ -200,6 +266,8 @@ size_t appendix_len = sizeof(appendix) / sizeof(wchar_t); url = temp_url; is_that_url = false; } + + index += 1; } while( is_that_url && index <= max_index ); @@ -207,7 +275,6 @@ return !is_that_url; } - void Item::do_migration(morm::ModelConnector * model_connector) { return; @@ -217,11 +284,11 @@ void Item::do_migration(morm::ModelConnector * model_connector) std::list list = finder.select().where().eq(L"type", static_cast(Item::dir)).eq(L"content_id", -1).get_list(); - for(Item & item : list) - { - item.item_content.set_save_mode(morm::Model::DO_INSERT_ON_SAVE); - item.save(); - } +// for(Item & item : list) +// { +// item.item_content.set_save_mode(morm::Model::DO_INSERT_ON_SAVE); +// item.save(); +// } } diff --git a/winixd/models/item.h b/winixd/models/item.h index 058e715..471f087 100644 --- a/winixd/models/item.h +++ b/winixd/models/item.h @@ -50,6 +50,12 @@ public: long size; + /* + * add an id of an item and compare it in 'update' method + * (in a case size==1) + * + */ + void map_fields() { field(L"size", size); @@ -109,12 +115,6 @@ public: */ int sort_index; - /* - * may not needed? - * the id is in the ItemContent object - */ - long content_id; - /* * */ @@ -139,19 +139,23 @@ public: bool prepare_url(); - /* - * CHECKME - * make sure update(...) methods from Model are not available - */ + + bool insert(morm::ModelData * model_data, bool update_whole_tree = true); + bool insert(morm::ModelData & model_data, bool update_whole_tree = true); + bool insert(bool update_whole_tree = true); + bool update(morm::ModelData * model_data, bool url_was_changed, bool update_whole_tree = true); bool update(morm::ModelData & model_data, bool url_was_changed, bool update_whole_tree = true); bool update(bool url_was_changed, bool update_whole_tree = true); - // IMPROVEME make the same for save() methods + + bool save(morm::ModelData * model_data, bool url_was_changed, bool save_whole_tree = true); + bool save(morm::ModelData & model_data, bool url_was_changed, bool save_whole_tree = true); + bool save(bool url_was_changed, bool save_whole_tree = true); /* * IMPROVEME - * when removing we should check whether the item_content.references is zero and them remove it + * when removing we should check whether the item_content.references is zero and then remove it * in other cases only decrement item_content.references * */ @@ -164,9 +168,6 @@ public: protected: - bool url_was_prepared_correctly; - - long calc_items_by_url(long parent_id, const std::wstring & url);