Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
D
doctrine-dbal
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Tomáš Trávníček
doctrine-dbal
Commits
d4fec7cd
Unverified
Commit
d4fec7cd
authored
Sep 22, 2016
by
Guilherme Blanco
Committed by
Sergei Morozov
Nov 24, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Decouple unique index from unique constraint
parent
9dbec4b5
Changes
11
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
513 additions
and
180 deletions
+513
-180
AbstractPlatform.php
lib/Doctrine/DBAL/Platforms/AbstractPlatform.php
+21
-13
SqlitePlatform.php
lib/Doctrine/DBAL/Platforms/SqlitePlatform.php
+2
-1
AbstractSchemaManager.php
lib/Doctrine/DBAL/Schema/AbstractSchemaManager.php
+4
-1
Index.php
lib/Doctrine/DBAL/Schema/Index.php
+2
-0
SchemaException.php
lib/Doctrine/DBAL/Schema/SchemaException.php
+17
-1
Table.php
lib/Doctrine/DBAL/Schema/Table.php
+336
-160
UniqueConstraint.php
lib/Doctrine/DBAL/Schema/UniqueConstraint.php
+121
-0
ExceptionTest.php
tests/Doctrine/Tests/DBAL/Functional/ExceptionTest.php
+1
-0
SchemaManagerFunctionalTestCase.php
...BAL/Functional/Schema/SchemaManagerFunctionalTestCase.php
+5
-2
ComparatorTest.php
tests/Doctrine/Tests/DBAL/Schema/ComparatorTest.php
+2
-0
TableTest.php
tests/Doctrine/Tests/DBAL/Schema/TableTest.php
+2
-2
No files found.
lib/Doctrine/DBAL/Platforms/AbstractPlatform.php
View file @
d4fec7cd
...
@@ -23,6 +23,7 @@ use Doctrine\DBAL\Schema\Index;
...
@@ -23,6 +23,7 @@ use Doctrine\DBAL\Schema\Index;
use
Doctrine\DBAL\Schema\Sequence
;
use
Doctrine\DBAL\Schema\Sequence
;
use
Doctrine\DBAL\Schema\Table
;
use
Doctrine\DBAL\Schema\Table
;
use
Doctrine\DBAL\Schema\TableDiff
;
use
Doctrine\DBAL\Schema\TableDiff
;
use
Doctrine\DBAL\Schema\UniqueConstraint
;
use
Doctrine\DBAL\TransactionIsolationLevel
;
use
Doctrine\DBAL\TransactionIsolationLevel
;
use
Doctrine\DBAL\Types
;
use
Doctrine\DBAL\Types
;
use
Doctrine\DBAL\Types\Type
;
use
Doctrine\DBAL\Types\Type
;
...
@@ -1534,15 +1535,30 @@ abstract class AbstractPlatform
...
@@ -1534,15 +1535,30 @@ abstract class AbstractPlatform
$options
[
'indexes'
]
=
[];
$options
[
'indexes'
]
=
[];
$options
[
'primary'
]
=
[];
$options
[
'primary'
]
=
[];
if
((
$createFlags
&
self
::
CREATE_INDEXES
)
>
0
)
{
if
((
$createFlags
&
self
::
CREATE_INDEXES
)
>
0
)
{
foreach
(
$table
->
getIndexes
()
as
$index
)
{
foreach
(
$table
->
getIndexes
()
as
$index
)
{
/** @var $index Index */
/** @var $index Index */
if
(
$index
->
isPrimary
())
{
if
(
!
$index
->
isPrimary
())
{
$options
[
'primary'
]
=
$index
->
getQuotedColumns
(
$this
);
$options
[
'primary_index'
]
=
$index
;
}
else
{
$options
[
'indexes'
][
$index
->
getQuotedName
(
$this
)]
=
$index
;
$options
[
'indexes'
][
$index
->
getQuotedName
(
$this
)]
=
$index
;
continue
;
}
}
$options
[
'primary'
]
=
$index
->
getQuotedColumns
(
$this
);
$options
[
'primary_index'
]
=
$index
;
}
foreach
(
$table
->
getUniqueConstraints
()
as
$uniqueConstraint
)
{
/** @var UniqueConstraint $uniqueConstraint */
$options
[
'uniqueConstraints'
][
$uniqueConstraint
->
getQuotedName
(
$this
)]
=
$uniqueConstraint
;
}
}
if
((
$createFlags
&
self
::
CREATE_FOREIGNKEYS
)
>
0
)
{
$options
[
'foreignKeys'
]
=
[];
foreach
(
$table
->
getForeignKeys
()
as
$fkConstraint
)
{
$options
[
'foreignKeys'
][]
=
$fkConstraint
;
}
}
}
}
...
@@ -1551,7 +1567,6 @@ abstract class AbstractPlatform
...
@@ -1551,7 +1567,6 @@ abstract class AbstractPlatform
foreach
(
$table
->
getColumns
()
as
$column
)
{
foreach
(
$table
->
getColumns
()
as
$column
)
{
/** @var Column $column */
/** @var Column $column */
if
(
$this
->
_eventManager
!==
null
&&
$this
->
_eventManager
->
hasListeners
(
Events
::
onSchemaCreateTableColumn
))
{
if
(
$this
->
_eventManager
!==
null
&&
$this
->
_eventManager
->
hasListeners
(
Events
::
onSchemaCreateTableColumn
))
{
$eventArgs
=
new
SchemaCreateTableColumnEventArgs
(
$column
,
$table
,
$this
);
$eventArgs
=
new
SchemaCreateTableColumnEventArgs
(
$column
,
$table
,
$this
);
$this
->
_eventManager
->
dispatchEvent
(
Events
::
onSchemaCreateTableColumn
,
$eventArgs
);
$this
->
_eventManager
->
dispatchEvent
(
Events
::
onSchemaCreateTableColumn
,
$eventArgs
);
...
@@ -1579,13 +1594,6 @@ abstract class AbstractPlatform
...
@@ -1579,13 +1594,6 @@ abstract class AbstractPlatform
$columns
[
$columnData
[
'name'
]]
=
$columnData
;
$columns
[
$columnData
[
'name'
]]
=
$columnData
;
}
}
if
((
$createFlags
&
self
::
CREATE_FOREIGNKEYS
)
>
0
)
{
$options
[
'foreignKeys'
]
=
[];
foreach
(
$table
->
getForeignKeys
()
as
$fkConstraint
)
{
$options
[
'foreignKeys'
][]
=
$fkConstraint
;
}
}
if
(
$this
->
_eventManager
!==
null
&&
$this
->
_eventManager
->
hasListeners
(
Events
::
onSchemaCreateTable
))
{
if
(
$this
->
_eventManager
!==
null
&&
$this
->
_eventManager
->
hasListeners
(
Events
::
onSchemaCreateTable
))
{
$eventArgs
=
new
SchemaCreateTableEventArgs
(
$table
,
$columns
,
$options
,
$this
);
$eventArgs
=
new
SchemaCreateTableEventArgs
(
$table
,
$columns
,
$options
,
$this
);
$this
->
_eventManager
->
dispatchEvent
(
Events
::
onSchemaCreateTable
,
$eventArgs
);
$this
->
_eventManager
->
dispatchEvent
(
Events
::
onSchemaCreateTable
,
$eventArgs
);
...
...
lib/Doctrine/DBAL/Platforms/SqlitePlatform.php
View file @
d4fec7cd
...
@@ -893,10 +893,11 @@ class SqlitePlatform extends AbstractPlatform
...
@@ -893,10 +893,11 @@ class SqlitePlatform extends AbstractPlatform
$sql
=
[];
$sql
=
[];
$tableSql
=
[];
$tableSql
=
[];
if
(
!
$this
->
onSchemaAlterTable
(
$diff
,
$tableSql
))
{
if
(
!
$this
->
onSchemaAlterTable
(
$diff
,
$tableSql
))
{
$dataTable
=
new
Table
(
'__temp__'
.
$table
->
getName
());
$dataTable
=
new
Table
(
'__temp__'
.
$table
->
getName
());
$newTable
=
new
Table
(
$table
->
getQuotedName
(
$this
),
$columns
,
$this
->
getPrimaryIndexInAlteredTable
(
$diff
),
$this
->
getForeignKeysInAlteredTable
(
$diff
),
0
,
$table
->
getOptions
());
$newTable
=
new
Table
(
$table
->
getQuotedName
(
$this
),
$columns
,
$this
->
getPrimaryIndexInAlteredTable
(
$diff
),
[],
$this
->
getForeignKeysInAlteredTable
(
$diff
),
0
,
$table
->
getOptions
());
$newTable
->
addOption
(
'alter'
,
true
);
$newTable
->
addOption
(
'alter'
,
true
);
$sql
=
$this
->
getPreAlterTableIndexForeignKeySQL
(
$diff
);
$sql
=
$this
->
getPreAlterTableIndexForeignKeySQL
(
$diff
);
...
...
lib/Doctrine/DBAL/Schema/AbstractSchemaManager.php
View file @
d4fec7cd
...
@@ -263,12 +263,14 @@ abstract class AbstractSchemaManager
...
@@ -263,12 +263,14 @@ abstract class AbstractSchemaManager
{
{
$columns
=
$this
->
listTableColumns
(
$tableName
);
$columns
=
$this
->
listTableColumns
(
$tableName
);
$foreignKeys
=
[];
$foreignKeys
=
[];
if
(
$this
->
_platform
->
supportsForeignKeyConstraints
())
{
if
(
$this
->
_platform
->
supportsForeignKeyConstraints
())
{
$foreignKeys
=
$this
->
listTableForeignKeys
(
$tableName
);
$foreignKeys
=
$this
->
listTableForeignKeys
(
$tableName
);
}
}
$indexes
=
$this
->
listTableIndexes
(
$tableName
);
$indexes
=
$this
->
listTableIndexes
(
$tableName
);
return
new
Table
(
$tableName
,
$columns
,
$indexes
,
$foreignKeys
,
false
,
[]);
return
new
Table
(
$tableName
,
$columns
,
$indexes
,
[],
$foreignKeys
,
false
,
[]);
}
}
/**
/**
...
@@ -587,6 +589,7 @@ abstract class AbstractSchemaManager
...
@@ -587,6 +589,7 @@ abstract class AbstractSchemaManager
public
function
alterTable
(
TableDiff
$tableDiff
)
public
function
alterTable
(
TableDiff
$tableDiff
)
{
{
$queries
=
$this
->
_platform
->
getAlterTableSQL
(
$tableDiff
);
$queries
=
$this
->
_platform
->
getAlterTableSQL
(
$tableDiff
);
if
(
!
is_array
(
$queries
)
||
!
count
(
$queries
))
{
if
(
!
is_array
(
$queries
)
||
!
count
(
$queries
))
{
return
;
return
;
}
}
...
...
lib/Doctrine/DBAL/Schema/Index.php
View file @
d4fec7cd
...
@@ -57,6 +57,7 @@ class Index extends AbstractAsset implements Constraint
...
@@ -57,6 +57,7 @@ class Index extends AbstractAsset implements Constraint
$isUnique
=
$isUnique
||
$isPrimary
;
$isUnique
=
$isUnique
||
$isPrimary
;
$this
->
_setName
(
$indexName
);
$this
->
_setName
(
$indexName
);
$this
->
_isUnique
=
$isUnique
;
$this
->
_isUnique
=
$isUnique
;
$this
->
_isPrimary
=
$isPrimary
;
$this
->
_isPrimary
=
$isPrimary
;
$this
->
options
=
$options
;
$this
->
options
=
$options
;
...
@@ -64,6 +65,7 @@ class Index extends AbstractAsset implements Constraint
...
@@ -64,6 +65,7 @@ class Index extends AbstractAsset implements Constraint
foreach
(
$columns
as
$column
)
{
foreach
(
$columns
as
$column
)
{
$this
->
_addColumn
(
$column
);
$this
->
_addColumn
(
$column
);
}
}
foreach
(
$flags
as
$flag
)
{
foreach
(
$flags
as
$flag
)
{
$this
->
addFlag
(
$flag
);
$this
->
addFlag
(
$flag
);
}
}
...
...
lib/Doctrine/DBAL/Schema/SchemaException.php
View file @
d4fec7cd
...
@@ -18,7 +18,8 @@ class SchemaException extends DBALException
...
@@ -18,7 +18,8 @@ class SchemaException extends DBALException
public
const
SEQUENCE_ALREADY_EXISTS
=
80
;
public
const
SEQUENCE_ALREADY_EXISTS
=
80
;
public
const
INDEX_INVALID_NAME
=
90
;
public
const
INDEX_INVALID_NAME
=
90
;
public
const
FOREIGNKEY_DOESNT_EXIST
=
100
;
public
const
FOREIGNKEY_DOESNT_EXIST
=
100
;
public
const
NAMESPACE_ALREADY_EXISTS
=
110
;
public
const
CONSTRAINT_DOESNT_EXIST
=
110
;
public
const
NAMESPACE_ALREADY_EXISTS
=
120
;
/**
/**
* @param string $tableName
* @param string $tableName
...
@@ -142,6 +143,21 @@ class SchemaException extends DBALException
...
@@ -142,6 +143,21 @@ class SchemaException extends DBALException
return
new
self
(
"There exists no sequence with the name '"
.
$sequenceName
.
"'."
,
self
::
SEQUENCE_DOENST_EXIST
);
return
new
self
(
"There exists no sequence with the name '"
.
$sequenceName
.
"'."
,
self
::
SEQUENCE_DOENST_EXIST
);
}
}
/**
* @param string $constraintName
* @param string $table
*
* @return self
*/
public
static
function
uniqueConstraintDoesNotExist
(
$constraintName
,
$table
)
{
return
new
self
(
sprintf
(
'There exists no unique constraint with the name "%s" on table "%s".'
,
$constraintName
,
$table
),
self
::
CONSTRAINT_DOESNT_EXIST
);
}
/**
/**
* @param string $fkName
* @param string $fkName
* @param string $table
* @param string $table
...
...
lib/Doctrine/DBAL/Schema/Table.php
View file @
d4fec7cd
This diff is collapsed.
Click to expand it.
lib/Doctrine/DBAL/Schema/UniqueConstraint.php
0 → 100644
View file @
d4fec7cd
<?php
namespace
Doctrine\DBAL\Schema
;
use
Doctrine\DBAL\Platforms\AbstractPlatform
;
use
InvalidArgumentException
;
use
function
array_keys
;
use
function
array_map
;
use
function
is_string
;
use
function
strtolower
;
/**
* Class for a unique constraint.
*/
class
UniqueConstraint
extends
AbstractAsset
implements
Constraint
{
/**
* Asset identifier instances of the column names the unique constraint is associated with.
* array($columnName => Identifier)
*
* @var Identifier[]
*/
protected
$columns
=
[];
/**
* Platform specific options
*
* @var mixed[]
*/
private
$options
=
[];
/**
* @param string $indexName
* @param string[] $columns
* @param mixed[] $options
*/
public
function
__construct
(
$indexName
,
array
$columns
,
array
$options
=
[])
{
$this
->
_setName
(
$indexName
);
$this
->
options
=
$options
;
foreach
(
$columns
as
$column
)
{
$this
->
_addColumn
(
$column
);
}
}
/**
* @param string $column
*
* @return void
*
* @throws InvalidArgumentException
*/
protected
function
_addColumn
(
$column
)
{
if
(
!
is_string
(
$column
))
{
throw
new
InvalidArgumentException
(
'Expecting a string as Index Column'
);
}
$this
->
_columns
[
$column
]
=
new
Identifier
(
$column
);
}
/**
* {@inheritdoc}
*/
public
function
getColumns
()
{
return
array_keys
(
$this
->
_columns
);
}
/**
* {@inheritdoc}
*/
public
function
getQuotedColumns
(
AbstractPlatform
$platform
)
{
$columns
=
[];
foreach
(
$this
->
_columns
as
$column
)
{
$columns
[]
=
$column
->
getQuotedName
(
$platform
);
}
return
$columns
;
}
/**
* @return string[]
*/
public
function
getUnquotedColumns
()
{
return
array_map
([
$this
,
'trimQuotes'
],
$this
->
getColumns
());
}
/**
* @param string $name
*
* @return bool
*/
public
function
hasOption
(
$name
)
{
return
isset
(
$this
->
options
[
strtolower
(
$name
)]);
}
/**
* @param string $name
*
* @return mixed
*/
public
function
getOption
(
$name
)
{
return
$this
->
options
[
strtolower
(
$name
)];
}
/**
* @return mixed[]
*/
public
function
getOptions
()
{
return
$this
->
options
;
}
}
tests/Doctrine/Tests/DBAL/Functional/ExceptionTest.php
View file @
d4fec7cd
...
@@ -314,6 +314,7 @@ class ExceptionTest extends DbalFunctionalTestCase
...
@@ -314,6 +314,7 @@ class ExceptionTest extends DbalFunctionalTestCase
$table
->
addColumn
(
'id'
,
'integer'
);
$table
->
addColumn
(
'id'
,
'integer'
);
$this
->
expectException
(
$exceptionClass
);
$this
->
expectException
(
$exceptionClass
);
foreach
(
$schema
->
toSql
(
$conn
->
getDatabasePlatform
())
as
$sql
)
{
foreach
(
$schema
->
toSql
(
$conn
->
getDatabasePlatform
())
as
$sql
)
{
$conn
->
exec
(
$sql
);
$conn
->
exec
(
$sql
);
}
}
...
...
tests/Doctrine/Tests/DBAL/Functional/Schema/SchemaManagerFunctionalTestCase.php
View file @
d4fec7cd
...
@@ -976,7 +976,7 @@ class SchemaManagerFunctionalTestCase extends DbalFunctionalTestCase
...
@@ -976,7 +976,7 @@ class SchemaManagerFunctionalTestCase extends DbalFunctionalTestCase
protected
function
getTestTable
(
$name
,
$options
=
[])
protected
function
getTestTable
(
$name
,
$options
=
[])
{
{
$table
=
new
Table
(
$name
,
[],
[],
[],
false
,
$options
);
$table
=
new
Table
(
$name
,
[],
[],
[],
[],
false
,
$options
);
$table
->
setSchemaConfig
(
$this
->
schemaManager
->
createSchemaConfig
());
$table
->
setSchemaConfig
(
$this
->
schemaManager
->
createSchemaConfig
());
$table
->
addColumn
(
'id'
,
'integer'
,
[
'notnull'
=>
true
]);
$table
->
addColumn
(
'id'
,
'integer'
,
[
'notnull'
=>
true
]);
$table
->
setPrimaryKey
([
'id'
]);
$table
->
setPrimaryKey
([
'id'
]);
...
@@ -987,7 +987,7 @@ class SchemaManagerFunctionalTestCase extends DbalFunctionalTestCase
...
@@ -987,7 +987,7 @@ class SchemaManagerFunctionalTestCase extends DbalFunctionalTestCase
protected
function
getTestCompositeTable
(
$name
)
protected
function
getTestCompositeTable
(
$name
)
{
{
$table
=
new
Table
(
$name
,
[],
[],
[],
false
,
[]);
$table
=
new
Table
(
$name
,
[],
[],
[],
[],
false
,
[]);
$table
->
setSchemaConfig
(
$this
->
schemaManager
->
createSchemaConfig
());
$table
->
setSchemaConfig
(
$this
->
schemaManager
->
createSchemaConfig
());
$table
->
addColumn
(
'id'
,
'integer'
,
[
'notnull'
=>
true
]);
$table
->
addColumn
(
'id'
,
'integer'
,
[
'notnull'
=>
true
]);
$table
->
addColumn
(
'other_id'
,
'integer'
,
[
'notnull'
=>
true
]);
$table
->
addColumn
(
'other_id'
,
'integer'
,
[
'notnull'
=>
true
]);
...
@@ -999,14 +999,17 @@ class SchemaManagerFunctionalTestCase extends DbalFunctionalTestCase
...
@@ -999,14 +999,17 @@ class SchemaManagerFunctionalTestCase extends DbalFunctionalTestCase
protected
function
assertHasTable
(
$tables
,
$tableName
)
protected
function
assertHasTable
(
$tables
,
$tableName
)
{
{
$foundTable
=
false
;
$foundTable
=
false
;
foreach
(
$tables
as
$table
)
{
foreach
(
$tables
as
$table
)
{
self
::
assertInstanceOf
(
Table
::
class
,
$table
,
'No Table instance was found in tables array.'
);
self
::
assertInstanceOf
(
Table
::
class
,
$table
,
'No Table instance was found in tables array.'
);
if
(
strtolower
(
$table
->
getName
())
!==
'list_tables_test_new_name'
)
{
if
(
strtolower
(
$table
->
getName
())
!==
'list_tables_test_new_name'
)
{
continue
;
continue
;
}
}
$foundTable
=
true
;
$foundTable
=
true
;
}
}
self
::
assertTrue
(
$foundTable
,
'Could not find new table'
);
self
::
assertTrue
(
$foundTable
,
'Could not find new table'
);
}
}
...
...
tests/Doctrine/Tests/DBAL/Schema/ComparatorTest.php
View file @
d4fec7cd
...
@@ -1272,6 +1272,7 @@ class ComparatorTest extends TestCase
...
@@ -1272,6 +1272,7 @@ class ComparatorTest extends TestCase
'id_table1'
=>
new
Column
(
'id_table1'
,
Type
::
getType
(
'integer'
)),
'id_table1'
=>
new
Column
(
'id_table1'
,
Type
::
getType
(
'integer'
)),
],
],
[],
[],
[],
[
[
new
ForeignKeyConstraint
([
'id_table1'
],
'table1'
,
[
'id'
],
'fk_table2_table1'
),
new
ForeignKeyConstraint
([
'id_table1'
],
'table1'
,
[
'id'
],
'fk_table2_table1'
),
]
]
...
@@ -1285,6 +1286,7 @@ class ComparatorTest extends TestCase
...
@@ -1285,6 +1286,7 @@ class ComparatorTest extends TestCase
'id_table3'
=>
new
Column
(
'id_table3'
,
Type
::
getType
(
'integer'
)),
'id_table3'
=>
new
Column
(
'id_table3'
,
Type
::
getType
(
'integer'
)),
],
],
[],
[],
[],
[
[
new
ForeignKeyConstraint
([
'id_table3'
],
'table3'
,
[
'id'
],
'fk_table2_table3'
),
new
ForeignKeyConstraint
([
'id_table3'
],
'table3'
,
[
'id'
],
'fk_table2_table3'
),
]
]
...
...
tests/Doctrine/Tests/DBAL/Schema/TableTest.php
View file @
d4fec7cd
...
@@ -200,7 +200,7 @@ class TableTest extends DbalTestCase
...
@@ -200,7 +200,7 @@ class TableTest extends DbalTestCase
{
{
$constraint
=
new
ForeignKeyConstraint
([],
'foo'
,
[]);
$constraint
=
new
ForeignKeyConstraint
([],
'foo'
,
[]);
$tableA
=
new
Table
(
'foo'
,
[],
[],
[
$constraint
]);
$tableA
=
new
Table
(
'foo'
,
[],
[],
[
],
[
$constraint
]);
$constraints
=
$tableA
->
getForeignKeys
();
$constraints
=
$tableA
->
getForeignKeys
();
self
::
assertCount
(
1
,
$constraints
);
self
::
assertCount
(
1
,
$constraints
);
...
@@ -209,7 +209,7 @@ class TableTest extends DbalTestCase
...
@@ -209,7 +209,7 @@ class TableTest extends DbalTestCase
public
function
testOptions
()
public
function
testOptions
()
{
{
$table
=
new
Table
(
'foo'
,
[],
[],
[],
false
,
[
'foo'
=>
'bar'
]);
$table
=
new
Table
(
'foo'
,
[],
[],
[],
[],
false
,
[
'foo'
=>
'bar'
]);
self
::
assertTrue
(
$table
->
hasOption
(
'foo'
));
self
::
assertTrue
(
$table
->
hasOption
(
'foo'
));
self
::
assertEquals
(
'bar'
,
$table
->
getOption
(
'foo'
));
self
::
assertEquals
(
'bar'
,
$table
->
getOption
(
'foo'
));
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment