├── .gitignore ├── README ├── lib ├── dd_idgen_IIdStore.php ├── dd_idgen_IIdGenerator.php ├── dd_idgen_AbstractIdGenerator.php ├── dd_idgen_IdGen.php ├── dd_idgen_RandomStringIdGenerator.php └── dd_idgen_DataSourceIdStore.php ├── tests ├── README └── DdIdgenBasicTest.php └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | .buildpath 2 | .project 3 | .settings 4 | ._* 5 | .*.swp 6 | build 7 | dist 8 | tests/*.sq3 9 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Dragonfly Development PHP ID Generation Library 2 | http://redmine.dflydev.com/projects/dd-idgen 3 | 4 | 5 | dd-idgen aims to provide a standard interface for generating unique 6 | string-based identifiers. 7 | -------------------------------------------------------------------------------- /lib/dd_idgen_IIdStore.php: -------------------------------------------------------------------------------- 1 | store($suggestion, $mob); } 14 | return $this->generateInternal($idStore, $mob); 15 | } 16 | 17 | /** 18 | * Generate and ID 19 | * 20 | * This is used internally by dd_idgen_AbstractIdGenerator and is what 21 | * subclasses of dd_idgen_AbstractIdGenerator should implement. 22 | * @param dd_idgen_IIdStore $idStore 23 | * @param string $mob 24 | */ 25 | abstract protected function generateInternal(dd_idgen_IIdStore $idStore, $mob = null); 26 | 27 | } -------------------------------------------------------------------------------- /lib/dd_idgen_IdGen.php: -------------------------------------------------------------------------------- 1 | idStore = $idStore; 34 | $this->idGenerator = $idGenerator; 35 | $this->mob = $mob; 36 | } 37 | 38 | /** 39 | * Generate a new identity 40 | * @param $suggestion 41 | */ 42 | public function generate($suggestion = null) { 43 | return $this->idGenerator->generate($this->idStore, $this->mob, $suggestion); 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010, Dragonfly Development Inc 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of Dragonfly Development Inc nor the names of its 13 | contributors may be used to endorse or promote products derived from 14 | this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | POSSIBILITY OF SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /lib/dd_idgen_RandomStringIdGenerator.php: -------------------------------------------------------------------------------- 1 | maxSize = $maxSize; 38 | $this->minSize = $minSize; 39 | 40 | $this->allowedCharacters = $allowedCharacters; 41 | 42 | } 43 | 44 | /** 45 | * (non-PHPdoc) 46 | * @see dd_idgen_AbstractIdGenerator::generateInternal() 47 | */ 48 | protected function generateInternal(dd_idgen_IIdStore $idStore, $mob = null) { 49 | $out = ''; 50 | $allowedMax = strlen($this->allowedCharacters) - 1; 51 | while ( strlen($out) < $this->maxSize ) { 52 | $nextChar = $this->allowedCharacters[rand(0, $allowedMax)]; 53 | $out .= $nextChar; 54 | if ( strlen($out) >= $this->minSize ) { 55 | $identity = $idStore->store($out, $mob); 56 | if ( $identity !== null ) return $identity; 57 | } 58 | } 59 | return null; 60 | } 61 | 62 | } -------------------------------------------------------------------------------- /lib/dd_idgen_DataSourceIdStore.php: -------------------------------------------------------------------------------- 1 | dataSource = $dataSource; 40 | $this->tableName = $tableName; 41 | $this->identityColumnName = $identityColumnName; 42 | $this->mobColumnName = $mobColumnName; 43 | } 44 | 45 | /** 46 | * (non-PHPdoc) 47 | * @see dd_idgen_IIdStore::store() 48 | */ 49 | public function store($identity, $mob = null) { 50 | 51 | if ( $mob === null and $this->mobColumnName !== null ) { 52 | return null; 53 | } 54 | 55 | // We do some things with our PDO Data Source that might be different 56 | // than how the caller might be wanting to deal with PDO. 57 | $originalPdoErrorMode = $this->dataSource->getAttribute(PDO::ATTR_ERRMODE); 58 | if ( $originalPdoErrorMode != PDO::ERRMODE_EXCEPTION ) { 59 | $this->dataSource->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 60 | } 61 | 62 | try { 63 | 64 | // 65 | // Insert into the database blindly. 66 | // 67 | // Relies on datbase driver to throw exception on duplicate key 68 | // errors. Relies on user to have designe database to have unique 69 | // constraint on id + mob columns. 70 | // 71 | 72 | $values = array($identity); 73 | $sql = null; 74 | 75 | if ( $mob === null ) { 76 | $sql = 'INSERT INTO ' . $this->tableName . ' (' . $this->identityColumnName . ') VALUES (?)'; 77 | } else { 78 | $sql = 'INSERT INTO ' . $this->tableName . ' (' . $this->identityColumnName . ', ' . $this->mobColumnName . ') VALUES (?, ?)'; 79 | $values[] = $mob; 80 | } 81 | 82 | $sth = $this->dataSource->prepare($sql); 83 | $sth->execute($values); 84 | 85 | } catch (Exception $e) { 86 | // Any exception is a failure. Change the identity to null as 87 | // $identity is what is going to be returned to our caller. 88 | $identity = null; 89 | } 90 | 91 | if ( $originalPdoErrorMode != PDO::ERRMODE_EXCEPTION ) { 92 | $this->dataSource->setAttribute(PDO::ATTR_ERRMODE, $originalPdoErrorMode); 93 | } 94 | 95 | return $identity; 96 | 97 | } 98 | 99 | } -------------------------------------------------------------------------------- /tests/DdIdgenBasicTest.php: -------------------------------------------------------------------------------- 1 | dataSource(true); 17 | 18 | require_once('dd_idgen_DataSourceIdStore.php'); 19 | require_once('dd_idgen_RandomStringIdGenerator.php'); 20 | require_once('dd_idgen_IdGen.php'); 21 | 22 | // Test with mob support. 23 | 24 | $idStore = new dd_idgen_DataSourceIdStore($dataSource, 'identities', 'identity', 'mob'); 25 | $idGenerator = new dd_idgen_RandomStringIdGenerator(5); 26 | $idGen = new dd_idgen_IdGen($idStore, $idGenerator, 'dummy-testing'); 27 | 28 | $id = $idGen->generate(); 29 | $this->assertTrue(null !== $id); 30 | 31 | $id = $idGen->generate('fooBar'); 32 | $this->assertEquals('fooBar', $id); 33 | 34 | $id = $idGen->generate('fooBar'); 35 | $this->assertEquals(null, $id); 36 | 37 | $id = $idGen->generate('fooBarBaz'); 38 | $this->assertEquals(null, $id); 39 | 40 | $id = $idGen->generate('fooBarBazWoot'); 41 | $this->assertEquals('fooBarBazWoot', $id); 42 | 43 | // Test w/o mob support (from idgen) 44 | 45 | $idGen = new dd_idgen_IdGen($idStore, $idGenerator); 46 | 47 | // This test should fail since the Data Source ID Storage engine 48 | // does not allow for a NULL mob when a mob column name is specified. 49 | // This is because some (all?) common SQL engines do not handle 50 | // NULL in UNIQUE constraints in a way that makes sense. 51 | $id = $idGen->generate(); 52 | $this->assertTrue(null === $id); 53 | 54 | // Test w/o mob support in table 55 | 56 | $idStore = new dd_idgen_DataSourceIdStore($dataSource, 'identitiesNoMob', 'identity'); 57 | $idGenerator = new dd_idgen_RandomStringIdGenerator(5); 58 | $idGen = new dd_idgen_IdGen($idStore, $idGenerator); 59 | 60 | $id = $idGen->generate(); 61 | $this->assertTrue(null !== $id); 62 | 63 | $id = $idGen->generate('fooBar'); 64 | $this->assertEquals('fooBar', $id); 65 | 66 | $id = $idGen->generate('fooBar'); 67 | $this->assertEquals(null, $id); 68 | 69 | $id = $idGen->generate('fooBarBaz'); 70 | $this->assertEquals(null, $id); 71 | 72 | $id = $idGen->generate('fooBarBazWoot'); 73 | $this->assertEquals('fooBarBazWoot', $id); 74 | 75 | } 76 | 77 | public function dataSource($initDb = false) { 78 | $dataSource = new PDO('sqlite:' . dirname(__FILE__) . '/DdIdgenBasicTest.sq3'); 79 | $dataSource->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 80 | if ( $initDb ) { 81 | $message = null; 82 | try { 83 | 84 | $dataSource->exec('DROP TABLE IF EXISTS identities'); 85 | $dataSource->exec(' 86 | CREATE TABLE identities ( 87 | identitiesId INTEGER PRIMARY KEY AUTOINCREMENT, 88 | identity TEXT, 89 | mob TEXT, 90 | UNIQUE(identity, mob) 91 | ) 92 | '); 93 | $dataSource->exec('INSERT INTO identities (identity, mob) VALUES ("fooBarBaz", "dummy-testing")'); 94 | $dataSource->exec('INSERT INTO identities (identity) VALUES ("fooBarBaz")'); 95 | 96 | $dataSource->exec('DROP TABLE IF EXISTS identitiesNoMob'); 97 | $dataSource->exec(' 98 | CREATE TABLE identitiesNoMob ( 99 | identitiesNoMobId INTEGER PRIMARY KEY AUTOINCREMENT, 100 | identity TEXT, 101 | UNIQUE(identity) 102 | ) 103 | '); 104 | $dataSource->exec('INSERT INTO identitiesNoMob (identity) VALUES ("fooBarBaz")'); 105 | 106 | } catch (Exception $e) { 107 | $message = $e->getMessage(); 108 | } 109 | $this->assertEquals(null, $message); 110 | $dataSource->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); 111 | } 112 | return $dataSource; 113 | } 114 | 115 | } 116 | ?> 117 | --------------------------------------------------------------------------------