Skip to content

Commit

Permalink
Merge pull request #1 from dealnews/next
Browse files Browse the repository at this point in the history
Add ColumnMapper
  • Loading branch information
brianlmoon authored Feb 27, 2024
2 parents 9acf932 + d08cc2e commit e549043
Show file tree
Hide file tree
Showing 10 changed files with 371 additions and 43 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: Testing DealNews\GetConfig
name: Testing DealNews\DB

on: [push, pull_request]
on: [push]

jobs:
test:
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
},
"require": {
"php": "^8.0",
"dealnews/data-mapper": "^3.0",
"dealnews/data-mapper": "^3.1.1",
"dealnews/get-config": "^2.0"
},
"require-dev": {
Expand Down
131 changes: 104 additions & 27 deletions src/AbstractMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,16 @@ public function delete($id): bool {
protected function loadRelations(object $object): object {
foreach ($this::MAPPING as $property => $mapping) {
if (!empty($mapping['mapper'])) {
if (!empty($mapping['type']) && $mapping['type'] == 'lookup') {
if (
is_a($mapping['mapper'], ColumnMapper::class, true) ||
is_subclass_of($mapping['mapper'], ColumnMapper::class, true)
) {
$object = $this->loadColumnMapper(
$object,
$property,
$mapping
);
} elseif (!empty($mapping['type']) && $mapping['type'] == 'lookup') {
$object = $this->loadLookupObjects(
$object,
$property,
Expand Down Expand Up @@ -285,7 +294,8 @@ protected function loadRelatedObjects(object $object, string $property, array $m
$mapper = new $mapping['mapper']();
$objects = $mapper->find(
[
$mapping['foreign_column'] => $object->{$this::PRIMARY_KEY},
// @phan-suppress-next-line PhanTypeArraySuspicious, PhanTypeInvalidDimOffset
$mapping['foreign_column'] => $this->getValue($object, $this::PRIMARY_KEY, $this::MAPPING[$this::PRIMARY_KEY]),
]
);

Expand Down Expand Up @@ -315,7 +325,8 @@ protected function loadLookupObjects(object $object, string $property, array $ma
$rows = $this->crud->read(
$mapping['table'],
[
$mapping['foreign_column'] => $object->{$this::PRIMARY_KEY},
// @phan-suppress-next-line PhanTypeArraySuspicious, PhanTypeInvalidDimOffset
$mapping['foreign_column'] => $this->getValue($object, $this::PRIMARY_KEY, $this::MAPPING[$this::PRIMARY_KEY]),
]
);

Expand All @@ -336,46 +347,65 @@ protected function loadLookupObjects(object $object, string $property, array $ma
}

/**
* Saves relations
* Loads a column mapper.
*
* @param object $object Object containing the relations
* @param object $object The object
* @param string $property The property
* @param array $mapping The mapping
*
* @return object
* @return object
*/
protected function saveRelations(object $object): object {
foreach ($this::MAPPING as $property => $mapping) {
if (!empty($mapping['mapper'])) {
$object = $this->saveRelationalObjects($object, $property, $mapping);
protected function loadColumnMapper(object $object, string $property, array $mapping): object {
$mapper = new ($mapping['mapper'])(
$mapping['table'],
$mapping['primary_key'],
$mapping['foreign_column'],
$mapping['column'],
$this->crud
);

if (!empty($mapping['type'])) {
if ($mapping['type'] == 'lookup') {
$object = $this->saveLookupRelations($object, $property, $mapping);
}
}
}
}
// @phan-suppress-next-line PhanTypeArraySuspicious, PhanTypeInvalidDimOffset
$data = $mapper->load($this->getValue($object, $this::PRIMARY_KEY, $this::MAPPING[$this::PRIMARY_KEY]));

$this->setValue(
$object,
$property,
[$property => $data],
$mapping
);

return $object;
}

/**
* Builds a data array for insertion into the database using the object
* properties. This can be overridden by a child class when more complex
* work needs to be done.
* Saves relations
*
* @param object $object
* @param object $object Object containing the relations
*
* @return array
* @return object
*/
protected function getData($object): array {
$data = [];
protected function saveRelations(object $object): object {
foreach ($this::MAPPING as $property => $mapping) {
if (empty($mapping['mapper'])) {
$data[$property] = $this->getValue($object, $property, $mapping);
if (!empty($mapping['mapper'])) {

if (
is_a($mapping['mapper'], ColumnMapper::class, true) ||
is_subclass_of($mapping['mapper'], ColumnMapper::class, true)
) {
$object = $this->saveColumnMapper($object, $property, $mapping);
} else {
$object = $this->saveRelationalObjects($object, $property, $mapping);

if (!empty($mapping['type'])) {
if ($mapping['type'] == 'lookup') {
$object = $this->saveLookupRelations($object, $property, $mapping);
}
}
}
}
}

return $data;
return $object;
}

/**
Expand Down Expand Up @@ -489,6 +519,53 @@ protected function saveRelationalObjects(object $object, string $property, array
return $object;
}

protected function saveColumnMapper(object $object, string $property, array $mapping): object {
$mapper = new ($mapping['mapper'])(
$mapping['table'],
$mapping['primary_key'],
$mapping['foreign_column'],
$mapping['column'],
$this->crud
);

$data = $this->getValue($object, $property, $mapping);

$data = $mapper->save(
// @phan-suppress-next-line PhanTypeArraySuspicious, PhanTypeInvalidDimOffset
$this->getValue($object, $this::PRIMARY_KEY, $this::MAPPING[$this::PRIMARY_KEY]),
$data
);

$this->setValue(
$object,
$property,
[$property => $data],
$mapping
);

return $object;
}

/**
* Builds a data array for insertion into the database using the object
* properties. This can be overridden by a child class when more complex
* work needs to be done.
*
* @param object $object
*
* @return array
*/
protected function getData($object): array {
$data = [];
foreach ($this::MAPPING as $property => $mapping) {
if (empty($mapping['mapper'])) {
$data[$property] = $this->getValue($object, $property, $mapping);
}
}

return $data;
}

/**
* Returns the "where" data to use when updating a row
*
Expand Down
172 changes: 172 additions & 0 deletions src/ColumnMapper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
<?php

namespace DealNews\DB;

/**
* Loads/saves a single column to/from an external table into an array
*
* @author Brian Moon <[email protected]>
* @copyright 1997-Present DealNews.com, Inc
* @package DealNews\DB
*/
class ColumnMapper {

/**
* CRUD PDO helper object
* @var \DealNews\DB\CRUD
*/
protected CRUD $crud;

/**
* The table with the values
*/
protected string $table = '';

/**
* The primary key for the table
*/
protected string $primary_key = '';

/**
* The column that has the foreign object pk in it
*/
protected string $foreign_column = '';

/**
* The column we want to return in the array
*/
protected string $column = '';


/**
* Constructs a new instance.
*
* @param string $table The table
* @param string $primary_key The primary key
* @param string $foreign_column The foreign column
* @param string $column The column
* @param CRUD $crud The crud
*/
public function __construct(
string $table,
string $primary_key,
string $foreign_column,
string $column,
CRUD $crud
) {

$this->table = $table;
$this->primary_key = $primary_key;
$this->foreign_column = $foreign_column;
$this->column = $column;
$this->crud = $crud;
}

/**
* Loads the data from the database
*
* @param int|string $id Primay key id of the object to look up
*
* @return array
*/
public function load(int|string $id): array {
$data = [];

$rows = $this->crud->read(
$this->table,
[
$this->foreign_column => $id,
],
order: $this->column
);

foreach ($rows as $row) {
$data[] = $row[$this->column];
}

return $data;
}

/**
* Saves the data
*
* @param int|string $id Primay key id of the object to look up
* @param array $data Values to save
*
* @return array
*/
public function save(int|string $id, array $data): array {
$success = true;

$already_in_transaction = $this->crud->pdo->inTransaction();

if (!$already_in_transaction) {
$this->crud->pdo->beginTransaction();
}

try {

$existing = $this->crud->read(
$this->table,
[
$this->foreign_column => $id,
]
);

foreach ($data as $dk => $value) {
foreach ($existing as $ek => $row) {
if ($row[$this->column] == $value) {
unset($data[$dk], $existing[$ek]);

break;
}
}
}

foreach ($data as $value) {
$success = $this->crud->create(
$this->table,
[
$this->column => $value,
$this->foreign_column => $id,
]
);
if (!$success) {
break;
}
}

if ($success) {
foreach ($existing as $ex) {
$success = $this->crud->delete(
$this->table,
[
$this->primary_key => $ex[$this->primary_key],
]
);
if (!$success) {
break;
}
}
}

} catch (\PDOException $e) {
if (!$already_in_transaction) {
$this->crud->pdo->rollBack();
}
throw $e;
}

if (!$already_in_transaction) {
if ($success) {
$this->crud->pdo->commit();
} else {
$this->crud->pdo->rollBack();
}
}

$data = $this->load($id);

return $data;
}
}
Loading

0 comments on commit e549043

Please sign in to comment.