Skip to content

Commit

Permalink
Entry collection (#7)
Browse files Browse the repository at this point in the history
* Fixed search engine inside grf with GrfEntryCollection

closed #6
  • Loading branch information
carloshenrq authored Feb 27, 2019
1 parent bc0749e commit 5e381ca
Show file tree
Hide file tree
Showing 7 changed files with 319 additions and 23 deletions.
55 changes: 52 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ This is a lib to allow PHP to read and write GRF (Gravity Ragnarok Files).

## How i can colaborate?

Please! check our and if you can fix or add new features, you're welcome.
Please! check our issues and if you can fix or add new features, you're welcome.

Also, see if what you're about to change is in ours .
Also, see if what you're about to change is in ours pull requests.

## How to open a file to read?

Expand Down Expand Up @@ -50,6 +50,44 @@ foreach ($grf->getEntries() as $entry) {
$grf = null;
```

If you wanna search inside entries:

```
<?php
require_once 'php-grf/lib/autoload.php';
// Instance a reader/writer for your grf file
$grf = new GrfFile('php-grf/tests/test200.grf');
// Find all files in entries (including added)
// when uncompressed the size is more then 1000 bytes.
$search = $grf->getEntries()->where(function($entry) {
return $entry->getUnCompressedSize() > 1000;
});
// Dispose all resources used
$grf = null;
```

Know the full path inside grf the file is?

```
<?php
require_once 'php-grf/lib/autoload.php';
// Instance a reader/writer for your grf file
$grf = new GrfFile('php-grf/tests/test200.grf');
$entries = $grf->getEntries();
$entry = $entries['data\\0_Tex1.bmp'];
if ($entry === null) { // not found
}
// Dispose all resources used
$grf = null;
```

## How to open a grf file to write?

The same way you open to read, you can write. See:
Expand All @@ -72,10 +110,21 @@ Large grf files may take some minutes to finish.

## How to create a grf file to write?

Look here how to create a new grf file:

```
Soon...
require_once 'php-grf/lib/autoload.php';
// Creates a new grf file with no files inside
$grf = GrfFile::create('your-grf-file.grf');
// Dispose all resources used
$grf->close(); // Auto save when closed
$grf = null;
```

To add files, just check the section above...

## Install

To install, you only need use composer require to use.
Expand Down
192 changes: 192 additions & 0 deletions lib/GrfEntryCollection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
<?php
/**
* MIT License
*
* Copyright (c) 2019 Carlos Henrique
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

class GrfEntryCollection implements IteratorAggregate, Countable, ArrayAccess
{
/**
* All grf entries.
*
* @return array
*/
private $entries;

/**
* Starts the constructor for grf entries
*
* @param array $entries All start entries
*
* @return void
*/
public function __construct($entries = [])
{
$this->entries = $entries;
}

/**
* Removes the offset inside collection
*
* @param mixed $offset Index inside collection
*
* @return void
*/
public function offsetUnset($offset)
{
if ($this->offsetExists($offset) === false)
return false;

unset($this->entries[$offset]);
}

/**
* Sets the object inside collections by offset
*
* @param mixed $offset Index inside collection
* @param mixed $value Value to make key-value collection
*
* @return void
*/
public function offsetSet($offset, $value)
{
if (empty($offset))
$offset = $value->getFilename();

$this->entries[$offset] = $value;
}

/**
* Gets the object inside collections by offset
*
* @param mixed $offset Index inside collection
*
* @return GrfEntry
*/
public function offsetGet($offset)
{
if ($this->offsetExists($offset) === false)
return null;

return $this->entries[$offset];
}

/**
* Verify if the offset exists inside collection
*
* @param mixed $offset Index inside collection
*
* @return bool
*/
public function offsetExists($offset)
{
return isset($this->entries[$offset]);
}

/**
* Gets the array iterator for entries.
*
* @return ArrayIterator
*/
public function getIterator()
{
return new ArrayIterator($this->entries);
}

/**
* Counts how many entries this collection have
*
* @return int
*/
public function count()
{
return count($this->entries);
}

/**
* Applies a search inside this collection
*
* @param callable $callback Function comparator
*
* @return GrfEntryCollection
*/
public function where($callback)
{
// No callable function? Then, no result. =]
if (is_callable($callback) === false)
return null;

$tmpEntries = [];
foreach ($this as $entry) {
if ($callback($entry) === true)
$tmpEntries[$entry->getFilename()] = $entry;
}

return new GrfEntryCollection($tmpEntries);
}

/**
* Gets the first GrfEntryHeader in the collection
*
* @param callable $callback Function comparator
*
* @return GrfEntryHeader
*/
public function first($callback = null)
{
$collection = $this;

if ($callback !== null && is_callable($callback))
$collection = $this->where($callback);

$tmpArray = $collection->getArrayCopy();
return array_shift($tmpArray);
}

/**
* Gets the last entry on collection
*
* @param callable $callback Function comparer
*
* @return GrfEntryHeader
*/
public function last($callback = null)
{
$collection = $this;

if ($callback !== null && is_callable($callback))
$collection = $this->where($callback);

$tmpArray = $collection->getArrayCopy();
return array_pop($tmpArray);
}

/**
* Gets an copy from array entries
*
* @return array
*/
public function getArrayCopy()
{
return $this->entries;
}
}
10 changes: 10 additions & 0 deletions lib/GrfEntryHeader.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,16 @@ public function __construct($name, BufferReader $buffer = null, GrfFile $grf, $f
$this->offset = -1;
}

/**
* Remove the file from entries collections
*
* @return void
*/
public function delete()
{
$this->getGrf()->delete($this->getFilename());
}

/**
* Gets the hash for the file
*
Expand Down
15 changes: 13 additions & 2 deletions lib/GrfFile.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ private function load($fileName, $readFileTables)
$this->fileName = $fileName;
$this->ptrFile = fopen($this->fileName, 'rb+');

$this->entries = new ArrayObject();
$this->entries = new GrfEntryCollection();

// Reads this grf header
$this->readHeader();
Expand Down Expand Up @@ -298,6 +298,18 @@ public function addBuffer($name, $buffer)
$this->isNeedingSave = true;
}

/**
* Delete a file inside grf entries
*
* @param string $name name of file
*
* @return void
*/
public function delete($name)
{
unset($this->entries[$name]);
}

/**
* Decompress the data
*
Expand Down Expand Up @@ -374,7 +386,6 @@ public function save()
fwrite($fpTmp, $buf->flush());
fflush($fpTmp);

$fileTableArray = new ArrayObject();
$entryOffset = 0;
foreach ($entries as $entry) {
fseek($fpTmp, $entryOffset + self::GRF_HEADER_SIZE, SEEK_SET);
Expand Down
2 changes: 1 addition & 1 deletion tests/GrfFileNotReadTableTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public function testGetEntries()
{
$entries = $this->grf->getEntries();

$this->assertInstanceOf('ArrayObject', $entries);
$this->assertInstanceOf('GrfEntryCollection', $entries);
$this->assertEquals(0, $entries->count());
}

Expand Down
41 changes: 40 additions & 1 deletion tests/GrfFileTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,52 @@ public function setUp()
$this->grf = new GrfFile('tests/test200.grf');
}

public function testEntriesCollection()
{
$entries = $this->grf->getEntries();

$this->assertNull($entries['data\\xampso.xml']);
unset($entries['data\\xampso.xml']);
$this->assertNull($entries['data\\xampso.xml']);

$entry = $entries->first();
$name = $entry->getFilename();
$this->assertNotNull($entries[$name]);
$entry->delete();
$this->assertNull($entries[$name]);

$nullWhere = $entries->where('xamspoTest');
$this->assertNull($nullWhere);

$otherEntries = $entries->where(function($e) use ($name) {
return strcmp($e->getFilename(), $name) !== 0;
});

$this->assertEquals(8, $otherEntries->count());

$first = $entries->first(function($e) use ($name) {
return strcmp($e->getFilename(), $name) !== 0;
});

$this->assertInstanceOf('GrfEntryHeader', $first);

$last = $entries->last();
$this->assertInstanceOf('GrfEntryHeader', $last);

$last = $entries->last(function($e) use ($name) {
return strcmp($e->getFilename(), $name) !== 0;
});

$this->assertInstanceOf('GrfEntryHeader', $last);
}

public function testEntriesCount()
{
$entries = $this->grf->getEntries();

$this->assertEquals(9, $entries->count());

$grfEntry = $entries[0];
$grfEntry = $entries->first();
$this->assertInstanceOf('GrfEntryHeader', $grfEntry);

$this->assertEquals('data\\0_Tex1.bmp', $grfEntry->getFilename());
Expand Down
Loading

0 comments on commit 5e381ca

Please sign in to comment.