Skip to content

Commit

Permalink
Merge 3f05957 into 9996a76
Browse files Browse the repository at this point in the history
  • Loading branch information
christianlupus committed Nov 23, 2020
2 parents 9996a76 + 3f05957 commit 8e731e3
Show file tree
Hide file tree
Showing 25 changed files with 2,242 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .github/actions/run-tests/tests/test-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ else

echo 'Copying the app code changes'
echo 'This might cause trouble when dependencies have changed'
rsync -a /app/ apps/cookbook/ --exclude /.git --exclude /build --exclude /.github
rsync -a /app/ apps/cookbook/ --exclude /.git --exclude /build --exclude /.github --exclude /vendor

fi

Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ jobs:
- database: mysql
coreVersion: stable19
phpVersion: "7.2"
mayFail: true
- database: mysql
coreVersion: stable19
phpVersion: "7.3"
mayFail: false

# Test against master (optionally)
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
[#387](https://github.com/nextcloud/cookbook/pull/387) @TobiasMie
- PHP linter and style checker enabled
[#390](https://github.com/nextcloud/cookbook/pull/390) @christianlupus
- Database abstraction added for simpler access
[#407](https://github.com/nextcloud/cookbook/pull/407) @christianlupus

### Changed
- Switch of project ownership to neextcloud organization in GitHub
Expand Down
208 changes: 208 additions & 0 deletions documentation/uml/dbwrappers.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
@startuml

namespace OCA.Cookbook {

namespace Entity {

interface Entity {
+ persist() : void
+ remove() : void
+ reload() : void
}

interface RecipeEntity {
--
+ getId() : int
+ getName() : string
+ setName(string) : void
..
+ getCategory() : CategoryEntity
+ setCategory(CategoryEntity) : void
+ getKeywords() : array
+ addKeyword(KeywordEntity) : void
+ removeKeyword(KeywordEntity) : void
}

interface CategoryEntity {
--
+ getName() : string
+ setName(string) : void
..
+ getRecipes() : array
}

interface KeywordEntity {
--
+ getName() : string
+ setName(string) : void
..
+ getRecipes() : array
}


namespace impl {

abstract class AbstractEntity {
- bool persisted
+ isPersisted() : bool
+ abstract clone() : ImplEntity
+ abstract isSame(AbstractEntity) : bool
+ abstract equals(AbstractEntity) : bool
}

class RecipeEntityImpl {
#id
#name
#userId
# RecipeDbWrapper wrapper
# CategoryEntityImpl newCategory
# array newKeywords
# array removedKeywords
+ getNewCategory() : CategoryEntityImpl | null
+ getNewKeywords() : array
+ getRemovedKeywords() : array
}

class CategoryEntityImpl {
#name
# CategoryDbWrapper wrapper
}

class KeywordEntityImpl {
#name
# KeywordDbWrapper wrapper
}

class CategoryMappingEntity {
}

class KeywordMappingEntity {
}

RecipeEntityImpl --|> AbstractEntity
CategoryEntityImpl --|> AbstractEntity
KeywordEntityImpl --|> AbstractEntity

CategoryMappingEntity -|> AbstractEntity
AbstractEntity <|- KeywordMappingEntity

RecipeEntityImpl "1" *--x CategoryMappingEntity
RecipeEntityImpl "1" *--x KeywordMappingEntity
CategoryEntityImpl "1" *--x CategoryMappingEntity
KeywordEntityImpl "1" *--x KeywordMappingEntity

}

RecipeEntity <|.. OCA.Cookbook.Entity.impl.RecipeEntityImpl
CategoryEntity <|.. OCA.Cookbook.Entity.impl.CategoryEntityImpl
KeywordEntity <|.. OCA.Cookbook.Entity.impl.KeywordEntityImpl

Entity <|.. RecipeEntity
Entity <|.. CategoryEntity
Entity <|.. KeywordEntity

}

namespace Db {

abstract class AbstractDbWrapper<T extends OCA.Cookbook.Entity.impl.AbstractEntity> {
# IDbConnection db
- array cache
- bool cacheValid
--
+ abstract createEntity() : T
# abstract fetchDatabase() : array
+ getEntites() : array
# setCache(array) : void
+ getServiceLocator() : DbWrapperSerciveLocator
..
+ store(T) : void
# abstract storeNew(T) : void
# abstract update(T) : void
+ remove(T) : void
}
note right
Cache represents the current state
of the database tables as clones.
endnote

class RecipeDbWrapper {
' - array idMap
--
+ createEntity() : RecipeEntityImpl
+ store(RecipeEntityImpl) : void
# storeNew(RecipeEntityImpl) : void
# update(RecipeEntityImpl) : void
+ remove(RecipeEntityImpl) : void
..
/'+ addKeyword(RecipeEntityImpl, KeywordEntityImpl) : KeywordMappingEntity
+ setCategory(RecipeEntityImpl, CategoryEntityImpl) : CategoryMappingEntity'/
+ getCategory(RecipeEntityImpl) : CategoryEntityImpl
+ getKeywords(RecipeEntityImpl) : array
}
class CategoryDbWrapper {
--
+ createEntity() : CategoryEntityImpl
+ store(CategoryEntityImpl) : void
# storeNew(CategoryEntityImpl) : void
# update(CategoryEntityImpl) : void
+ remove(CategoryEntityImpl) : void
..
+ getRecipes(CategoryEntityImpl) : array
}
class KeywordDbWrapper {
--
+ createEntity() : KeywordEntityImpl
+ store(KeywordEntityImpl) : void
# storeNew(KeywordEntityImpl) : void
# update(KeywordEntityImpl) : void
+ remove(KeywordEntityImpl) : void
..
+ getRecipes(KeywordEntityImpl) : array
}

class CategoryMappingsDbWrapper {
+ createEntity() : CategoryMappingEntity
+ store(CategoryMappingEntity) : void
# storeNew(CategoryMappingEntity) : void
# update(CategoryMappingEntity) : void
+ remove(CategoryMappingEntity) : void
}

class KeywordMappingsDbWrapper {
+ createEntity() : KeywordMappingEntity
+ store(KeywordMappingEntity) : void
# storeNew(KeywordMappingEntity) : void
# update(KeywordMappingEntity) : void
+ remove(KeywordMappingEntity) : void
}

class DbWrapperSerciveLocator {
+ getRecipeDbWrapoper() : RecipeDbWrapper
+ getCategoryDbWrapper() : CategoryDbWrapper
+ getKeywordDbWrapper() : KeywordDbWrapper
+ getKeywordMappingDbWrapper() : KeywordMappingsDbWrapper
+ getCategoryMappingDbWrapper() : CategoryMappingsDbWrapper
}

AbstractDbWrapper <|-- RecipeDbWrapper
AbstractDbWrapper <|-- CategoryDbWrapper
AbstractDbWrapper <|-- KeywordDbWrapper

RecipeDbWrapper "1" o-- "1" DbWrapperSerciveLocator
CategoryDbWrapper "1" o-- "1" DbWrapperSerciveLocator
KeywordDbWrapper "1" o-- "1" DbWrapperSerciveLocator

CategoryMappingsDbWrapper "1" o- "1" DbWrapperSerciveLocator
DbWrapperSerciveLocator "1" -o "1" KeywordMappingsDbWrapper

AbstractDbWrapper <|--- CategoryMappingsDbWrapper
AbstractDbWrapper <|--- KeywordMappingsDbWrapper

DbWrapperSerciveLocator -[hidden]-> AbstractDbWrapper
}

}


@enduml
104 changes: 104 additions & 0 deletions lib/Db/AbstractDbWrapper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<?php

namespace OCA\Cookbook\Db;

use OCP\IDBConnection;

abstract class AbstractDbWrapper {

/**
* @var array
*/
private $cache;

/**
* @var bool
*/
private $initialized;

/**
* @var IDBConnection
*/
private $db;

/**
* @var DbWrapperServiceProvider
*/
protected $wrapperLocator;

public function __construct(IDBConnection $db) {
$this->initialized = false;
$this->db = $db;
}

/**
* Fetch all elements from the database.
*
* The concrete class must implemnt a way to fetch an array or elements represented by the database.
* @return array The (possible empty) array of entities in the database
*/
abstract protected function fetchDatabase(): array;

/**
* Fetch the entries in the database
*
* If the cache has already been fetched, the values in the cache are returned.
*
* @return array The entities in the database.
*/
public function getEntries(): array {
if (! $this->initialized) {
$this->reloadCache();
}

return $this->cache;
}

/**
* Reload the cache from the database.
*/
private function reloadCache(): void {
$this->cache = $this->fetchDatabase();
$this->initialized = true;
}

/**
* Invalidate the local cache.
*
* This will cause any access to the entities to refetch the whole cache.
*/
protected function invalidateCache(): void {
$this->initialized = false;
}

/**
* Set the cache to the given array.
*
* This function will repace the current cache by the given array.
* No further checks are carried out.
* Please be very careful to provide the most up to date data as present in the database.
* Otherwise you will see very strange effects.
*
* @param array $entities The new entities of the cache
*/
protected function setEntites(array $entities): void {
$this->cache = $entities;
$this->initialized = true;
}

/**
* Set the central service locator for registering of all wrappers
* @param DbWrapperServiceProvider $locator The locator for the registered wrappers
*/
public function setWrapperServiceLocator(DbWrapperServiceProvider $locator) {
$this->wrapperLocator = $locator;
}

/**
* Get the central service locator for registering of all wrappers
* @return DbWrapperServiceProvider The locator for the registered wrappers
*/
public function getWrapperServiceLocator() {
return $this->wrapperLocator;
}
}
Loading

0 comments on commit 8e731e3

Please sign in to comment.